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