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