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