Index: chrome/browser/sync/glue/sync_backend_host.cc |
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc |
index 963ccaba599e2d8c73ee53f85c015595c5405c9f..84f98cddb831bd2d59cb69fbc69a78771c13e96a 100644 |
--- a/chrome/browser/sync/glue/sync_backend_host.cc |
+++ b/chrome/browser/sync/glue/sync_backend_host.cc |
@@ -126,10 +126,6 @@ class SyncBackendHost::Core |
// initialization and authentication). |
void DoStartSyncing(const syncer::ModelSafeRoutingInfo& routing_info); |
- // Called to cleanup disabled types. |
- void DoRequestCleanupDisabledTypes( |
- const syncer::ModelSafeRoutingInfo& routing_info); |
- |
// Called to set the passphrase for encryption. |
void DoSetEncryptionPassphrase(const std::string& passphrase, |
bool is_explicit); |
@@ -159,14 +155,18 @@ class SyncBackendHost::Core |
void DoStopSyncManagerForShutdown(const base::Closure& closure); |
void DoShutdown(bool stopping_sync); |
- virtual void DoRequestConfig( |
- const syncer::ModelSafeRoutingInfo& routing_info, |
+ // Configuration methods that must execute on sync loop. |
+ void DoConfigureSyncer( |
+ syncer::ConfigureReason reason, |
syncer::ModelTypeSet types_to_config, |
- syncer::ConfigureReason reason); |
- |
- // Start the configuration mode. |callback| is called on the sync |
- // thread. |
- virtual void DoStartConfiguration(const base::Closure& callback); |
+ const syncer::ModelSafeRoutingInfo routing_info, |
+ const base::Callback<void(syncer::ModelTypeSet)>& ready_task, |
+ const base::Closure& retry_callback); |
+ void DoFinishConfigureDataTypes( |
+ syncer::ModelTypeSet types_to_config, |
+ const base::Callback<void(syncer::ModelTypeSet)>& ready_task); |
+ void DoRetryConfiguration( |
+ const base::Closure& retry_callback); |
// Set the base request context to use when making HTTP calls. |
// This method will add a reference to the context to persist it |
@@ -179,9 +179,6 @@ class SyncBackendHost::Core |
// sync databases), as well as shutdown when you're no longer syncing. |
void DeleteSyncDataFolder(); |
- // A callback from the SyncerThread when it is safe to continue config. |
- void FinishConfigureDataTypes(); |
- |
private: |
friend class base::RefCountedThreadSafe<SyncBackendHost::Core>; |
friend class SyncBackendHostForProfileSyncTest; |
@@ -355,9 +352,10 @@ std::string MakeUserAgentForSyncApi() { |
return user_agent; |
} |
-syncer::HttpPostProviderFactory* MakeHttpBridgeFactory( |
+scoped_ptr<syncer::HttpPostProviderFactory> MakeHttpBridgeFactory( |
const scoped_refptr<net::URLRequestContextGetter>& getter) { |
- return new syncer::HttpBridgeFactory(getter, MakeUserAgentForSyncApi()); |
+ return scoped_ptr<syncer::HttpPostProviderFactory>( |
+ new syncer::HttpBridgeFactory(getter, MakeUserAgentForSyncApi())); |
} |
} // namespace |
@@ -369,10 +367,11 @@ void SyncBackendHost::Initialize( |
syncer::ModelTypeSet initial_types, |
const SyncCredentials& credentials, |
bool delete_sync_data_folder, |
+ syncer::SyncManagerFactory* sync_manager_factory, |
syncer::UnrecoverableErrorHandler* unrecoverable_error_handler, |
syncer::ReportUnrecoverableErrorFunction |
report_unrecoverable_error_function) { |
- if (!sync_thread_.Start()) |
+ if (!StartSyncThread()) |
return; |
frontend_ = frontend; |
@@ -407,6 +406,7 @@ void SyncBackendHost::Initialize( |
credentials, |
&chrome_sync_notification_bridge_, |
&sync_notifier_factory_, |
+ sync_manager_factory, |
delete_sync_data_folder, |
sync_prefs_->GetEncryptionBootstrapToken(), |
syncer::SyncManager::NON_TEST, |
@@ -589,8 +589,8 @@ void SyncBackendHost::ConfigureDataTypes( |
syncer::ModelTypeSet types_to_add, |
syncer::ModelTypeSet types_to_remove, |
NigoriState nigori_state, |
- base::Callback<void(syncer::ModelTypeSet)> ready_task, |
- base::Callback<void()> retry_callback) { |
+ const base::Callback<void(syncer::ModelTypeSet)>& ready_task, |
+ const base::Callback<void()>& retry_callback) { |
syncer::ModelTypeSet types_to_add_with_nigori = types_to_add; |
syncer::ModelTypeSet types_to_remove_with_nigori = types_to_remove; |
if (nigori_state == WITH_NIGORI) { |
@@ -600,44 +600,56 @@ void SyncBackendHost::ConfigureDataTypes( |
types_to_add_with_nigori.Remove(syncer::NIGORI); |
types_to_remove_with_nigori.Put(syncer::NIGORI); |
} |
- // Only one configure is allowed at a time. |
- DCHECK(!pending_config_mode_state_.get()); |
- DCHECK(!pending_download_state_.get()); |
+ // Only one configure is allowed at a time (DataTypeManager handles user |
+ // changes that happen while the syncer is reconfiguring, and will only |
+ // trigger another call to ConfigureDataTypes once the current reconfiguration |
+ // completes). |
DCHECK_GT(initialization_state_, NOT_INITIALIZED); |
- pending_config_mode_state_.reset(new PendingConfigureDataTypesState()); |
- pending_config_mode_state_->ready_task = ready_task; |
- pending_config_mode_state_->types_to_add = types_to_add_with_nigori; |
- pending_config_mode_state_->added_types = |
- registrar_->ConfigureDataTypes(types_to_add_with_nigori, |
- types_to_remove_with_nigori); |
- pending_config_mode_state_->reason = reason; |
- pending_config_mode_state_->retry_callback = retry_callback; |
- |
- // Cleanup disabled types before starting configuration so that |
- // callers can assume that the data types are cleaned up once |
- // configuration is done. |
- if (!types_to_remove_with_nigori.Empty()) { |
- syncer::ModelSafeRoutingInfo routing_info; |
- registrar_->GetModelSafeRoutingInfo(&routing_info); |
- sync_thread_.message_loop()->PostTask( |
- FROM_HERE, |
- base::Bind(&SyncBackendHost::Core::DoRequestCleanupDisabledTypes, |
- core_.get(), |
- routing_info)); |
- } |
- |
- StartConfiguration( |
- base::Bind(&SyncBackendHost::Core::FinishConfigureDataTypes, |
- core_.get())); |
-} |
- |
-void SyncBackendHost::StartConfiguration(const base::Closure& callback) { |
- // Put syncer in the config mode. DTM will put us in normal mode once it is |
- // done. This is to ensure we dont do a normal sync when we are doing model |
- // association. |
- sync_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
- &SyncBackendHost::Core::DoStartConfiguration, core_.get(), callback)); |
+ // The new set of enabled types is types_to_add_with_nigori + the |
+ // previously enabled types (on restart, the preferred types are already |
+ // enabled) - types_to_remove_with_nigori. After reconfiguring the registrar, |
+ // the new routing info will reflect the set of enabled types. |
+ syncer::ModelSafeRoutingInfo routing_info; |
+ registrar_->ConfigureDataTypes(types_to_add_with_nigori, |
+ types_to_remove_with_nigori); |
+ registrar_->GetModelSafeRoutingInfo(&routing_info); |
+ const syncer::ModelTypeSet enabled_types = |
+ GetRoutingInfoTypes(routing_info); |
+ |
+ // Figure out which types need to actually be downloaded. We pass those on |
+ // to the syncer while it's in configuration mode so that they can be |
+ // downloaded before we perform association. Once we switch to normal mode |
+ // downloads will get applied normally and hit the datatype's change |
+ // processor. |
+ // A datatype is in need of downloading if any of the following are true: |
+ // 1. it's enabled and initial_sync_ended is false (initial_sync_ended is |
+ // set after applying updates, and hence is a more conservative measure |
+ // than having a non-empty progress marker, which is set during |
+ // StoreTimestamps). |
+ // 2. the type is NIGORI, and any other datatype is being downloaded (nigori |
+ // is always included if we download a datatype). |
+ // TODO(sync): consider moving this logic onto the sync thread (perhaps |
+ // as part of SyncManager::ConfigureSyncer). |
+ syncer::ModelTypeSet initial_sync_ended_types = |
+ core_->sync_manager()->InitialSyncEndedTypes(); |
+ initial_sync_ended_types.RetainAll(enabled_types); |
+ syncer::ModelTypeSet types_to_config = |
+ Difference(enabled_types, initial_sync_ended_types); |
+ if (!types_to_config.Empty() && enabled_types.Has(syncer::NIGORI)) |
+ types_to_config.Put(syncer::NIGORI); |
+ |
+ SDVLOG(1) << "Types " |
+ << syncer::ModelTypeSetToString(types_to_config) |
+ << " added; calling DoConfigureSyncer"; |
+ // TODO(zea): figure out how to bypass this call if no types are being |
+ // configured and GetKey is not needed. For now we rely on determining the |
+ // need for GetKey as part of the SyncManager::ConfigureSyncer logic. |
+ RequestConfigureSyncer(reason, |
+ types_to_config, |
+ routing_info, |
+ ready_task, |
+ retry_callback); |
} |
void SyncBackendHost::EnableEncryptEverything() { |
@@ -703,159 +715,58 @@ void SyncBackendHost::GetModelSafeRoutingInfo( |
} |
} |
+bool SyncBackendHost::StartSyncThread() { |
+ if (!sync_thread_.IsRunning()) |
+ return sync_thread_.Start(); |
+ return true; |
+} |
+ |
void SyncBackendHost::InitCore(const DoInitializeOptions& options) { |
sync_thread_.message_loop()->PostTask(FROM_HERE, |
base::Bind(&SyncBackendHost::Core::DoInitialize, core_.get(), options)); |
} |
-void SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop( |
- const SyncSessionSnapshot& snapshot) { |
- if (!frontend_) |
- return; |
- DCHECK_EQ(MessageLoop::current(), frontend_loop_); |
- |
- last_snapshot_ = snapshot; |
- |
- SDVLOG(1) << "Got snapshot " << snapshot.ToString(); |
- |
- const syncer::ModelTypeSet to_migrate = |
- snapshot.model_neutral_state().types_needing_local_migration; |
- if (!to_migrate.Empty()) |
- frontend_->OnMigrationNeededForTypes(to_migrate); |
- |
- // Process any changes to the datatypes we're syncing. |
- // TODO(sync): add support for removing types. |
- if (initialized()) |
- AddExperimentalTypes(); |
- |
- // If we are waiting for a configuration change, check here to see |
- // if this sync cycle has initialized all of the types we've been |
- // waiting for. |
- if (pending_download_state_.get()) { |
- const syncer::ModelTypeSet types_to_add = |
- pending_download_state_->types_to_add; |
- const syncer::ModelTypeSet added_types = |
- pending_download_state_->added_types; |
- DCHECK(types_to_add.HasAll(added_types)); |
- const syncer::ModelTypeSet initial_sync_ended = |
- snapshot.initial_sync_ended(); |
- const syncer::ModelTypeSet failed_configuration_types = |
- Difference(added_types, initial_sync_ended); |
- SDVLOG(1) |
- << "Added types: " |
- << syncer::ModelTypeSetToString(added_types) |
- << ", configured types: " |
- << syncer::ModelTypeSetToString(initial_sync_ended) |
- << ", failed configuration types: " |
- << syncer::ModelTypeSetToString(failed_configuration_types); |
- |
- if (!failed_configuration_types.Empty() && |
- snapshot.retry_scheduled()) { |
- // Inform the caller that download failed but we are retrying. |
- if (!pending_download_state_->retry_in_progress) { |
- pending_download_state_->retry_callback.Run(); |
- pending_download_state_->retry_in_progress = true; |
- } |
- // Nothing more to do. |
- return; |
- } |
- |
- scoped_ptr<PendingConfigureDataTypesState> state( |
- pending_download_state_.release()); |
- state->ready_task.Run(failed_configuration_types); |
- |
- // Syncer did not report an error but did not download everything |
- // we requested either. So abort. The caller of the config will cleanup. |
- if (!failed_configuration_types.Empty()) |
- return; |
- } |
- |
- if (initialized()) |
- frontend_->OnSyncCycleCompleted(); |
-} |
- |
-void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop() { |
- DCHECK_EQ(MessageLoop::current(), frontend_loop_); |
- // Nudge the syncer. This is necessary for both datatype addition/deletion. |
- // |
- // Deletions need a nudge in order to ensure the deletion occurs in a timely |
- // manner (see issue 56416). |
- // |
- // In the case of additions, on the next sync cycle, the syncer should |
- // notice that the routing info has changed and start the process of |
- // downloading updates for newly added data types. Once this is |
- // complete, the configure_state_.ready_task_ is run via an |
- // OnInitializationComplete notification. |
- |
- SDVLOG(1) << "Syncer in config mode. SBH executing " |
- << "FinishConfigureDataTypesOnFrontendLoop"; |
- |
- syncer::ModelSafeRoutingInfo routing_info; |
- registrar_->GetModelSafeRoutingInfo(&routing_info); |
- const syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info); |
+void SyncBackendHost::RequestConfigureSyncer( |
+ syncer::ConfigureReason reason, |
+ syncer::ModelTypeSet types_to_config, |
+ const syncer::ModelSafeRoutingInfo& routing_info, |
+ const base::Callback<void(syncer::ModelTypeSet)>& ready_task, |
+ const base::Closure& retry_callback) { |
+ sync_thread_.message_loop()->PostTask(FROM_HERE, |
+ base::Bind(&SyncBackendHost::Core::DoConfigureSyncer, |
+ core_.get(), |
+ reason, |
+ types_to_config, |
+ routing_info, |
+ ready_task, |
+ retry_callback)); |
+} |
+ |
+void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop( |
+ syncer::ModelTypeSet types_to_configure, |
+ syncer::ModelTypeSet configured_types, |
+ const base::Callback<void(syncer::ModelTypeSet)>& ready_task) { |
+ const syncer::ModelTypeSet failed_configuration_types = |
+ Difference(types_to_configure, configured_types); |
+ SDVLOG(1) |
+ << "Added types: " |
+ << syncer::ModelTypeSetToString(types_to_configure) |
+ << ", configured types: " |
+ << syncer::ModelTypeSetToString(configured_types) |
+ << ", failed configuration types: " |
+ << syncer::ModelTypeSetToString(failed_configuration_types); |
// Update |chrome_sync_notification_bridge_|'s enabled types here as it has |
// to happen on the UI thread. |
- chrome_sync_notification_bridge_.UpdateEnabledTypes(enabled_types); |
- |
- if (pending_config_mode_state_->added_types.Empty() && |
- !core_->sync_manager()->InitialSyncEndedTypes().HasAll(enabled_types)) { |
- |
- // TODO(tim): Log / UMA / count this somehow? |
- // Add only the types with empty progress markers. Note: it is possible |
- // that some types have their initial_sync_ended be false but with non |
- // empty progress marker. Which is ok as the rest of the changes would |
- // be downloaded on a regular nudge and initial_sync_ended should be set |
- // to true. However this is a very corner case. So it is not explicitly |
- // handled. |
- pending_config_mode_state_->added_types = |
- syncer::GetTypesWithEmptyProgressMarkerToken(enabled_types, |
- GetUserShare()); |
- } |
- |
- // If we've added types, we always want to request a nudge/config (even if |
- // the initial sync is ended), in case we could not decrypt the data. |
- if (pending_config_mode_state_->added_types.Empty()) { |
- SDVLOG(1) << "No new types added; calling ready_task directly"; |
- // No new types - just notify the caller that the types are available. |
- const syncer::ModelTypeSet failed_configuration_types; |
- pending_config_mode_state_->ready_task.Run(failed_configuration_types); |
- } else { |
- pending_download_state_.reset(pending_config_mode_state_.release()); |
- |
- // Always configure nigori if it's enabled. |
- syncer::ModelTypeSet types_to_config = pending_download_state_->added_types; |
- if (IsNigoriEnabled()) { |
- // Note: Nigori is the only type that gets added with a nonempty |
- // progress marker during config. If the server returns a migration |
- // error then we will go into unrecoverable error. We dont handle it |
- // explicitly because server might help us out here by not sending a |
- // migraiton error for nigori during config. |
- types_to_config.Put(syncer::NIGORI); |
- } |
- SDVLOG(1) << "Types " |
- << syncer::ModelTypeSetToString(types_to_config) |
- << " added; calling DoRequestConfig"; |
- syncer::ModelSafeRoutingInfo routing_info; |
- registrar_->GetModelSafeRoutingInfo(&routing_info); |
- sync_thread_.message_loop()->PostTask(FROM_HERE, |
- base::Bind(&SyncBackendHost::Core::DoRequestConfig, |
- core_.get(), |
- routing_info, |
- types_to_config, |
- pending_download_state_->reason)); |
- } |
- |
- pending_config_mode_state_.reset(); |
+ chrome_sync_notification_bridge_.UpdateEnabledTypes(configured_types); |
// Notify SyncManager (especially the notification listener) about new types. |
sync_thread_.message_loop()->PostTask(FROM_HERE, |
base::Bind(&SyncBackendHost::Core::DoUpdateEnabledTypes, core_.get(), |
- enabled_types)); |
-} |
+ configured_types)); |
-bool SyncBackendHost::IsDownloadingNigoriForTest() const { |
- return initialization_state_ == DOWNLOADING_NIGORI; |
+ if (!ready_task.is_null()) |
+ ready_task.Run(failed_configuration_types); |
} |
SyncBackendHost::DoInitializeOptions::DoInitializeOptions( |
@@ -870,6 +781,7 @@ SyncBackendHost::DoInitializeOptions::DoInitializeOptions( |
const syncer::SyncCredentials& credentials, |
ChromeSyncNotificationBridge* chrome_sync_notification_bridge, |
syncer::SyncNotifierFactory* sync_notifier_factory, |
+ syncer::SyncManagerFactory* sync_manager_factory, |
bool delete_sync_data_folder, |
const std::string& restored_key_for_bootstrapping, |
syncer::SyncManager::TestingMode testing_mode, |
@@ -887,6 +799,7 @@ SyncBackendHost::DoInitializeOptions::DoInitializeOptions( |
credentials(credentials), |
chrome_sync_notification_bridge(chrome_sync_notification_bridge), |
sync_notifier_factory(sync_notifier_factory), |
+ sync_manager_factory(sync_manager_factory), |
delete_sync_data_folder(delete_sync_data_folder), |
restored_key_for_bootstrapping(restored_key_for_bootstrapping), |
testing_mode(testing_mode), |
@@ -913,14 +826,6 @@ SyncBackendHost::Core::~Core() { |
DCHECK(!sync_loop_); |
} |
-SyncBackendHost::PendingConfigureDataTypesState:: |
-PendingConfigureDataTypesState() |
- : reason(syncer::CONFIGURE_REASON_UNKNOWN), |
- retry_in_progress(false) {} |
- |
-SyncBackendHost::PendingConfigureDataTypesState:: |
-~PendingConfigureDataTypesState() {} |
- |
void SyncBackendHost::Core::OnSyncCycleCompleted( |
const SyncSessionSnapshot& snapshot) { |
if (!sync_loop_) |
@@ -1061,7 +966,7 @@ void SyncBackendHost::Core::DoInitialize(const DoInitializeOptions& options) { |
registrar_ = options.registrar; |
DCHECK(registrar_); |
- sync_manager_.reset(new syncer::SyncManager(name_)); |
+ sync_manager_ = options.sync_manager_factory->CreateSyncManager(name_); |
sync_manager_->AddObserver(this); |
success = sync_manager_->Init( |
sync_data_folder_path_, |
@@ -1070,15 +975,15 @@ void SyncBackendHost::Core::DoInitialize(const DoInitializeOptions& options) { |
options.service_url.EffectiveIntPort(), |
options.service_url.SchemeIsSecure(), |
BrowserThread::GetBlockingPool(), |
- options.make_http_bridge_factory_fn.Run(), |
+ options.make_http_bridge_factory_fn.Run().Pass(), |
options.routing_info, |
options.workers, |
options.extensions_activity_monitor, |
options.registrar /* as SyncManager::ChangeDelegate */, |
options.credentials, |
- new BridgedSyncNotifier( |
+ scoped_ptr<syncer::SyncNotifier>(new BridgedSyncNotifier( |
options.chrome_sync_notification_bridge, |
- options.sync_notifier_factory->CreateSyncNotifier()), |
+ options.sync_notifier_factory->CreateSyncNotifier())), |
options.restored_key_for_bootstrapping, |
options.testing_mode, |
&encryptor_, |
@@ -1116,12 +1021,6 @@ void SyncBackendHost::Core::DoStartSyncing( |
sync_manager_->StartSyncingNormally(routing_info); |
} |
-void SyncBackendHost::Core::DoRequestCleanupDisabledTypes( |
- const syncer::ModelSafeRoutingInfo& routing_info) { |
- DCHECK_EQ(MessageLoop::current(), sync_loop_); |
- sync_manager_->RequestCleanupDisabledTypes(routing_info); |
-} |
- |
void SyncBackendHost::Core::DoSetEncryptionPassphrase( |
const std::string& passphrase, |
bool is_explicit) { |
@@ -1173,18 +1072,46 @@ void SyncBackendHost::Core::DoShutdown(bool sync_disabled) { |
host_.Reset(); |
} |
-void SyncBackendHost::Core::DoRequestConfig( |
- const syncer::ModelSafeRoutingInfo& routing_info, |
+void SyncBackendHost::Core::DoConfigureSyncer( |
+ syncer::ConfigureReason reason, |
syncer::ModelTypeSet types_to_config, |
- syncer::ConfigureReason reason) { |
+ const syncer::ModelSafeRoutingInfo routing_info, |
+ const base::Callback<void(syncer::ModelTypeSet)>& ready_task, |
+ const base::Closure& retry_callback) { |
DCHECK_EQ(MessageLoop::current(), sync_loop_); |
- sync_manager_->RequestConfig(routing_info, types_to_config, reason); |
+ sync_manager_->ConfigureSyncer( |
+ reason, |
+ types_to_config, |
+ routing_info, |
+ base::Bind(&SyncBackendHost::Core::DoFinishConfigureDataTypes, |
+ this, |
+ types_to_config, |
+ ready_task), |
+ base::Bind(&SyncBackendHost::Core::DoRetryConfiguration, |
+ this, |
+ retry_callback)); |
} |
-void SyncBackendHost::Core::DoStartConfiguration( |
- const base::Closure& callback) { |
+void SyncBackendHost::Core::DoFinishConfigureDataTypes( |
+ syncer::ModelTypeSet types_to_config, |
+ const base::Callback<void(syncer::ModelTypeSet)>& ready_task) { |
DCHECK_EQ(MessageLoop::current(), sync_loop_); |
- sync_manager_->StartConfigurationMode(callback); |
+ syncer::ModelTypeSet configured_types = |
+ sync_manager_->InitialSyncEndedTypes(); |
+ configured_types.RetainAll(types_to_config); |
+ host_.Call(FROM_HERE, |
+ &SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop, |
+ types_to_config, |
+ configured_types, |
+ ready_task); |
+} |
+ |
+void SyncBackendHost::Core::DoRetryConfiguration( |
+ const base::Closure& retry_callback) { |
+ DCHECK_EQ(MessageLoop::current(), sync_loop_); |
+ host_.Call(FROM_HERE, |
+ &SyncBackendHost::RetryConfigurationOnFrontendLoop, |
+ retry_callback); |
} |
void SyncBackendHost::Core::DeleteSyncDataFolder() { |
@@ -1195,13 +1122,6 @@ void SyncBackendHost::Core::DeleteSyncDataFolder() { |
} |
} |
-void SyncBackendHost::Core::FinishConfigureDataTypes() { |
- DCHECK_EQ(MessageLoop::current(), sync_loop_); |
- host_.Call( |
- FROM_HERE, |
- &SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop); |
-} |
- |
void SyncBackendHost::Core::StartSavingChanges() { |
// We may already be shut down. |
if (!sync_loop_) |
@@ -1234,6 +1154,21 @@ void SyncBackendHost::OnNigoriDownloadRetry() { |
frontend_->OnSyncConfigureRetry(); |
} |
+namespace { |
+ |
+syncer::ModelTypeSet GetPartiallySyncedTypes( |
+ syncer::SyncManager* sync_manager) { |
+ syncer::ModelTypeSet partially_synced_types = |
+ syncer::ModelTypeSet::All(); |
+ partially_synced_types.RemoveAll(sync_manager->InitialSyncEndedTypes()); |
+ partially_synced_types.RemoveAll( |
+ sync_manager->GetTypesWithEmptyProgressMarkerToken( |
+ syncer::ModelTypeSet::All())); |
+ return partially_synced_types; |
+} |
+ |
+} // namespace |
+ |
void SyncBackendHost::HandleInitializationCompletedOnFrontendLoop( |
const syncer::WeakHandle<syncer::JsBackend>& js_backend, bool success) { |
DCHECK_NE(NOT_ATTEMPTED, initialization_state_); |
@@ -1253,17 +1188,61 @@ void SyncBackendHost::HandleInitializationCompletedOnFrontendLoop( |
return; |
} |
- // If setup has completed, start off in DOWNLOADING_NIGORI so that |
- // we start off by refreshing nigori. |
- CHECK(sync_prefs_.get()); |
- if (sync_prefs_->HasSyncSetupCompleted() && |
- initialization_state_ < DOWNLOADING_NIGORI) { |
- initialization_state_ = DOWNLOADING_NIGORI; |
- } |
- |
// Run initialization state machine. |
switch (initialization_state_) { |
- case NOT_INITIALIZED: |
+ case NOT_INITIALIZED: { |
+ NigoriState nigori_state; |
+ syncer::ModelTypeSet partially_synced_types = GetPartiallySyncedTypes( |
+ core_->sync_manager()); |
+ |
+ // Although it's possible for any type to be in a partially downloaded |
+ // state, we only care about nigori as it's the only one we download |
+ // before the backend is fully initialized. Other types will be |
+ // re-downloaded at configuration time, at which point we can handle |
+ // migrations and other events. |
+ UMA_HISTOGRAM_COUNTS("Sync.PartiallySyncedTypes", |
+ partially_synced_types.Size()); |
+ |
+ if (partially_synced_types.Has(syncer::NIGORI)) { |
+ // Configure without nigori to force it to be cleaned ( |
+ // SyncBackendRegistrar will remove nigori from routing info as part |
+ // of the configuration). |
+ nigori_state = WITHOUT_NIGORI; |
+ initialization_state_ = CLEANING_NIGORI; |
+ } else { |
+ // Normal configuration. Will do nothing if the nigori is already |
+ // downloaded and applied. |
+ nigori_state = WITH_NIGORI; |
+ initialization_state_ = DOWNLOADING_NIGORI; |
+ } |
+ ConfigureDataTypes( |
+ syncer::CONFIGURE_REASON_NEW_CLIENT, |
+ syncer::ModelTypeSet(), |
+ syncer::ModelTypeSet(), |
+ nigori_state, |
+ // Calls back into this function. |
+ base::Bind( |
+ &SyncBackendHost:: |
+ HandleNigoriConfigurationCompletedOnFrontendLoop, |
+ weak_ptr_factory_.GetWeakPtr(), js_backend), |
+ base::Bind(&SyncBackendHost::OnNigoriDownloadRetry, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ break; |
+ } |
+ case CLEANING_NIGORI: { |
+ syncer::ModelTypeSet partially_synced_types = GetPartiallySyncedTypes( |
+ core_->sync_manager()); |
+ if (partially_synced_types.Has(syncer::NIGORI)) { |
+ // We apparently failed to clean the nigori somehow. Attempting |
+ // to continue could lead to crashes (see bug 133219), so we fail |
+ // gracefully instead by triggering an unrecoverable error. |
+ LOG(ERROR) << "Failed to cleanup partial nigori."; |
+ initialization_state_ = NOT_INITIALIZED; |
+ frontend_->OnBackendInitialized( |
+ syncer::WeakHandle<syncer::JsBackend>(), false); |
+ return; |
+ } |
+ |
initialization_state_ = DOWNLOADING_NIGORI; |
ConfigureDataTypes( |
syncer::CONFIGURE_REASON_NEW_CLIENT, |
@@ -1278,6 +1257,7 @@ void SyncBackendHost::HandleInitializationCompletedOnFrontendLoop( |
base::Bind(&SyncBackendHost::OnNigoriDownloadRetry, |
weak_ptr_factory_.GetWeakPtr())); |
break; |
+ } |
case DOWNLOADING_NIGORI: |
initialization_state_ = REFRESHING_NIGORI; |
// Triggers OnEncryptedTypesChanged() and OnEncryptionComplete() |
@@ -1301,6 +1281,36 @@ void SyncBackendHost::HandleInitializationCompletedOnFrontendLoop( |
} |
} |
+void SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop( |
+ const SyncSessionSnapshot& snapshot) { |
+ if (!frontend_) |
+ return; |
+ DCHECK_EQ(MessageLoop::current(), frontend_loop_); |
+ |
+ last_snapshot_ = snapshot; |
+ |
+ SDVLOG(1) << "Got snapshot " << snapshot.ToString(); |
+ |
+ const syncer::ModelTypeSet to_migrate = |
+ snapshot.model_neutral_state().types_needing_local_migration; |
+ if (!to_migrate.Empty()) |
+ frontend_->OnMigrationNeededForTypes(to_migrate); |
+ |
+ // Process any changes to the datatypes we're syncing. |
+ // TODO(sync): add support for removing types. |
+ if (initialized()) |
+ AddExperimentalTypes(); |
+ |
+ if (initialized()) |
+ frontend_->OnSyncCycleCompleted(); |
+} |
+ |
+void SyncBackendHost::RetryConfigurationOnFrontendLoop( |
+ const base::Closure& retry_callback) { |
+ SDVLOG(1) << "Failed to complete configuration, informing of retry."; |
+ retry_callback.Run(); |
+} |
+ |
void SyncBackendHost::PersistEncryptionBootstrapToken( |
const std::string& token) { |
CHECK(sync_prefs_.get()); |