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/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 
     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 
     92 DoInitializeOptions::~DoInitializeOptions() {}
     93 
     94 DoConfigureSyncerTypes::DoConfigureSyncerTypes() {}
     95 
     96 DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {}
     97 
     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 
    115 SyncBackendHostCore::~SyncBackendHostCore() {
    116   DCHECK(!sync_manager_.get());
    117 }
    118 
    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 
    131 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) {
    132   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
    133   sync_manager_->RefreshTypes(types);
    134 }
    135 
    136 void SyncBackendHostCore::OnControlTypesDownloadRetry() {
    137   host_.Call(FROM_HERE,
    138              &SyncBackendHostImpl::HandleControlTypesDownloadRetry);
    139 }
    140 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    292 void SyncBackendHostCore::OnCryptographerStateChanged(
    293     syncer::Cryptographer* cryptographer) {
    294   // Do nothing.
    295 }
    296 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    363 void SyncBackendHostCore::DoOnInvalidatorStateChange(
    364     syncer::InvalidatorState state) {
    365   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
    366   sync_manager_->OnInvalidatorStateChange(state);
    367 }
    368 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    515 void SyncBackendHostCore::DoEnableEncryptEverything() {
    516   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
    517   sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
    518 }
    519 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    648 void SyncBackendHostCore::DisableProtocolEventForwarding() {
    649   forward_protocol_events_ = false;
    650 }
    651 
    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 
    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 
    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 
    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 
    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 
    721 void SyncBackendHostCore::SaveChanges() {
    722   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
    723   sync_manager_->SaveChanges();
    724 }
    725 
    726 }  // namespace browser_sync
    727 
    728