OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/sync/glue/sync_backend_host_core.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/files/file_util.h" | |
9 #include "base/location.h" | |
10 #include "base/metrics/histogram.h" | |
11 #include "base/single_thread_task_runner.h" | |
12 #include "components/data_use_measurement/core/data_use_user_data.h" | |
13 #include "components/invalidation/public/invalidation_util.h" | |
14 #include "components/invalidation/public/object_id_invalidation_map.h" | |
15 #include "components/sync_driver/glue/sync_backend_registrar.h" | |
16 #include "components/sync_driver/invalidation_adapter.h" | |
17 #include "components/sync_driver/local_device_info_provider_impl.h" | |
18 #include "sync/internal_api/public/events/protocol_event.h" | |
19 #include "sync/internal_api/public/http_post_provider_factory.h" | |
20 #include "sync/internal_api/public/internal_components_factory.h" | |
21 #include "sync/internal_api/public/sessions/commit_counters.h" | |
22 #include "sync/internal_api/public/sessions/status_counters.h" | |
23 #include "sync/internal_api/public/sessions/sync_session_snapshot.h" | |
24 #include "sync/internal_api/public/sessions/update_counters.h" | |
25 #include "sync/internal_api/public/sync_context_proxy.h" | |
26 #include "sync/internal_api/public/sync_manager.h" | |
27 #include "sync/internal_api/public/sync_manager_factory.h" | |
28 #include "url/gurl.h" | |
29 | |
30 // Helper macros to log with the syncer thread name; useful when there | |
31 // are multiple syncers involved. | |
32 | |
33 #define SLOG(severity) LOG(severity) << name_ << ": " | |
34 | |
35 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": " | |
36 | |
37 static const int kSaveChangesIntervalSeconds = 10; | |
38 | |
39 namespace syncer { | |
40 class InternalComponentsFactory; | |
41 } // namespace syncer | |
42 | |
43 namespace net { | |
44 class URLFetcher; | |
45 } | |
46 | |
47 namespace { | |
48 | |
49 // Enums for UMAs. | |
50 enum SyncBackendInitState { | |
51 SETUP_COMPLETED_FOUND_RESTORED_TYPES = 0, | |
52 SETUP_COMPLETED_NO_RESTORED_TYPES, | |
53 FIRST_SETUP_NO_RESTORED_TYPES, | |
54 FIRST_SETUP_RESTORED_TYPES, | |
55 SYNC_BACKEND_INIT_STATE_COUNT | |
56 }; | |
57 | |
58 void BindFetcherToDataTracker(net::URLFetcher* fetcher) { | |
59 data_use_measurement::DataUseUserData::AttachToFetcher( | |
60 fetcher, data_use_measurement::DataUseUserData::SYNC); | |
61 } | |
62 | |
63 } // namespace | |
64 | |
65 namespace browser_sync { | |
66 | |
67 DoInitializeOptions::DoInitializeOptions( | |
68 base::MessageLoop* sync_loop, | |
69 SyncBackendRegistrar* registrar, | |
70 const syncer::ModelSafeRoutingInfo& routing_info, | |
71 const std::vector<scoped_refptr<syncer::ModelSafeWorker>>& workers, | |
72 const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity, | |
73 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler, | |
74 const GURL& service_url, | |
75 const std::string& sync_user_agent, | |
76 scoped_ptr<syncer::HttpPostProviderFactory> http_bridge_factory, | |
77 const syncer::SyncCredentials& credentials, | |
78 const std::string& invalidator_client_id, | |
79 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory, | |
80 bool delete_sync_data_folder, | |
81 const std::string& restored_key_for_bootstrapping, | |
82 const std::string& restored_keystore_key_for_bootstrapping, | |
83 scoped_ptr<syncer::InternalComponentsFactory> internal_components_factory, | |
84 const syncer::WeakHandle<syncer::UnrecoverableErrorHandler>& | |
85 unrecoverable_error_handler, | |
86 const base::Closure& report_unrecoverable_error_function, | |
87 scoped_ptr<syncer::SyncEncryptionHandler::NigoriState> saved_nigori_state, | |
88 syncer::PassphraseTransitionClearDataOption clear_data_option, | |
89 const std::map<syncer::ModelType, int64>& invalidation_versions) | |
90 : sync_loop(sync_loop), | |
91 registrar(registrar), | |
92 routing_info(routing_info), | |
93 workers(workers), | |
94 extensions_activity(extensions_activity), | |
95 event_handler(event_handler), | |
96 service_url(service_url), | |
97 sync_user_agent(sync_user_agent), | |
98 http_bridge_factory(http_bridge_factory.Pass()), | |
99 credentials(credentials), | |
100 invalidator_client_id(invalidator_client_id), | |
101 sync_manager_factory(sync_manager_factory.Pass()), | |
102 delete_sync_data_folder(delete_sync_data_folder), | |
103 restored_key_for_bootstrapping(restored_key_for_bootstrapping), | |
104 restored_keystore_key_for_bootstrapping( | |
105 restored_keystore_key_for_bootstrapping), | |
106 internal_components_factory(internal_components_factory.Pass()), | |
107 unrecoverable_error_handler(unrecoverable_error_handler), | |
108 report_unrecoverable_error_function(report_unrecoverable_error_function), | |
109 saved_nigori_state(saved_nigori_state.Pass()), | |
110 clear_data_option(clear_data_option), | |
111 invalidation_versions(invalidation_versions) {} | |
112 | |
113 DoInitializeOptions::~DoInitializeOptions() {} | |
114 | |
115 DoConfigureSyncerTypes::DoConfigureSyncerTypes() {} | |
116 | |
117 DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {} | |
118 | |
119 SyncBackendHostCore::SyncBackendHostCore( | |
120 const std::string& name, | |
121 const base::FilePath& sync_data_folder_path, | |
122 bool has_sync_setup_completed, | |
123 const base::WeakPtr<SyncBackendHostImpl>& backend) | |
124 : name_(name), | |
125 sync_data_folder_path_(sync_data_folder_path), | |
126 host_(backend), | |
127 sync_loop_(NULL), | |
128 registrar_(NULL), | |
129 has_sync_setup_completed_(has_sync_setup_completed), | |
130 forward_protocol_events_(false), | |
131 forward_type_info_(false), | |
132 weak_ptr_factory_(this) { | |
133 DCHECK(backend.get()); | |
134 } | |
135 | |
136 SyncBackendHostCore::~SyncBackendHostCore() { | |
137 DCHECK(!sync_manager_.get()); | |
138 } | |
139 | |
140 void SyncBackendHostCore::OnSyncCycleCompleted( | |
141 const syncer::sessions::SyncSessionSnapshot& snapshot) { | |
142 if (!sync_loop_) | |
143 return; | |
144 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
145 | |
146 host_.Call( | |
147 FROM_HERE, | |
148 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop, | |
149 snapshot); | |
150 } | |
151 | |
152 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) { | |
153 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
154 sync_manager_->RefreshTypes(types); | |
155 } | |
156 | |
157 void SyncBackendHostCore::OnInitializationComplete( | |
158 const syncer::WeakHandle<syncer::JsBackend>& js_backend, | |
159 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& | |
160 debug_info_listener, | |
161 bool success, | |
162 const syncer::ModelTypeSet restored_types) { | |
163 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
164 | |
165 if (!success) { | |
166 DoDestroySyncManager(syncer::STOP_SYNC); | |
167 host_.Call(FROM_HERE, | |
168 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop); | |
169 return; | |
170 } | |
171 | |
172 // Register for encryption related changes now. We have to do this before | |
173 // the initializing downloading control types or initializing the encryption | |
174 // handler in order to receive notifications triggered during encryption | |
175 // startup. | |
176 sync_manager_->GetEncryptionHandler()->AddObserver(this); | |
177 | |
178 // Sync manager initialization is complete, so we can schedule recurring | |
179 // SaveChanges. | |
180 sync_loop_->task_runner()->PostTask( | |
181 FROM_HERE, base::Bind(&SyncBackendHostCore::StartSavingChanges, | |
182 weak_ptr_factory_.GetWeakPtr())); | |
183 | |
184 // Hang on to these for a while longer. We're not ready to hand them back to | |
185 // the UI thread yet. | |
186 js_backend_ = js_backend; | |
187 debug_info_listener_ = debug_info_listener; | |
188 | |
189 // Track whether or not sync DB and preferences were in sync. | |
190 SyncBackendInitState backend_init_state; | |
191 if (has_sync_setup_completed_ && !restored_types.Empty()) { | |
192 backend_init_state = SETUP_COMPLETED_FOUND_RESTORED_TYPES; | |
193 } else if (has_sync_setup_completed_ && restored_types.Empty()) { | |
194 backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES; | |
195 } else if (!has_sync_setup_completed_ && restored_types.Empty()) { | |
196 backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES; | |
197 } else { // (!has_sync_setup_completed_ && !restored_types.Empty()) | |
198 backend_init_state = FIRST_SETUP_RESTORED_TYPES; | |
199 } | |
200 | |
201 UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState", | |
202 backend_init_state, | |
203 SYNC_BACKEND_INIT_STATE_COUNT); | |
204 | |
205 // Before proceeding any further, we need to download the control types and | |
206 // purge any partial data (ie. data downloaded for a type that was on its way | |
207 // to being initially synced, but didn't quite make it.). The following | |
208 // configure cycle will take care of this. It depends on the registrar state | |
209 // which we initialize below to ensure that we don't perform any downloads if | |
210 // all control types have already completed their initial sync. | |
211 registrar_->SetInitialTypes(restored_types); | |
212 | |
213 syncer::ConfigureReason reason = | |
214 restored_types.Empty() ? | |
215 syncer::CONFIGURE_REASON_NEW_CLIENT : | |
216 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE; | |
217 | |
218 syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes( | |
219 syncer::ControlTypes(), syncer::ModelTypeSet()); | |
220 syncer::ModelSafeRoutingInfo routing_info; | |
221 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
222 SDVLOG(1) << "Control Types " | |
223 << syncer::ModelTypeSetToString(new_control_types) | |
224 << " added; calling ConfigureSyncer"; | |
225 | |
226 syncer::ModelTypeSet types_to_purge = | |
227 syncer::Difference(syncer::ModelTypeSet::All(), | |
228 GetRoutingInfoTypes(routing_info)); | |
229 | |
230 sync_manager_->ConfigureSyncer( | |
231 reason, | |
232 new_control_types, | |
233 types_to_purge, | |
234 syncer::ModelTypeSet(), | |
235 syncer::ModelTypeSet(), | |
236 routing_info, | |
237 base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes, | |
238 weak_ptr_factory_.GetWeakPtr()), | |
239 base::Closure()); | |
240 } | |
241 | |
242 void SyncBackendHostCore::OnConnectionStatusChange( | |
243 syncer::ConnectionStatus status) { | |
244 if (!sync_loop_) | |
245 return; | |
246 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
247 host_.Call( | |
248 FROM_HERE, | |
249 &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop, status); | |
250 } | |
251 | |
252 void SyncBackendHostCore::OnPassphraseRequired( | |
253 syncer::PassphraseRequiredReason reason, | |
254 const sync_pb::EncryptedData& pending_keys) { | |
255 if (!sync_loop_) | |
256 return; | |
257 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
258 host_.Call( | |
259 FROM_HERE, | |
260 &SyncBackendHostImpl::NotifyPassphraseRequired, reason, pending_keys); | |
261 } | |
262 | |
263 void SyncBackendHostCore::OnPassphraseAccepted() { | |
264 if (!sync_loop_) | |
265 return; | |
266 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
267 host_.Call( | |
268 FROM_HERE, | |
269 &SyncBackendHostImpl::NotifyPassphraseAccepted); | |
270 } | |
271 | |
272 void SyncBackendHostCore::OnBootstrapTokenUpdated( | |
273 const std::string& bootstrap_token, | |
274 syncer::BootstrapTokenType type) { | |
275 if (!sync_loop_) | |
276 return; | |
277 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
278 host_.Call(FROM_HERE, | |
279 &SyncBackendHostImpl::PersistEncryptionBootstrapToken, | |
280 bootstrap_token, | |
281 type); | |
282 } | |
283 | |
284 void SyncBackendHostCore::OnEncryptedTypesChanged( | |
285 syncer::ModelTypeSet encrypted_types, | |
286 bool encrypt_everything) { | |
287 if (!sync_loop_) | |
288 return; | |
289 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
290 // NOTE: We're in a transaction. | |
291 host_.Call( | |
292 FROM_HERE, | |
293 &SyncBackendHostImpl::NotifyEncryptedTypesChanged, | |
294 encrypted_types, encrypt_everything); | |
295 } | |
296 | |
297 void SyncBackendHostCore::OnEncryptionComplete() { | |
298 if (!sync_loop_) | |
299 return; | |
300 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
301 // NOTE: We're in a transaction. | |
302 host_.Call( | |
303 FROM_HERE, | |
304 &SyncBackendHostImpl::NotifyEncryptionComplete); | |
305 } | |
306 | |
307 void SyncBackendHostCore::OnCryptographerStateChanged( | |
308 syncer::Cryptographer* cryptographer) { | |
309 // Do nothing. | |
310 } | |
311 | |
312 void SyncBackendHostCore::OnPassphraseTypeChanged( | |
313 syncer::PassphraseType type, base::Time passphrase_time) { | |
314 host_.Call( | |
315 FROM_HERE, | |
316 &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop, | |
317 type, passphrase_time); | |
318 } | |
319 | |
320 void SyncBackendHostCore::OnLocalSetPassphraseEncryption( | |
321 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) { | |
322 host_.Call( | |
323 FROM_HERE, | |
324 &SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop, | |
325 nigori_state); | |
326 } | |
327 | |
328 void SyncBackendHostCore::OnCommitCountersUpdated( | |
329 syncer::ModelType type, | |
330 const syncer::CommitCounters& counters) { | |
331 host_.Call( | |
332 FROM_HERE, | |
333 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop, | |
334 type, counters); | |
335 } | |
336 | |
337 void SyncBackendHostCore::OnUpdateCountersUpdated( | |
338 syncer::ModelType type, | |
339 const syncer::UpdateCounters& counters) { | |
340 host_.Call( | |
341 FROM_HERE, | |
342 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop, | |
343 type, counters); | |
344 } | |
345 | |
346 void SyncBackendHostCore::OnStatusCountersUpdated( | |
347 syncer::ModelType type, | |
348 const syncer::StatusCounters& counters) { | |
349 host_.Call( | |
350 FROM_HERE, | |
351 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop, | |
352 type, counters); | |
353 } | |
354 | |
355 void SyncBackendHostCore::OnActionableError( | |
356 const syncer::SyncProtocolError& sync_error) { | |
357 if (!sync_loop_) | |
358 return; | |
359 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
360 host_.Call( | |
361 FROM_HERE, | |
362 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop, | |
363 sync_error); | |
364 } | |
365 | |
366 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types) { | |
367 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
368 host_.Call( | |
369 FROM_HERE, | |
370 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop, | |
371 types); | |
372 } | |
373 | |
374 void SyncBackendHostCore::OnProtocolEvent( | |
375 const syncer::ProtocolEvent& event) { | |
376 // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr. | |
377 if (forward_protocol_events_) { | |
378 scoped_ptr<syncer::ProtocolEvent> event_clone(event.Clone()); | |
379 host_.Call( | |
380 FROM_HERE, | |
381 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop, | |
382 event_clone.release()); | |
383 } | |
384 } | |
385 | |
386 void SyncBackendHostCore::DoOnInvalidatorStateChange( | |
387 syncer::InvalidatorState state) { | |
388 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
389 sync_manager_->SetInvalidatorEnabled(state == syncer::INVALIDATIONS_ENABLED); | |
390 } | |
391 | |
392 void SyncBackendHostCore::DoOnIncomingInvalidation( | |
393 const syncer::ObjectIdInvalidationMap& invalidation_map) { | |
394 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
395 | |
396 syncer::ObjectIdSet ids = invalidation_map.GetObjectIds(); | |
397 for (const invalidation::ObjectId& object_id : ids) { | |
398 syncer::ModelType type; | |
399 if (!NotificationTypeToRealModelType(object_id.name(), &type)) { | |
400 DLOG(WARNING) << "Notification has invalid id: " | |
401 << syncer::ObjectIdToString(object_id); | |
402 } else { | |
403 syncer::SingleObjectInvalidationSet invalidation_set = | |
404 invalidation_map.ForObject(object_id); | |
405 for (syncer::Invalidation invalidation : invalidation_set) { | |
406 auto last_invalidation = last_invalidation_versions_.find(type); | |
407 if (!invalidation.is_unknown_version() && | |
408 last_invalidation != last_invalidation_versions_.end() && | |
409 invalidation.version() <= last_invalidation->second) { | |
410 DVLOG(1) << "Ignoring redundant invalidation for " | |
411 << syncer::ModelTypeToString(type) << " with version " | |
412 << invalidation.version() << ", last seen version was " | |
413 << last_invalidation->second; | |
414 continue; | |
415 } | |
416 scoped_ptr<syncer::InvalidationInterface> inv_adapter( | |
417 new InvalidationAdapter(invalidation)); | |
418 sync_manager_->OnIncomingInvalidation(type, inv_adapter.Pass()); | |
419 if (!invalidation.is_unknown_version()) | |
420 last_invalidation_versions_[type] = invalidation.version(); | |
421 } | |
422 } | |
423 } | |
424 | |
425 host_.Call( | |
426 FROM_HERE, | |
427 &SyncBackendHostImpl::UpdateInvalidationVersions, | |
428 last_invalidation_versions_); | |
429 } | |
430 | |
431 void SyncBackendHostCore::DoInitialize( | |
432 scoped_ptr<DoInitializeOptions> options) { | |
433 DCHECK(!sync_loop_); | |
434 sync_loop_ = options->sync_loop; | |
435 DCHECK(sync_loop_); | |
436 | |
437 // Finish initializing the HttpBridgeFactory. We do this here because | |
438 // building the user agent may block on some platforms. | |
439 options->http_bridge_factory->Init(options->sync_user_agent, | |
440 base::Bind(&BindFetcherToDataTracker)); | |
441 | |
442 // Blow away the partial or corrupt sync data folder before doing any more | |
443 // initialization, if necessary. | |
444 if (options->delete_sync_data_folder) { | |
445 DeleteSyncDataFolder(); | |
446 } | |
447 | |
448 // Make sure that the directory exists before initializing the backend. | |
449 // If it already exists, this will do no harm. | |
450 if (!base::CreateDirectory(sync_data_folder_path_)) { | |
451 DLOG(FATAL) << "Sync Data directory creation failed."; | |
452 } | |
453 | |
454 // Load the previously persisted set of invalidation versions into memory. | |
455 last_invalidation_versions_ = options->invalidation_versions; | |
456 | |
457 DCHECK(!registrar_); | |
458 registrar_ = options->registrar; | |
459 DCHECK(registrar_); | |
460 | |
461 sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_); | |
462 sync_manager_->AddObserver(this); | |
463 | |
464 syncer::SyncManager::InitArgs args; | |
465 args.database_location = sync_data_folder_path_; | |
466 args.event_handler = options->event_handler; | |
467 args.service_url = options->service_url; | |
468 args.post_factory = options->http_bridge_factory.Pass(); | |
469 args.workers = options->workers; | |
470 args.extensions_activity = options->extensions_activity.get(); | |
471 args.change_delegate = options->registrar; // as SyncManager::ChangeDelegate | |
472 args.credentials = options->credentials; | |
473 args.invalidator_client_id = options->invalidator_client_id; | |
474 args.restored_key_for_bootstrapping = options->restored_key_for_bootstrapping; | |
475 args.restored_keystore_key_for_bootstrapping = | |
476 options->restored_keystore_key_for_bootstrapping; | |
477 args.internal_components_factory = | |
478 options->internal_components_factory.Pass(); | |
479 args.encryptor = &encryptor_; | |
480 args.unrecoverable_error_handler = options->unrecoverable_error_handler; | |
481 args.report_unrecoverable_error_function = | |
482 options->report_unrecoverable_error_function; | |
483 args.cancelation_signal = &stop_syncing_signal_; | |
484 args.saved_nigori_state = options->saved_nigori_state.Pass(); | |
485 args.clear_data_option = options->clear_data_option; | |
486 sync_manager_->Init(&args); | |
487 } | |
488 | |
489 void SyncBackendHostCore::DoUpdateCredentials( | |
490 const syncer::SyncCredentials& credentials) { | |
491 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
492 // UpdateCredentials can be called during backend initialization, possibly | |
493 // when backend initialization has failed but hasn't notified the UI thread | |
494 // yet. In that case, the sync manager may have been destroyed on the sync | |
495 // thread before this task was executed, so we do nothing. | |
496 if (sync_manager_) { | |
497 sync_manager_->UpdateCredentials(credentials); | |
498 } | |
499 } | |
500 | |
501 void SyncBackendHostCore::DoStartSyncing( | |
502 const syncer::ModelSafeRoutingInfo& routing_info, | |
503 base::Time last_poll_time) { | |
504 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
505 sync_manager_->StartSyncingNormally(routing_info, last_poll_time); | |
506 } | |
507 | |
508 void SyncBackendHostCore::DoSetEncryptionPassphrase( | |
509 const std::string& passphrase, | |
510 bool is_explicit) { | |
511 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
512 sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase( | |
513 passphrase, is_explicit); | |
514 } | |
515 | |
516 void SyncBackendHostCore::DoInitialProcessControlTypes() { | |
517 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
518 | |
519 DVLOG(1) << "Initilalizing Control Types"; | |
520 | |
521 // Initialize encryption. | |
522 sync_manager_->GetEncryptionHandler()->Init(); | |
523 | |
524 // Note: experiments are currently handled via SBH::AddExperimentalTypes, | |
525 // which is called at the end of every sync cycle. | |
526 // TODO(zea): eventually add an experiment handler and initialize it here. | |
527 | |
528 if (!sync_manager_->GetUserShare()) { // NULL in some tests. | |
529 DVLOG(1) << "Skipping initialization of DeviceInfo"; | |
530 host_.Call( | |
531 FROM_HERE, | |
532 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop); | |
533 return; | |
534 } | |
535 | |
536 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) { | |
537 LOG(ERROR) << "Failed to download control types"; | |
538 host_.Call( | |
539 FROM_HERE, | |
540 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop); | |
541 return; | |
542 } | |
543 | |
544 host_.Call(FROM_HERE, | |
545 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop, | |
546 js_backend_, | |
547 debug_info_listener_, | |
548 sync_manager_->GetSyncContextProxy(), | |
549 sync_manager_->cache_guid()); | |
550 | |
551 js_backend_.Reset(); | |
552 debug_info_listener_.Reset(); | |
553 } | |
554 | |
555 void SyncBackendHostCore::DoSetDecryptionPassphrase( | |
556 const std::string& passphrase) { | |
557 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
558 sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase( | |
559 passphrase); | |
560 } | |
561 | |
562 void SyncBackendHostCore::DoEnableEncryptEverything() { | |
563 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
564 sync_manager_->GetEncryptionHandler()->EnableEncryptEverything(); | |
565 } | |
566 | |
567 void SyncBackendHostCore::ShutdownOnUIThread() { | |
568 // This will cut short any blocking network tasks, cut short any in-progress | |
569 // sync cycles, and prevent the creation of new blocking network tasks and new | |
570 // sync cycles. If there was an in-progress network request, it would have | |
571 // had a reference to the RequestContextGetter. This reference will be | |
572 // dropped by the time this function returns. | |
573 // | |
574 // It is safe to call this even if Sync's backend classes have not been | |
575 // initialized yet. Those classes will receive the message when the sync | |
576 // thread finally getes around to constructing them. | |
577 stop_syncing_signal_.Signal(); | |
578 | |
579 // This will drop the HttpBridgeFactory's reference to the | |
580 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can | |
581 // no longer be used to create new HttpBridge instances. We can get away with | |
582 // this because the stop_syncing_signal_ has already been signalled, which | |
583 // guarantees that the ServerConnectionManager will no longer attempt to | |
584 // create new connections. | |
585 release_request_context_signal_.Signal(); | |
586 } | |
587 | |
588 void SyncBackendHostCore::DoShutdown(syncer::ShutdownReason reason) { | |
589 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
590 | |
591 DoDestroySyncManager(reason); | |
592 | |
593 registrar_ = NULL; | |
594 | |
595 if (reason == syncer::DISABLE_SYNC) | |
596 DeleteSyncDataFolder(); | |
597 | |
598 host_.Reset(); | |
599 weak_ptr_factory_.InvalidateWeakPtrs(); | |
600 } | |
601 | |
602 void SyncBackendHostCore::DoDestroySyncManager(syncer::ShutdownReason reason) { | |
603 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
604 if (sync_manager_) { | |
605 DisableDirectoryTypeDebugInfoForwarding(); | |
606 save_changes_timer_.reset(); | |
607 sync_manager_->RemoveObserver(this); | |
608 sync_manager_->ShutdownOnSyncThread(reason); | |
609 sync_manager_.reset(); | |
610 } | |
611 } | |
612 | |
613 void SyncBackendHostCore::DoConfigureSyncer( | |
614 syncer::ConfigureReason reason, | |
615 const DoConfigureSyncerTypes& config_types, | |
616 const syncer::ModelSafeRoutingInfo routing_info, | |
617 const base::Callback<void(syncer::ModelTypeSet, | |
618 syncer::ModelTypeSet)>& ready_task, | |
619 const base::Closure& retry_callback) { | |
620 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
621 DCHECK(!ready_task.is_null()); | |
622 DCHECK(!retry_callback.is_null()); | |
623 base::Closure chained_ready_task( | |
624 base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes, | |
625 weak_ptr_factory_.GetWeakPtr(), | |
626 config_types.to_download, | |
627 ready_task)); | |
628 base::Closure chained_retry_task( | |
629 base::Bind(&SyncBackendHostCore::DoRetryConfiguration, | |
630 weak_ptr_factory_.GetWeakPtr(), | |
631 retry_callback)); | |
632 sync_manager_->ConfigureSyncer(reason, | |
633 config_types.to_download, | |
634 config_types.to_purge, | |
635 config_types.to_journal, | |
636 config_types.to_unapply, | |
637 routing_info, | |
638 chained_ready_task, | |
639 chained_retry_task); | |
640 } | |
641 | |
642 void SyncBackendHostCore::DoFinishConfigureDataTypes( | |
643 syncer::ModelTypeSet types_to_config, | |
644 const base::Callback<void(syncer::ModelTypeSet, | |
645 syncer::ModelTypeSet)>& ready_task) { | |
646 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
647 | |
648 // Update the enabled types for the bridge and sync manager. | |
649 syncer::ModelSafeRoutingInfo routing_info; | |
650 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
651 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info); | |
652 enabled_types.RemoveAll(syncer::ProxyTypes()); | |
653 | |
654 const syncer::ModelTypeSet failed_configuration_types = | |
655 Difference(types_to_config, sync_manager_->InitialSyncEndedTypes()); | |
656 const syncer::ModelTypeSet succeeded_configuration_types = | |
657 Difference(types_to_config, failed_configuration_types); | |
658 host_.Call(FROM_HERE, | |
659 &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop, | |
660 enabled_types, | |
661 succeeded_configuration_types, | |
662 failed_configuration_types, | |
663 ready_task); | |
664 } | |
665 | |
666 void SyncBackendHostCore::DoRetryConfiguration( | |
667 const base::Closure& retry_callback) { | |
668 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
669 host_.Call(FROM_HERE, | |
670 &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop, | |
671 retry_callback); | |
672 } | |
673 | |
674 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() { | |
675 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
676 forward_protocol_events_ = true; | |
677 | |
678 if (sync_manager_) { | |
679 // Grab our own copy of the buffered events. | |
680 // The buffer is not modified by this operation. | |
681 std::vector<syncer::ProtocolEvent*> buffered_events; | |
682 sync_manager_->GetBufferedProtocolEvents().release(&buffered_events); | |
683 | |
684 // Send them all over the fence to the host. | |
685 for (std::vector<syncer::ProtocolEvent*>::iterator it = | |
686 buffered_events.begin(); it != buffered_events.end(); ++it) { | |
687 // TODO(rlarocque): Make it explicit that host_ takes ownership. | |
688 host_.Call( | |
689 FROM_HERE, | |
690 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop, | |
691 *it); | |
692 } | |
693 } | |
694 } | |
695 | |
696 void SyncBackendHostCore::DisableProtocolEventForwarding() { | |
697 forward_protocol_events_ = false; | |
698 } | |
699 | |
700 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() { | |
701 DCHECK(sync_manager_); | |
702 | |
703 forward_type_info_ = true; | |
704 | |
705 if (!sync_manager_->HasDirectoryTypeDebugInfoObserver(this)) | |
706 sync_manager_->RegisterDirectoryTypeDebugInfoObserver(this); | |
707 sync_manager_->RequestEmitDebugInfo(); | |
708 } | |
709 | |
710 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() { | |
711 DCHECK(sync_manager_); | |
712 | |
713 if (!forward_type_info_) | |
714 return; | |
715 | |
716 forward_type_info_ = false; | |
717 | |
718 if (sync_manager_->HasDirectoryTypeDebugInfoObserver(this)) | |
719 sync_manager_->UnregisterDirectoryTypeDebugInfoObserver(this); | |
720 } | |
721 | |
722 void SyncBackendHostCore::DeleteSyncDataFolder() { | |
723 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
724 if (base::DirectoryExists(sync_data_folder_path_)) { | |
725 if (!base::DeleteFile(sync_data_folder_path_, true)) | |
726 SLOG(DFATAL) << "Could not delete the Sync Data folder."; | |
727 } | |
728 } | |
729 | |
730 void SyncBackendHostCore::GetAllNodesForTypes( | |
731 syncer::ModelTypeSet types, | |
732 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
733 base::Callback<void(const std::vector<syncer::ModelType>& type, | |
734 ScopedVector<base::ListValue>)> callback) { | |
735 std::vector<syncer::ModelType> types_vector; | |
736 ScopedVector<base::ListValue> node_lists; | |
737 | |
738 syncer::ModelSafeRoutingInfo routes; | |
739 registrar_->GetModelSafeRoutingInfo(&routes); | |
740 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routes); | |
741 | |
742 for (syncer::ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { | |
743 types_vector.push_back(it.Get()); | |
744 if (!enabled_types.Has(it.Get())) { | |
745 node_lists.push_back(new base::ListValue()); | |
746 } else { | |
747 node_lists.push_back( | |
748 sync_manager_->GetAllNodesForType(it.Get()).release()); | |
749 } | |
750 } | |
751 | |
752 task_runner->PostTask( | |
753 FROM_HERE, | |
754 base::Bind(callback, types_vector, base::Passed(&node_lists))); | |
755 } | |
756 | |
757 void SyncBackendHostCore::StartSavingChanges() { | |
758 // We may already be shut down. | |
759 if (!sync_loop_) | |
760 return; | |
761 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
762 DCHECK(!save_changes_timer_.get()); | |
763 save_changes_timer_.reset(new base::RepeatingTimer()); | |
764 save_changes_timer_->Start(FROM_HERE, | |
765 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds), | |
766 this, &SyncBackendHostCore::SaveChanges); | |
767 } | |
768 | |
769 void SyncBackendHostCore::SaveChanges() { | |
770 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
771 sync_manager_->SaveChanges(); | |
772 } | |
773 | |
774 void SyncBackendHostCore::DoClearServerData( | |
775 const syncer::SyncManager::ClearServerDataCallback& frontend_callback) { | |
776 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
777 const syncer::SyncManager::ClearServerDataCallback callback = | |
778 base::Bind(&SyncBackendHostCore::ClearServerDataDone, | |
779 weak_ptr_factory_.GetWeakPtr(), frontend_callback); | |
780 sync_manager_->ClearServerData(callback); | |
781 } | |
782 | |
783 void SyncBackendHostCore::ClearServerDataDone( | |
784 const base::Closure& frontend_callback) { | |
785 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); | |
786 host_.Call(FROM_HERE, &SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop, | |
787 frontend_callback); | |
788 } | |
789 | |
790 | |
791 } // namespace browser_sync | |
OLD | NEW |