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