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