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