Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4012)

Unified Diff: chrome/browser/sync/glue/sync_backend_host_core.cc

Issue 61183003: Refactor SyncBackendHost (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove double virtual Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sync/glue/sync_backend_host_core.cc
diff --git a/chrome/browser/sync/glue/sync_backend_host_core.cc b/chrome/browser/sync/glue/sync_backend_host_core.cc
new file mode 100644
index 0000000000000000000000000000000000000000..829e6b8416dd61705eeaf899b07e003cf065d50e
--- /dev/null
+++ b/chrome/browser/sync/glue/sync_backend_host_core.cc
@@ -0,0 +1,621 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/glue/sync_backend_host_core.h"
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/metrics/histogram.h"
+#include "chrome/browser/sync/glue/device_info.h"
+#include "chrome/browser/sync/glue/sync_backend_registrar.h"
+#include "chrome/browser/sync/glue/synced_device_tracker.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_version_info.h"
+#include "sync/internal_api/public/http_post_provider_factory.h"
+#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
+#include "sync/internal_api/public/sync_manager.h"
+#include "sync/internal_api/public/sync_manager_factory.h"
+
+// Helper macros to log with the syncer thread name; useful when there
+// are multiple syncers involved.
+
+#define SLOG(severity) LOG(severity) << name_ << ": "
+
+#define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
+
+static const int kSaveChangesIntervalSeconds = 10;
+
+namespace {
+
+// Enums for UMAs.
+enum SyncBackendInitState {
+ SETUP_COMPLETED_FOUND_RESTORED_TYPES = 0,
+ SETUP_COMPLETED_NO_RESTORED_TYPES,
+ FIRST_SETUP_NO_RESTORED_TYPES,
+ FIRST_SETUP_RESTORED_TYPES,
+ SYNC_BACKEND_INIT_STATE_COUNT
+};
+
+} // namespace
+
+namespace syncer {
Nicolas Zea 2013/11/06 18:03:21 nit: I think we typically have forward declaration
rlarocque 2013/11/06 21:48:47 Done.
+class InternalComponentsFactory;
+} // namespace syncer
+
+namespace browser_sync {
+
+DoInitializeOptions::DoInitializeOptions(
+ base::MessageLoop* sync_loop,
+ SyncBackendRegistrar* registrar,
+ const syncer::ModelSafeRoutingInfo& routing_info,
+ const std::vector<syncer::ModelSafeWorker*>& workers,
+ const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity,
+ const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
+ const GURL& service_url,
+ scoped_ptr<syncer::HttpPostProviderFactory> http_bridge_factory,
+ const syncer::SyncCredentials& credentials,
+ const std::string& invalidator_client_id,
+ scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
+ bool delete_sync_data_folder,
+ const std::string& restored_key_for_bootstrapping,
+ const std::string& restored_keystore_key_for_bootstrapping,
+ scoped_ptr<syncer::InternalComponentsFactory> internal_components_factory,
+ scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
+ syncer::ReportUnrecoverableErrorFunction
+ report_unrecoverable_error_function)
+ : sync_loop(sync_loop),
+ registrar(registrar),
+ routing_info(routing_info),
+ workers(workers),
+ extensions_activity(extensions_activity),
+ event_handler(event_handler),
+ service_url(service_url),
+ http_bridge_factory(http_bridge_factory.Pass()),
+ credentials(credentials),
+ invalidator_client_id(invalidator_client_id),
+ sync_manager_factory(sync_manager_factory.Pass()),
+ delete_sync_data_folder(delete_sync_data_folder),
+ restored_key_for_bootstrapping(restored_key_for_bootstrapping),
+ restored_keystore_key_for_bootstrapping(
+ restored_keystore_key_for_bootstrapping),
+ internal_components_factory(internal_components_factory.Pass()),
+ unrecoverable_error_handler(unrecoverable_error_handler.Pass()),
+ report_unrecoverable_error_function(
+ report_unrecoverable_error_function) {
+}
+
+DoInitializeOptions::~DoInitializeOptions() {}
+
+DoConfigureSyncerTypes::DoConfigureSyncerTypes() {}
+
+DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {}
+
+SyncBackendHostCore::SyncBackendHostCore(
+ const std::string& name,
+ const base::FilePath& sync_data_folder_path,
+ bool has_sync_setup_completed,
+ const base::WeakPtr<SyncBackendHostImpl>& backend)
+ : name_(name),
+ sync_data_folder_path_(sync_data_folder_path),
+ host_(backend),
+ sync_loop_(NULL),
+ registrar_(NULL),
+ has_sync_setup_completed_(has_sync_setup_completed),
+ weak_ptr_factory_(this) {
+ DCHECK(backend.get());
+}
+
+SyncBackendHostCore::~SyncBackendHostCore() {
+ DCHECK(!sync_manager_.get());
+}
+
+void SyncBackendHostCore::OnSyncCycleCompleted(
+ const syncer::sessions::SyncSessionSnapshot& snapshot) {
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop,
+ snapshot);
+}
+
+void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ sync_manager_->RefreshTypes(types);
+}
+
+void SyncBackendHostCore::OnControlTypesDownloadRetry() {
+ host_.Call(FROM_HERE,
+ &SyncBackendHostImpl::HandleControlTypesDownloadRetry);
+}
+
+void SyncBackendHostCore::OnInitializationComplete(
+ const syncer::WeakHandle<syncer::JsBackend>& js_backend,
+ const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
+ debug_info_listener,
+ bool success,
+ const syncer::ModelTypeSet restored_types) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+
+ if (!success) {
+ DoDestroySyncManager();
+ host_.Call(FROM_HERE,
+ &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
+ return;
+ }
+
+ // Register for encryption related changes now. We have to do this before
+ // the initializing downloading control types or initializing the encryption
+ // handler in order to receive notifications triggered during encryption
+ // startup.
+ sync_manager_->GetEncryptionHandler()->AddObserver(this);
+
+ // Sync manager initialization is complete, so we can schedule recurring
+ // SaveChanges.
+ sync_loop_->PostTask(FROM_HERE,
+ base::Bind(&SyncBackendHostCore::StartSavingChanges,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ // Hang on to these for a while longer. We're not ready to hand them back to
+ // the UI thread yet.
+ js_backend_ = js_backend;
+ debug_info_listener_ = debug_info_listener;
+
+ // Track whether or not sync DB and preferences were in sync.
+ SyncBackendInitState backend_init_state;
+ if (has_sync_setup_completed_ && !restored_types.Empty()) {
+ backend_init_state = SETUP_COMPLETED_FOUND_RESTORED_TYPES;
+ } else if (has_sync_setup_completed_ && restored_types.Empty()) {
+ backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES;
+ } else if (!has_sync_setup_completed_ && restored_types.Empty()) {
+ backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES;
+ } else { // (!has_sync_setup_completed_ && !restored_types.Empty())
+ backend_init_state = FIRST_SETUP_RESTORED_TYPES;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState",
+ backend_init_state,
+ SYNC_BACKEND_INIT_STATE_COUNT);
+
+ // Before proceeding any further, we need to download the control types and
+ // purge any partial data (ie. data downloaded for a type that was on its way
+ // to being initially synced, but didn't quite make it.). The following
+ // configure cycle will take care of this. It depends on the registrar state
+ // which we initialize below to ensure that we don't perform any downloads if
+ // all control types have already completed their initial sync.
+ registrar_->SetInitialTypes(restored_types);
+
+ syncer::ConfigureReason reason =
+ restored_types.Empty() ?
+ syncer::CONFIGURE_REASON_NEW_CLIENT :
+ syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
+
+ syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes(
+ syncer::ControlTypes(), syncer::ModelTypeSet());
+ syncer::ModelSafeRoutingInfo routing_info;
+ registrar_->GetModelSafeRoutingInfo(&routing_info);
+ SDVLOG(1) << "Control Types "
+ << syncer::ModelTypeSetToString(new_control_types)
+ << " added; calling ConfigureSyncer";
+
+ syncer::ModelTypeSet types_to_purge =
+ syncer::Difference(syncer::ModelTypeSet::All(),
+ GetRoutingInfoTypes(routing_info));
+
+ sync_manager_->ConfigureSyncer(
+ reason,
+ new_control_types,
+ types_to_purge,
+ syncer::ModelTypeSet(),
+ syncer::ModelTypeSet(),
+ routing_info,
+ base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&SyncBackendHostCore::OnControlTypesDownloadRetry,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void SyncBackendHostCore::OnConnectionStatusChange(
+ syncer::ConnectionStatus status) {
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop, status);
+}
+
+void SyncBackendHostCore::OnPassphraseRequired(
+ syncer::PassphraseRequiredReason reason,
+ const sync_pb::EncryptedData& pending_keys) {
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::NotifyPassphraseRequired, reason, pending_keys);
+}
+
+void SyncBackendHostCore::OnPassphraseAccepted() {
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::NotifyPassphraseAccepted);
+}
+
+void SyncBackendHostCore::OnBootstrapTokenUpdated(
+ const std::string& bootstrap_token,
+ syncer::BootstrapTokenType type) {
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ host_.Call(FROM_HERE,
+ &SyncBackendHostImpl::PersistEncryptionBootstrapToken,
+ bootstrap_token,
+ type);
+}
+
+void SyncBackendHostCore::OnStopSyncingPermanently() {
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::HandleStopSyncingPermanentlyOnFrontendLoop);
+}
+
+void SyncBackendHostCore::OnEncryptedTypesChanged(
+ syncer::ModelTypeSet encrypted_types,
+ bool encrypt_everything) {
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ // NOTE: We're in a transaction.
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::NotifyEncryptedTypesChanged,
+ encrypted_types, encrypt_everything);
+}
+
+void SyncBackendHostCore::OnEncryptionComplete() {
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ // NOTE: We're in a transaction.
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::NotifyEncryptionComplete);
+}
+
+void SyncBackendHostCore::OnCryptographerStateChanged(
+ syncer::Cryptographer* cryptographer) {
+ // Do nothing.
+}
+
+void SyncBackendHostCore::OnPassphraseTypeChanged(
+ syncer::PassphraseType type, base::Time passphrase_time) {
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop,
+ type, passphrase_time);
+}
+
+void SyncBackendHostCore::OnActionableError(
+ const syncer::SyncProtocolError& sync_error) {
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop,
+ sync_error);
+}
+
+void SyncBackendHostCore::DoOnInvalidatorStateChange(
+ syncer::InvalidatorState state) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ sync_manager_->OnInvalidatorStateChange(state);
+}
+
+void SyncBackendHostCore::DoOnIncomingInvalidation(
+ syncer::ObjectIdInvalidationMap invalidation_map) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ sync_manager_->OnIncomingInvalidation(invalidation_map);
+}
+
+void SyncBackendHostCore::DoInitialize(
+ scoped_ptr<DoInitializeOptions> options) {
+ DCHECK(!sync_loop_);
+ sync_loop_ = options->sync_loop;
+ DCHECK(sync_loop_);
+
+ // Finish initializing the HttpBridgeFactory. We do this here because
+ // building the user agent may block on some platforms.
+ chrome::VersionInfo version_info;
+ options->http_bridge_factory->Init(
+ DeviceInfo::MakeUserAgentForSyncApi(version_info));
+
+ // Blow away the partial or corrupt sync data folder before doing any more
+ // initialization, if necessary.
+ if (options->delete_sync_data_folder) {
+ DeleteSyncDataFolder();
+ }
+
+ // Make sure that the directory exists before initializing the backend.
+ // If it already exists, this will do no harm.
+ if (!file_util::CreateDirectory(sync_data_folder_path_)) {
+ DLOG(FATAL) << "Sync Data directory creation failed.";
+ }
+
+ DCHECK(!registrar_);
+ registrar_ = options->registrar;
+ DCHECK(registrar_);
+
+ sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_);
+ sync_manager_->AddObserver(this);
+ sync_manager_->Init(sync_data_folder_path_,
+ options->event_handler,
+ options->service_url.host() + options->service_url.path(),
+ options->service_url.EffectiveIntPort(),
+ options->service_url.SchemeIsSecure(),
+ options->http_bridge_factory.Pass(),
+ options->workers,
+ options->extensions_activity,
+ options->registrar /* as SyncManager::ChangeDelegate */,
+ options->credentials,
+ options->invalidator_client_id,
+ options->restored_key_for_bootstrapping,
+ options->restored_keystore_key_for_bootstrapping,
+ options->internal_components_factory.get(),
+ &encryptor_,
+ options->unrecoverable_error_handler.Pass(),
+ options->report_unrecoverable_error_function,
+ &stop_syncing_signal_);
+
+ // |sync_manager_| may end up being NULL here in tests (in
+ // synchronous initialization mode).
+ //
+ // TODO(akalin): Fix this behavior (see http://crbug.com/140354).
+ if (sync_manager_) {
+ // Now check the command line to see if we need to simulate an
+ // unrecoverable error for testing purpose. Note the error is thrown
+ // only if the initialization succeeded. Also it makes sense to use this
+ // flag only when restarting the browser with an account already setup. If
+ // you use this before setting up the setup would not succeed as an error
+ // would be encountered.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSyncThrowUnrecoverableError)) {
+ sync_manager_->ThrowUnrecoverableError();
+ }
+ }
+}
+
+void SyncBackendHostCore::DoUpdateCredentials(
+ const syncer::SyncCredentials& credentials) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ // UpdateCredentials can be called during backend initialization, possibly
+ // when backend initialization has failed but hasn't notified the UI thread
+ // yet. In that case, the sync manager may have been destroyed on the sync
+ // thread before this task was executed, so we do nothing.
+ if (sync_manager_) {
+ sync_manager_->UpdateCredentials(credentials);
+ }
+}
+
+void SyncBackendHostCore::DoStartSyncing(
+ const syncer::ModelSafeRoutingInfo& routing_info) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ sync_manager_->StartSyncingNormally(routing_info);
+}
+
+void SyncBackendHostCore::DoSetEncryptionPassphrase(
+ const std::string& passphrase,
+ bool is_explicit) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(
+ passphrase, is_explicit);
+}
+
+void SyncBackendHostCore::DoInitialProcessControlTypes() {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+
+ DVLOG(1) << "Initilalizing Control Types";
+
+ // Initialize encryption.
+ sync_manager_->GetEncryptionHandler()->Init();
+
+ // Note: experiments are currently handled via SBH::AddExperimentalTypes,
+ // which is called at the end of every sync cycle.
+ // TODO(zea): eventually add an experiment handler and initialize it here.
+
+ if (!sync_manager_->GetUserShare()) { // NULL in some tests.
+ DVLOG(1) << "Skipping initialization of DeviceInfo";
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
+ return;
+ }
+
+ if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
+ LOG(ERROR) << "Failed to download control types";
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
+ return;
+ }
+
+ // Initialize device info. This is asynchronous on some platforms, so we
+ // provide a callback for when it finishes.
+ synced_device_tracker_.reset(
+ new SyncedDeviceTracker(sync_manager_->GetUserShare(),
+ sync_manager_->cache_guid()));
+ synced_device_tracker_->InitLocalDeviceInfo(
+ base::Bind(&SyncBackendHostCore::DoFinishInitialProcessControlTypes,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void SyncBackendHostCore::DoFinishInitialProcessControlTypes() {
+ registrar_->ActivateDataType(syncer::DEVICE_INFO,
+ syncer::GROUP_PASSIVE,
+ synced_device_tracker_.get(),
+ sync_manager_->GetUserShare());
+
+ host_.Call(
+ FROM_HERE,
+ &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop,
+ js_backend_,
+ debug_info_listener_);
+
+ js_backend_.Reset();
+ debug_info_listener_.Reset();
+}
+
+void SyncBackendHostCore::DoSetDecryptionPassphrase(
+ const std::string& passphrase) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(
+ passphrase);
+}
+
+void SyncBackendHostCore::DoEnableEncryptEverything() {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
+}
+
+void SyncBackendHostCore::ShutdownOnUIThread() {
+ // This will cut short any blocking network tasks, cut short any in-progress
+ // sync cycles, and prevent the creation of new blocking network tasks and new
+ // sync cycles. If there was an in-progress network request, it would have
+ // had a reference to the RequestContextGetter. This reference will be
+ // dropped by the time this function returns.
+ //
+ // It is safe to call this even if Sync's backend classes have not been
+ // initialized yet. Those classes will receive the message when the sync
+ // thread finally getes around to constructing them.
+ stop_syncing_signal_.Signal();
+
+ // This will drop the HttpBridgeFactory's reference to the
+ // RequestContextGetter. Once this has been called, the HttpBridgeFactory can
+ // no longer be used to create new HttpBridge instances. We can get away with
+ // this because the stop_syncing_signal_ has already been signalled, which
+ // guarantees that the ServerConnectionManager will no longer attempt to
+ // create new connections.
+ release_request_context_signal_.Signal();
+}
+
+void SyncBackendHostCore::DoShutdown(bool sync_disabled) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+
+ // It's safe to do this even if the type was never activated.
+ registrar_->DeactivateDataType(syncer::DEVICE_INFO);
+ synced_device_tracker_.reset();
+
+ DoDestroySyncManager();
+
+ registrar_ = NULL;
+
+ if (sync_disabled)
+ DeleteSyncDataFolder();
+
+ host_.Reset();
+ weak_ptr_factory_.InvalidateWeakPtrs();
+}
+
+void SyncBackendHostCore::DoDestroySyncManager() {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ if (sync_manager_) {
+ save_changes_timer_.reset();
+ sync_manager_->RemoveObserver(this);
+ sync_manager_->ShutdownOnSyncThread();
+ sync_manager_.reset();
+ }
+}
+
+void SyncBackendHostCore::DoConfigureSyncer(
+ syncer::ConfigureReason reason,
+ const DoConfigureSyncerTypes& config_types,
+ const syncer::ModelSafeRoutingInfo routing_info,
+ const base::Callback<void(syncer::ModelTypeSet,
+ syncer::ModelTypeSet)>& ready_task,
+ const base::Closure& retry_callback) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ sync_manager_->ConfigureSyncer(
+ reason,
+ config_types.to_download,
+ config_types.to_purge,
+ config_types.to_journal,
+ config_types.to_unapply,
+ routing_info,
+ base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes,
+ weak_ptr_factory_.GetWeakPtr(),
+ config_types.to_download,
+ ready_task),
+ base::Bind(&SyncBackendHostCore::DoRetryConfiguration,
+ weak_ptr_factory_.GetWeakPtr(),
+ retry_callback));
+}
+
+void SyncBackendHostCore::DoFinishConfigureDataTypes(
+ syncer::ModelTypeSet types_to_config,
+ const base::Callback<void(syncer::ModelTypeSet,
+ syncer::ModelTypeSet)>& ready_task) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+
+ // Update the enabled types for the bridge and sync manager.
+ syncer::ModelSafeRoutingInfo routing_info;
+ registrar_->GetModelSafeRoutingInfo(&routing_info);
+ syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
+ enabled_types.RemoveAll(syncer::ProxyTypes());
+
+ const syncer::ModelTypeSet failed_configuration_types =
+ Difference(types_to_config, sync_manager_->InitialSyncEndedTypes());
+ const syncer::ModelTypeSet succeeded_configuration_types =
+ Difference(types_to_config, failed_configuration_types);
+ host_.Call(FROM_HERE,
+ &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop,
+ enabled_types,
+ succeeded_configuration_types,
+ failed_configuration_types,
+ ready_task);
+}
+
+void SyncBackendHostCore::DoRetryConfiguration(
+ const base::Closure& retry_callback) {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ host_.Call(FROM_HERE,
+ &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop,
+ retry_callback);
+}
+
+void SyncBackendHostCore::DeleteSyncDataFolder() {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ if (base::DirectoryExists(sync_data_folder_path_)) {
+ if (!base::DeleteFile(sync_data_folder_path_, true))
+ SLOG(DFATAL) << "Could not delete the Sync Data folder.";
+ }
+}
+
+void SyncBackendHostCore::StartSavingChanges() {
+ // We may already be shut down.
+ if (!sync_loop_)
+ return;
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ DCHECK(!save_changes_timer_.get());
+ save_changes_timer_.reset(new base::RepeatingTimer<SyncBackendHostCore>());
+ save_changes_timer_->Start(FROM_HERE,
+ base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
+ this, &SyncBackendHostCore::SaveChanges);
+}
+
+void SyncBackendHostCore::SaveChanges() {
+ DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+ sync_manager_->SaveChanges();
+}
+
+} // namespace browser_sync
+

Powered by Google App Engine
This is Rietveld 408576698