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

Unified Diff: chrome/browser/sync/glue/sync_backend_host.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.cc
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
index 0c7c3b3631ad0d31374ff457040dafca23ce57e5..b45142a0d0cd898584ae4282e9d70864c9cb6bfe 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -4,1608 +4,10 @@
#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include <algorithm>
-#include <map>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/location.h"
-#include "base/metrics/histogram.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/timer/timer.h"
-#include "base/tracked_objects.h"
-#include "build/build_config.h"
-#include "chrome/browser/invalidation/invalidation_service.h"
-#include "chrome/browser/invalidation/invalidation_service_factory.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/network_time/network_time_tracker.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/token_service.h"
-#include "chrome/browser/signin/token_service_factory.h"
-#include "chrome/browser/sync/glue/change_processor.h"
-#include "chrome/browser/sync/glue/chrome_encryptor.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/browser/sync/sync_prefs.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/chrome_version_info.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/common/content_client.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "jingle/notifier/base/notification_method.h"
-#include "jingle/notifier/base/notifier_options.h"
-#include "net/base/host_port_pair.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "sync/internal_api/public/base/cancelation_signal.h"
-#include "sync/internal_api/public/base_transaction.h"
-#include "sync/internal_api/public/engine/model_safe_worker.h"
-#include "sync/internal_api/public/http_bridge.h"
-#include "sync/internal_api/public/internal_components_factory_impl.h"
-#include "sync/internal_api/public/read_transaction.h"
-#include "sync/internal_api/public/sync_manager_factory.h"
-#include "sync/internal_api/public/util/experiments.h"
-#include "sync/internal_api/public/util/sync_string_conversions.h"
-#include "sync/protocol/encryption.pb.h"
-#include "sync/protocol/sync.pb.h"
-#include "sync/util/nigori.h"
-
-static const int kSaveChangesIntervalSeconds = 10;
-static const base::FilePath::CharType kSyncDataFolderName[] =
- FILE_PATH_LITERAL("Sync Data");
-
-typedef TokenService::TokenAvailableDetails TokenAvailableDetails;
-
-typedef GoogleServiceAuthError AuthError;
-
namespace browser_sync {
-using content::BrowserThread;
-using syncer::InternalComponentsFactory;
-using syncer::InternalComponentsFactoryImpl;
-using syncer::sessions::SyncSessionSnapshot;
-using syncer::SyncCredentials;
-
-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
-};
-
-// Helper struct to handle currying params to
-// SyncBackendHost::Core::DoConfigureSyncer.
-struct DoConfigureSyncerTypes {
- DoConfigureSyncerTypes() {}
- ~DoConfigureSyncerTypes() {}
- syncer::ModelTypeSet to_download;
- syncer::ModelTypeSet to_purge;
- syncer::ModelTypeSet to_journal;
- syncer::ModelTypeSet to_unapply;
-};
-
-} // namespace
-
-// 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_ << ": "
-
-class SyncBackendHost::Core
- : public base::RefCountedThreadSafe<SyncBackendHost::Core>,
- public syncer::SyncEncryptionHandler::Observer,
- public syncer::SyncManager::Observer {
- public:
- Core(const std::string& name,
- const base::FilePath& sync_data_folder_path,
- bool has_sync_setup_completed,
- const base::WeakPtr<SyncBackendHost>& backend);
-
- // SyncManager::Observer implementation. The Core just acts like an air
- // traffic controller here, forwarding incoming messages to appropriate
- // landing threads.
- virtual void OnSyncCycleCompleted(
- const syncer::sessions::SyncSessionSnapshot& snapshot) OVERRIDE;
- virtual void OnInitializationComplete(
- const syncer::WeakHandle<syncer::JsBackend>& js_backend,
- const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
- debug_info_listener,
- bool success,
- syncer::ModelTypeSet restored_types) OVERRIDE;
- virtual void OnConnectionStatusChange(
- syncer::ConnectionStatus status) OVERRIDE;
- virtual void OnStopSyncingPermanently() OVERRIDE;
- virtual void OnActionableError(
- const syncer::SyncProtocolError& sync_error) OVERRIDE;
-
- // SyncEncryptionHandler::Observer implementation.
- virtual void OnPassphraseRequired(
- syncer::PassphraseRequiredReason reason,
- const sync_pb::EncryptedData& pending_keys) OVERRIDE;
- virtual void OnPassphraseAccepted() OVERRIDE;
- virtual void OnBootstrapTokenUpdated(
- const std::string& bootstrap_token,
- syncer::BootstrapTokenType type) OVERRIDE;
- virtual void OnEncryptedTypesChanged(
- syncer::ModelTypeSet encrypted_types,
- bool encrypt_everything) OVERRIDE;
- virtual void OnEncryptionComplete() OVERRIDE;
- virtual void OnCryptographerStateChanged(
- syncer::Cryptographer* cryptographer) OVERRIDE;
- virtual void OnPassphraseTypeChanged(syncer::PassphraseType type,
- base::Time passphrase_time) OVERRIDE;
-
- // Forwards an invalidation state change to the sync manager.
- void DoOnInvalidatorStateChange(syncer::InvalidatorState state);
-
- // Forwards an invalidation to the sync manager.
- void DoOnIncomingInvalidation(
- syncer::ObjectIdInvalidationMap invalidation_map);
-
- // Note:
- //
- // The Do* methods are the various entry points from our
- // SyncBackendHost. They are all called on the sync thread to
- // actually perform synchronous (and potentially blocking) syncapi
- // operations.
- //
- // Called to perform initialization of the syncapi on behalf of
- // SyncBackendHost::Initialize.
- void DoInitialize(scoped_ptr<DoInitializeOptions> options);
-
- // Called to perform credential update on behalf of
- // SyncBackendHost::UpdateCredentials.
- void DoUpdateCredentials(const syncer::SyncCredentials& credentials);
-
- // Called to tell the syncapi to start syncing (generally after
- // initialization and authentication).
- void DoStartSyncing(const syncer::ModelSafeRoutingInfo& routing_info);
-
- // Called to set the passphrase for encryption.
- void DoSetEncryptionPassphrase(const std::string& passphrase,
- bool is_explicit);
-
- // Called to decrypt the pending keys.
- void DoSetDecryptionPassphrase(const std::string& passphrase);
-
- // Called to turn on encryption of all sync data as well as
- // reencrypt everything.
- void DoEnableEncryptEverything();
-
- // Ask the syncer to check for updates for the specified types.
- void DoRefreshTypes(syncer::ModelTypeSet types);
-
- // Invoked if we failed to download the necessary control types at startup.
- // Invokes SyncBackendHost::HandleControlTypesDownloadRetry.
- void OnControlTypesDownloadRetry();
-
- // Called to perform tasks which require the control data to be downloaded.
- // This includes refreshing encryption, setting up the device info change
- // processor, etc.
- void DoInitialProcessControlTypes();
-
- // Some parts of DoInitialProcessControlTypes() may be executed on a different
- // thread. This function asynchronously continues the work started in
- // DoInitialProcessControlTypes() once that other thread gets back to us.
- void DoFinishInitialProcessControlTypes();
-
- // The shutdown order is a bit complicated:
- // 1) Call ShutdownOnUIThread() from |frontend_loop_| to request sync manager
- // to stop as soon as possible.
- // 2) Post DoShutdown() to sync loop to clean up backend state, save
- // directory and destroy sync manager.
- void ShutdownOnUIThread();
- void DoShutdown(bool sync_disabled);
- void DoDestroySyncManager();
-
- // Configuration methods that must execute on sync loop.
- void 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);
- void DoFinishConfigureDataTypes(
- syncer::ModelTypeSet types_to_config,
- const base::Callback<void(syncer::ModelTypeSet,
- 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
- // on the IO thread. Must be removed from IO thread.
-
- syncer::SyncManager* sync_manager() { return sync_manager_.get(); }
-
- SyncedDeviceTracker* synced_device_tracker() {
- return synced_device_tracker_.get();
- }
-
- // Delete the sync data folder to cleanup backend data. Happens the first
- // time sync is enabled for a user (to prevent accidentally reusing old
- // sync databases), as well as shutdown when you're no longer syncing.
- void DeleteSyncDataFolder();
-
- // We expose this member because it's required in the construction of the
- // HttpBridgeFactory.
- syncer::CancelationSignal* GetRequestContextCancelationSignal() {
- return &release_request_context_signal_;
- }
-
- private:
- friend class base::RefCountedThreadSafe<SyncBackendHost::Core>;
- friend class SyncBackendHostForProfileSyncTest;
-
- virtual ~Core();
-
- // Invoked when initialization of syncapi is complete and we can start
- // our timer.
- // This must be called from the thread on which SaveChanges is intended to
- // be run on; the host's |registrar_->sync_thread()|.
- void StartSavingChanges();
-
- // Invoked periodically to tell the syncapi to persist its state
- // by writing to disk.
- // This is called from the thread we were created on (which is sync thread),
- // using a repeating timer that is kicked off as soon as the SyncManager
- // tells us it completed initialization.
- void SaveChanges();
-
- // Name used for debugging.
- const std::string name_;
-
- // Path of the folder that stores the sync data files.
- const base::FilePath sync_data_folder_path_;
-
- // Our parent SyncBackendHost.
- syncer::WeakHandle<SyncBackendHost> host_;
-
- // The loop where all the sync backend operations happen.
- // Non-NULL only between calls to DoInitialize() and ~Core().
- base::MessageLoop* sync_loop_;
-
- // Our parent's registrar (not owned). Non-NULL only between
- // calls to DoInitialize() and DoShutdown().
- SyncBackendRegistrar* registrar_;
-
- // The timer used to periodically call SaveChanges.
- scoped_ptr<base::RepeatingTimer<Core> > save_changes_timer_;
-
- // Our encryptor, which uses Chrome's encryption functions.
- ChromeEncryptor encryptor_;
-
- // A special ChangeProcessor that tracks the DEVICE_INFO type for us.
- scoped_ptr<SyncedDeviceTracker> synced_device_tracker_;
-
- // The top-level syncapi entry point. Lives on the sync thread.
- scoped_ptr<syncer::SyncManager> sync_manager_;
-
- // Temporary holder of sync manager's initialization results. Set by
- // OnInitializeComplete, and consumed when we pass it via OnBackendInitialized
- // in the final state of HandleInitializationSuccessOnFrontendLoop.
- syncer::WeakHandle<syncer::JsBackend> js_backend_;
- syncer::WeakHandle<syncer::DataTypeDebugInfoListener> debug_info_listener_;
-
- // These signals allow us to send requests to shut down the HttpBridgeFactory
- // and ServerConnectionManager without having to wait for those classes to
- // finish initializing first.
- //
- // See comments in Core::ShutdownOnUIThread() for more details.
- syncer::CancelationSignal release_request_context_signal_;
- syncer::CancelationSignal stop_syncing_signal_;
-
- // Matches the value of SyncPref's HasSyncSetupCompleted() flag at init time.
- // Should not be used for anything except for UMAs and logging.
- const bool has_sync_setup_completed_;
-
- base::WeakPtrFactory<Core> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-SyncBackendHost::SyncBackendHost(
- const std::string& name,
- Profile* profile,
- const base::WeakPtr<SyncPrefs>& sync_prefs)
- : frontend_loop_(base::MessageLoop::current()),
- profile_(profile),
- name_(name),
- initialized_(false),
- sync_prefs_(sync_prefs),
- frontend_(NULL),
- cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
- invalidator_(
- invalidation::InvalidationServiceFactory::GetForProfile(profile)),
- invalidation_handler_registered_(false),
- weak_ptr_factory_(this) {
- core_ = new Core(name_, profile_->GetPath().Append(kSyncDataFolderName),
- sync_prefs_->HasSyncSetupCompleted(),
- weak_ptr_factory_.GetWeakPtr());
-}
-
-SyncBackendHost::SyncBackendHost(Profile* profile)
- : frontend_loop_(base::MessageLoop::current()),
- profile_(profile),
- name_("Unknown"),
- initialized_(false),
- frontend_(NULL),
- cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
- invalidation_handler_registered_(false),
- weak_ptr_factory_(this) {
-}
-
-SyncBackendHost::~SyncBackendHost() {
- DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor.";
- DCHECK(!registrar_.get());
-}
-
-void SyncBackendHost::Initialize(
- SyncFrontend* frontend,
- scoped_ptr<base::Thread> sync_thread,
- const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
- const GURL& sync_service_url,
- const SyncCredentials& credentials,
- bool delete_sync_data_folder,
- scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
- scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
- syncer::ReportUnrecoverableErrorFunction
- report_unrecoverable_error_function) {
- registrar_.reset(new SyncBackendRegistrar(name_,
- profile_,
- sync_thread.Pass()));
- CHECK(registrar_->sync_thread());
-
- frontend_ = frontend;
- DCHECK(frontend);
-
- syncer::ModelSafeRoutingInfo routing_info;
- std::vector<syncer::ModelSafeWorker*> workers;
- registrar_->GetModelSafeRoutingInfo(&routing_info);
- registrar_->GetWorkers(&workers);
-
- InternalComponentsFactory::Switches factory_switches = {
- InternalComponentsFactory::ENCRYPTION_KEYSTORE,
- InternalComponentsFactory::BACKOFF_NORMAL
- };
-
- CommandLine* cl = CommandLine::ForCurrentProcess();
- if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) {
- factory_switches.backoff_override =
- InternalComponentsFactoryImpl::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE;
- }
- if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) {
- factory_switches.pre_commit_updates_policy =
- InternalComponentsFactoryImpl::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE;
- }
-
- scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions(
- registrar_->sync_thread()->message_loop(),
- registrar_.get(),
- routing_info,
- workers,
- extensions_activity_monitor_.GetExtensionsActivity(),
- event_handler,
- sync_service_url,
- scoped_ptr<syncer::HttpPostProviderFactory>(
- new syncer::HttpBridgeFactory(
- make_scoped_refptr(profile_->GetRequestContext()),
- NetworkTimeTracker::BuildNotifierUpdateCallback(),
- core_->GetRequestContextCancelationSignal())),
- credentials,
- invalidator_->GetInvalidatorClientId(),
- sync_manager_factory.Pass(),
- delete_sync_data_folder,
- sync_prefs_->GetEncryptionBootstrapToken(),
- sync_prefs_->GetKeystoreEncryptionBootstrapToken(),
- scoped_ptr<InternalComponentsFactory>(
- new InternalComponentsFactoryImpl(factory_switches)).Pass(),
- unrecoverable_error_handler.Pass(),
- report_unrecoverable_error_function));
- InitCore(init_opts.Pass());
-}
-
-void SyncBackendHost::UpdateCredentials(const SyncCredentials& credentials) {
- DCHECK(registrar_->sync_thread()->IsRunning());
- registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoUpdateCredentials,
- core_.get(),
- credentials));
-}
-
-void SyncBackendHost::StartSyncingWithServer() {
- SDVLOG(1) << "SyncBackendHost::StartSyncingWithServer called.";
-
- syncer::ModelSafeRoutingInfo routing_info;
- registrar_->GetModelSafeRoutingInfo(&routing_info);
-
- registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoStartSyncing,
- core_.get(), routing_info));
-}
-
-void SyncBackendHost::SetEncryptionPassphrase(const std::string& passphrase,
- bool is_explicit) {
- DCHECK(registrar_->sync_thread()->IsRunning());
- if (!IsNigoriEnabled()) {
- NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori"
- " is disabled.";
- return;
- }
-
- // We should never be called with an empty passphrase.
- DCHECK(!passphrase.empty());
-
- // This should only be called by the frontend.
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-
- // SetEncryptionPassphrase should never be called if we are currently
- // encrypted with an explicit passphrase.
- DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE ||
- cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE);
-
- // Post an encryption task on the syncer thread.
- registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoSetEncryptionPassphrase,
- core_.get(),
- passphrase, is_explicit));
-}
-
-bool SyncBackendHost::SetDecryptionPassphrase(const std::string& passphrase) {
- if (!IsNigoriEnabled()) {
- NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori"
- " is disabled.";
- return false;
- }
-
- // We should never be called with an empty passphrase.
- DCHECK(!passphrase.empty());
-
- // This should only be called by the frontend.
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-
- // This should only be called when we have cached pending keys.
- DCHECK(cached_pending_keys_.has_blob());
-
- // Check the passphrase that was provided against our local cache of the
- // cryptographer's pending keys. If this was unsuccessful, the UI layer can
- // immediately call OnPassphraseRequired without showing the user a spinner.
- if (!CheckPassphraseAgainstCachedPendingKeys(passphrase))
- return false;
-
- // Post a decryption task on the syncer thread.
- registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoSetDecryptionPassphrase,
- core_.get(),
- passphrase));
-
- // Since we were able to decrypt the cached pending keys with the passphrase
- // provided, we immediately alert the UI layer that the passphrase was
- // accepted. This will avoid the situation where a user enters a passphrase,
- // clicks OK, immediately reopens the advanced settings dialog, and gets an
- // unnecessary prompt for a passphrase.
- // Note: It is not guaranteed that the passphrase will be accepted by the
- // syncer thread, since we could receive a new nigori node while the task is
- // pending. This scenario is a valid race, and SetDecryptionPassphrase can
- // trigger a new OnPassphraseRequired if it needs to.
- NotifyPassphraseAccepted();
- return true;
-}
-
-void SyncBackendHost::StopSyncingForShutdown() {
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-
- // Immediately stop sending messages to the frontend.
- frontend_ = NULL;
-
- // Stop listening for and forwarding locally-triggered sync refresh requests.
- notification_registrar_.RemoveAll();
-
- DCHECK(registrar_->sync_thread()->IsRunning());
-
- registrar_->RequestWorkerStopOnUIThread();
-
- core_->ShutdownOnUIThread();
-}
-
-scoped_ptr<base::Thread> SyncBackendHost::Shutdown(ShutdownOption option) {
- // StopSyncingForShutdown() (which nulls out |frontend_|) should be
- // called first.
- DCHECK(!frontend_);
- DCHECK(registrar_->sync_thread()->IsRunning());
-
- bool sync_disabled = (option == DISABLE_AND_CLAIM_THREAD);
- bool sync_thread_claimed =
- (option == DISABLE_AND_CLAIM_THREAD || option == STOP_AND_CLAIM_THREAD);
-
- if (invalidation_handler_registered_) {
- if (sync_disabled) {
- UnregisterInvalidationIds();
- }
- invalidator_->UnregisterInvalidationHandler(this);
- invalidator_ = NULL;
- }
- invalidation_handler_registered_ = false;
-
- // Shut down and destroy sync manager.
- registrar_->sync_thread()->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoShutdown,
- core_.get(), sync_disabled));
- core_ = NULL;
-
- // Worker cleanup.
- SyncBackendRegistrar* detached_registrar = registrar_.release();
- detached_registrar->sync_thread()->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&SyncBackendRegistrar::Shutdown,
- base::Unretained(detached_registrar)));
-
- if (sync_thread_claimed)
- return detached_registrar->ReleaseSyncThread();
- else
- return scoped_ptr<base::Thread>();
-}
-
-void SyncBackendHost::UnregisterInvalidationIds() {
- if (invalidation_handler_registered_) {
- invalidator_->UpdateRegisteredInvalidationIds(
- this,
- syncer::ObjectIdSet());
- }
-}
-
-void SyncBackendHost::ConfigureDataTypes(
- syncer::ConfigureReason reason,
- const DataTypeConfigStateMap& config_state_map,
- const base::Callback<void(syncer::ModelTypeSet,
- syncer::ModelTypeSet)>& ready_task,
- const base::Callback<void()>& retry_callback) {
- // Only one configure is allowed at a time. This is guaranteed by our
- // callers. The SyncBackendHost requests one configure as the backend is
- // initializing and waits for it to complete. After initialization, all
- // configurations will pass through the DataTypeManager, which is careful to
- // never send a new configure request until the current request succeeds.
-
- // The SyncBackendRegistrar's routing info will be updated by adding the
- // types_to_add to the list then removing types_to_remove. Any types which
- // are not in either of those sets will remain untouched.
- //
- // Types which were not in the list previously are not fully downloaded, so we
- // must ask the syncer to download them. Any newly supported datatypes will
- // not have been in that routing info list, so they will be among the types
- // downloaded if they are enabled.
- //
- // The SyncBackendRegistrar's state was initially derived from the types
- // detected to have been downloaded in the database. Afterwards it is
- // modified only by this function. We expect it to remain in sync with the
- // backend because configuration requests are never aborted; they are retried
- // until they succeed or the backend is shut down.
-
- syncer::ModelTypeSet previous_types = registrar_->GetLastConfiguredTypes();
-
- syncer::ModelTypeSet disabled_types =
- GetDataTypesInState(DISABLED, config_state_map);
- syncer::ModelTypeSet fatal_types =
- GetDataTypesInState(FATAL, config_state_map);
- syncer::ModelTypeSet crypto_types =
- GetDataTypesInState(CRYPTO, config_state_map);
- disabled_types.PutAll(fatal_types);
- disabled_types.PutAll(crypto_types);
- syncer::ModelTypeSet active_types =
- GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
- syncer::ModelTypeSet clean_first_types =
- GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
- syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes(
- syncer::Union(active_types, clean_first_types),
- disabled_types);
- types_to_download.PutAll(clean_first_types);
- types_to_download.RemoveAll(syncer::ProxyTypes());
- if (!types_to_download.Empty())
- types_to_download.Put(syncer::NIGORI);
-
- // TODO(sync): crbug.com/137550.
- // It's dangerous to configure types that have progress markers. Types with
- // progress markers can trigger a MIGRATION_DONE response. We are not
- // prepared to handle a migration during a configure, so we must ensure that
- // all our types_to_download actually contain no data before we sync them.
- //
- // One common way to end up in this situation used to be types which
- // downloaded some or all of their data but have not applied it yet. We avoid
- // problems with those types by purging the data of any such partially synced
- // types soon after we load the directory.
- //
- // Another possible scenario is that we have newly supported or newly enabled
- // data types being downloaded here but the nigori type, which is always
- // included in any GetUpdates request, requires migration. The server has
- // code to detect this scenario based on the configure reason, the fact that
- // the nigori type is the only requested type which requires migration, and
- // that the requested types list includes at least one non-nigori type. It
- // will not send a MIGRATION_DONE response in that case. We still need to be
- // careful to not send progress markers for non-nigori types, though. If a
- // non-nigori type in the request requires migration, a MIGRATION_DONE
- // response will be sent.
-
- syncer::ModelSafeRoutingInfo routing_info;
- registrar_->GetModelSafeRoutingInfo(&routing_info);
-
- syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes();
- syncer::ModelTypeSet types_to_purge =
- syncer::Difference(previous_types, current_types);
- syncer::ModelTypeSet inactive_types =
- GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
- types_to_purge.RemoveAll(inactive_types);
-
- // If a type has already been disabled and unapplied or journaled, it will
- // not be part of the |types_to_purge| set, and therefore does not need
- // to be acted on again.
- fatal_types.RetainAll(types_to_purge);
- syncer::ModelTypeSet unapply_types =
- syncer::Union(crypto_types, clean_first_types);
- unapply_types.RetainAll(types_to_purge);
-
- DCHECK(syncer::Intersection(current_types, fatal_types).Empty());
- DCHECK(syncer::Intersection(current_types, crypto_types).Empty());
- DCHECK(current_types.HasAll(types_to_download));
-
- SDVLOG(1) << "Types "
- << syncer::ModelTypeSetToString(types_to_download)
- << " added; calling DoConfigureSyncer";
- // Divide up the types into their corresponding actions (each is mutually
- // exclusive):
- // - Types which have just been added to the routing info (types_to_download):
- // are downloaded.
- // - Types which have encountered a fatal error (fatal_types) are deleted
- // from the directory and journaled in the delete journal.
- // - Types which have encountered a cryptographer error (crypto_types) are
- // unapplied (local state is purged but sync state is not).
- // - All other types not in the routing info (types just disabled) are deleted
- // from the directory.
- // - Everything else (enabled types and already disabled types) is not
- // touched.
- RequestConfigureSyncer(reason,
- types_to_download,
- types_to_purge,
- fatal_types,
- unapply_types,
- inactive_types,
- routing_info,
- ready_task,
- retry_callback);
-}
-
-void SyncBackendHost::EnableEncryptEverything() {
- registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoEnableEncryptEverything,
- core_.get()));
-}
-
-void SyncBackendHost::ActivateDataType(
- syncer::ModelType type, syncer::ModelSafeGroup group,
- ChangeProcessor* change_processor) {
- registrar_->ActivateDataType(type, group, change_processor, GetUserShare());
-}
-
-void SyncBackendHost::DeactivateDataType(syncer::ModelType type) {
- registrar_->DeactivateDataType(type);
-}
-
-syncer::UserShare* SyncBackendHost::GetUserShare() const {
- return core_->sync_manager()->GetUserShare();
-}
-
-SyncBackendHost::Status SyncBackendHost::GetDetailedStatus() {
- DCHECK(initialized());
- return core_->sync_manager()->GetDetailedStatus();
-}
-
-SyncSessionSnapshot SyncBackendHost::GetLastSessionSnapshot() const {
- return last_snapshot_;
-}
-
-bool SyncBackendHost::HasUnsyncedItems() const {
- DCHECK(initialized());
- return core_->sync_manager()->HasUnsyncedItems();
-}
-
-bool SyncBackendHost::IsNigoriEnabled() const {
- return registrar_.get() && registrar_->IsNigoriEnabled();
-}
-
-syncer::PassphraseType SyncBackendHost::GetPassphraseType() const {
- return cached_passphrase_type_;
-}
-
-base::Time SyncBackendHost::GetExplicitPassphraseTime() const {
- return cached_explicit_passphrase_time_;
-}
-
-bool SyncBackendHost::IsCryptographerReady(
- const syncer::BaseTransaction* trans) const {
- return initialized() && trans->GetCryptographer()->is_ready();
-}
-
-void SyncBackendHost::GetModelSafeRoutingInfo(
- syncer::ModelSafeRoutingInfo* out) const {
- if (initialized()) {
- CHECK(registrar_.get());
- registrar_->GetModelSafeRoutingInfo(out);
- } else {
- NOTREACHED();
- }
-}
-
-SyncedDeviceTracker* SyncBackendHost::GetSyncedDeviceTracker() const {
- if (!initialized())
- return NULL;
- return core_->synced_device_tracker();
-}
-
-void SyncBackendHost::InitCore(scoped_ptr<DoInitializeOptions> options) {
- registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoInitialize,
- core_.get(), base::Passed(&options)));
-}
-
-void SyncBackendHost::RequestConfigureSyncer(
- syncer::ConfigureReason reason,
- syncer::ModelTypeSet to_download,
- syncer::ModelTypeSet to_purge,
- syncer::ModelTypeSet to_journal,
- syncer::ModelTypeSet to_unapply,
- syncer::ModelTypeSet to_ignore,
- const syncer::ModelSafeRoutingInfo& routing_info,
- const base::Callback<void(syncer::ModelTypeSet,
- syncer::ModelTypeSet)>& ready_task,
- const base::Closure& retry_callback) {
- DoConfigureSyncerTypes config_types;
- config_types.to_download = to_download;
- config_types.to_purge = to_purge;
- config_types.to_journal = to_journal;
- config_types.to_unapply = to_unapply;
- registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoConfigureSyncer,
- core_.get(),
- reason,
- config_types,
- routing_info,
- ready_task,
- retry_callback));
-}
-
-void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop(
- const syncer::ModelTypeSet enabled_types,
- const syncer::ModelTypeSet succeeded_configuration_types,
- const syncer::ModelTypeSet failed_configuration_types,
- const base::Callback<void(syncer::ModelTypeSet,
- syncer::ModelTypeSet)>& ready_task) {
- if (!frontend_)
- return;
-
- invalidator_->UpdateRegisteredInvalidationIds(
- this,
- ModelTypeSetToObjectIdSet(enabled_types));
-
- if (!ready_task.is_null())
- ready_task.Run(succeeded_configuration_types, failed_configuration_types);
-}
-
-void SyncBackendHost::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL);
-
- content::Details<const syncer::ModelTypeSet> state_details(details);
- const syncer::ModelTypeSet& types = *(state_details.ptr());
- registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoRefreshTypes, core_.get(), types));
-}
-
-SyncBackendHost::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<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) {
-}
-
-SyncBackendHost::DoInitializeOptions::~DoInitializeOptions() {}
-
-SyncBackendHost::Core::Core(const std::string& name,
- const base::FilePath& sync_data_folder_path,
- bool has_sync_setup_completed,
- const base::WeakPtr<SyncBackendHost>& 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());
-}
-
-SyncBackendHost::Core::~Core() {
- DCHECK(!sync_manager_.get());
-}
-
-void SyncBackendHost::Core::OnSyncCycleCompleted(
- const SyncSessionSnapshot& snapshot) {
- if (!sync_loop_)
- return;
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
-
- host_.Call(
- FROM_HERE,
- &SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop,
- snapshot);
-}
-
-void SyncBackendHost::Core::DoRefreshTypes(syncer::ModelTypeSet types) {
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- sync_manager_->RefreshTypes(types);
-}
-
-void SyncBackendHost::Core::OnControlTypesDownloadRetry() {
- host_.Call(FROM_HERE,
- &SyncBackendHost::HandleControlTypesDownloadRetry);
-}
-
-void SyncBackendHost::Core::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,
- &SyncBackendHost::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(&Core::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(&SyncBackendHost::Core::DoInitialProcessControlTypes,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&SyncBackendHost::Core::OnControlTypesDownloadRetry,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void SyncBackendHost::Core::OnConnectionStatusChange(
- syncer::ConnectionStatus status) {
- if (!sync_loop_)
- return;
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- host_.Call(
- FROM_HERE,
- &SyncBackendHost::HandleConnectionStatusChangeOnFrontendLoop, status);
-}
-
-void SyncBackendHost::Core::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,
- &SyncBackendHost::NotifyPassphraseRequired, reason, pending_keys);
-}
-
-void SyncBackendHost::Core::OnPassphraseAccepted() {
- if (!sync_loop_)
- return;
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- host_.Call(
- FROM_HERE,
- &SyncBackendHost::NotifyPassphraseAccepted);
-}
-
-void SyncBackendHost::Core::OnBootstrapTokenUpdated(
- const std::string& bootstrap_token,
- syncer::BootstrapTokenType type) {
- if (!sync_loop_)
- return;
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- host_.Call(FROM_HERE,
- &SyncBackendHost::PersistEncryptionBootstrapToken,
- bootstrap_token,
- type);
-}
-
-void SyncBackendHost::Core::OnStopSyncingPermanently() {
- if (!sync_loop_)
- return;
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- host_.Call(
- FROM_HERE,
- &SyncBackendHost::HandleStopSyncingPermanentlyOnFrontendLoop);
-}
-
-void SyncBackendHost::Core::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,
- &SyncBackendHost::NotifyEncryptedTypesChanged,
- encrypted_types, encrypt_everything);
-}
-
-void SyncBackendHost::Core::OnEncryptionComplete() {
- if (!sync_loop_)
- return;
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- // NOTE: We're in a transaction.
- host_.Call(
- FROM_HERE,
- &SyncBackendHost::NotifyEncryptionComplete);
-}
-
-void SyncBackendHost::Core::OnCryptographerStateChanged(
- syncer::Cryptographer* cryptographer) {
- // Do nothing.
-}
-
-void SyncBackendHost::Core::OnPassphraseTypeChanged(
- syncer::PassphraseType type, base::Time passphrase_time) {
- host_.Call(
- FROM_HERE,
- &SyncBackendHost::HandlePassphraseTypeChangedOnFrontendLoop,
- type, passphrase_time);
-}
-
-void SyncBackendHost::Core::OnActionableError(
- const syncer::SyncProtocolError& sync_error) {
- if (!sync_loop_)
- return;
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- host_.Call(
- FROM_HERE,
- &SyncBackendHost::HandleActionableErrorEventOnFrontendLoop,
- sync_error);
-}
-
-void SyncBackendHost::Core::DoOnInvalidatorStateChange(
- syncer::InvalidatorState state) {
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- sync_manager_->OnInvalidatorStateChange(state);
-}
-
-void SyncBackendHost::Core::DoOnIncomingInvalidation(
- syncer::ObjectIdInvalidationMap invalidation_map) {
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- sync_manager_->OnIncomingInvalidation(invalidation_map);
-}
-
-void SyncBackendHost::Core::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 SyncBackendHost::Core::DoUpdateCredentials(
- const 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 SyncBackendHost::Core::DoStartSyncing(
- const syncer::ModelSafeRoutingInfo& routing_info) {
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- sync_manager_->StartSyncingNormally(routing_info);
-}
-
-void SyncBackendHost::Core::DoSetEncryptionPassphrase(
- const std::string& passphrase,
- bool is_explicit) {
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(
- passphrase, is_explicit);
-}
-
-void SyncBackendHost::Core::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,
- &SyncBackendHost::HandleInitializationFailureOnFrontendLoop);
- return;
- }
-
- if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
- LOG(ERROR) << "Failed to download control types";
- host_.Call(
- FROM_HERE,
- &SyncBackendHost::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(&SyncBackendHost::Core::DoFinishInitialProcessControlTypes,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void SyncBackendHost::Core::DoFinishInitialProcessControlTypes() {
- registrar_->ActivateDataType(syncer::DEVICE_INFO,
- syncer::GROUP_PASSIVE,
- synced_device_tracker_.get(),
- sync_manager_->GetUserShare());
-
- host_.Call(
- FROM_HERE,
- &SyncBackendHost::HandleInitializationSuccessOnFrontendLoop,
- js_backend_,
- debug_info_listener_);
-
- js_backend_.Reset();
- debug_info_listener_.Reset();
-}
-
-void SyncBackendHost::Core::DoSetDecryptionPassphrase(
- const std::string& passphrase) {
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(
- passphrase);
-}
-
-void SyncBackendHost::Core::DoEnableEncryptEverything() {
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
-}
-
-void SyncBackendHost::Core::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 SyncBackendHost::Core::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 SyncBackendHost::Core::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 SyncBackendHost::Core::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(&SyncBackendHost::Core::DoFinishConfigureDataTypes,
- weak_ptr_factory_.GetWeakPtr(),
- config_types.to_download,
- ready_task),
- base::Bind(&SyncBackendHost::Core::DoRetryConfiguration,
- weak_ptr_factory_.GetWeakPtr(),
- retry_callback));
-}
-
-void SyncBackendHost::Core::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,
- &SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop,
- enabled_types,
- succeeded_configuration_types,
- failed_configuration_types,
- ready_task);
-}
-
-void SyncBackendHost::Core::DoRetryConfiguration(
- const base::Closure& retry_callback) {
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- host_.Call(FROM_HERE,
- &SyncBackendHost::RetryConfigurationOnFrontendLoop,
- retry_callback);
-}
-
-void SyncBackendHost::Core::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 SyncBackendHost::Core::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<Core>());
- save_changes_timer_->Start(FROM_HERE,
- base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
- this, &Core::SaveChanges);
-}
-
-void SyncBackendHost::Core::SaveChanges() {
- DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
- sync_manager_->SaveChanges();
-}
-
-void SyncBackendHost::AddExperimentalTypes() {
- CHECK(initialized());
- syncer::Experiments experiments;
- if (core_->sync_manager()->ReceivedExperiment(&experiments))
- frontend_->OnExperimentsChanged(experiments);
-}
-
-void SyncBackendHost::HandleControlTypesDownloadRetry() {
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
- if (!frontend_)
- return;
-
- frontend_->OnSyncConfigureRetry();
-}
-
-void SyncBackendHost::HandleInitializationSuccessOnFrontendLoop(
- const syncer::WeakHandle<syncer::JsBackend> js_backend,
- const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>
- debug_info_listener) {
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
- if (!frontend_)
- return;
-
- initialized_ = true;
-
- invalidator_->RegisterInvalidationHandler(this);
- invalidation_handler_registered_ = true;
-
- // Fake a state change to initialize the SyncManager's cached invalidator
- // state.
- OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
-
- // Start forwarding refresh requests to the SyncManager
- notification_registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
- content::Source<Profile>(profile_));
-
- // Now that we've downloaded the control types, we can see if there are any
- // experimental types to enable. This should be done before we inform
- // the frontend to ensure they're visible in the customize screen.
- AddExperimentalTypes();
- frontend_->OnBackendInitialized(js_backend,
- debug_info_listener,
- true);
-}
-
-void SyncBackendHost::HandleInitializationFailureOnFrontendLoop() {
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
- if (!frontend_)
- return;
-
- frontend_->OnBackendInitialized(
- syncer::WeakHandle<syncer::JsBackend>(),
- syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
- false);
-}
-
-void SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop(
- const SyncSessionSnapshot& snapshot) {
- if (!frontend_)
- return;
- DCHECK_EQ(base::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,
- syncer::BootstrapTokenType token_type) {
- CHECK(sync_prefs_.get());
- DCHECK(!token.empty());
- if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN)
- sync_prefs_->SetEncryptionBootstrapToken(token);
- else
- sync_prefs_->SetKeystoreEncryptionBootstrapToken(token);
-}
-
-void SyncBackendHost::HandleActionableErrorEventOnFrontendLoop(
- const syncer::SyncProtocolError& sync_error) {
- if (!frontend_)
- return;
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
- frontend_->OnActionableError(sync_error);
-}
-
-void SyncBackendHost::OnInvalidatorStateChange(syncer::InvalidatorState state) {
- registrar_->sync_thread()->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoOnInvalidatorStateChange,
- core_.get(),
- state));
-}
-
-void SyncBackendHost::OnIncomingInvalidation(
- const syncer::ObjectIdInvalidationMap& invalidation_map) {
- // TODO(rlarocque): Acknowledge these invalidations only after the syncer has
- // acted on them and saved the results to disk.
- syncer::ObjectIdSet ids = invalidation_map.GetObjectIds();
- for (syncer::ObjectIdSet::const_iterator it = ids.begin();
- it != ids.end(); ++it) {
- const syncer::AckHandle& handle =
- invalidation_map.ForObject(*it).back().ack_handle();
- invalidator_->AcknowledgeInvalidation(*it, handle);
- }
-
- registrar_->sync_thread()->message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&SyncBackendHost::Core::DoOnIncomingInvalidation,
- core_.get(),
- invalidation_map));
-}
-
-bool SyncBackendHost::CheckPassphraseAgainstCachedPendingKeys(
- const std::string& passphrase) const {
- DCHECK(cached_pending_keys_.has_blob());
- DCHECK(!passphrase.empty());
- syncer::Nigori nigori;
- nigori.InitByDerivation("localhost", "dummy", passphrase);
- std::string plaintext;
- bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext);
- DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys.";
- return result;
-}
-
-void SyncBackendHost::NotifyPassphraseRequired(
- syncer::PassphraseRequiredReason reason,
- sync_pb::EncryptedData pending_keys) {
- if (!frontend_)
- return;
-
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-
- // Update our cache of the cryptographer's pending keys.
- cached_pending_keys_ = pending_keys;
-
- frontend_->OnPassphraseRequired(reason, pending_keys);
-}
-
-void SyncBackendHost::NotifyPassphraseAccepted() {
- if (!frontend_)
- return;
-
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-
- // Clear our cache of the cryptographer's pending keys.
- cached_pending_keys_.clear_blob();
- frontend_->OnPassphraseAccepted();
-}
-
-void SyncBackendHost::NotifyEncryptedTypesChanged(
- syncer::ModelTypeSet encrypted_types,
- bool encrypt_everything) {
- if (!frontend_)
- return;
-
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
- frontend_->OnEncryptedTypesChanged(
- encrypted_types, encrypt_everything);
-}
-
-void SyncBackendHost::NotifyEncryptionComplete() {
- if (!frontend_)
- return;
-
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
- frontend_->OnEncryptionComplete();
-}
-
-void SyncBackendHost::HandlePassphraseTypeChangedOnFrontendLoop(
- syncer::PassphraseType type,
- base::Time explicit_passphrase_time) {
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
- DVLOG(1) << "Passphrase type changed to "
- << syncer::PassphraseTypeToString(type);
- cached_passphrase_type_ = type;
- cached_explicit_passphrase_time_ = explicit_passphrase_time;
-}
-
-void SyncBackendHost::HandleStopSyncingPermanentlyOnFrontendLoop() {
- if (!frontend_)
- return;
- frontend_->OnStopSyncingPermanently();
-}
-
-void SyncBackendHost::HandleConnectionStatusChangeOnFrontendLoop(
- syncer::ConnectionStatus status) {
- if (!frontend_)
- return;
-
- DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
-
- DVLOG(1) << "Connection status changed: "
- << syncer::ConnectionStatusToString(status);
- frontend_->OnConnectionStatusChange(status);
-}
-
-base::MessageLoop* SyncBackendHost::GetSyncLoopForTesting() {
- return registrar_->sync_thread()->message_loop();
-}
-
-#undef SDVLOG
+SyncBackendHost::SyncBackendHost() {}
-#undef SLOG
+SyncBackendHost::~SyncBackendHost() {}
} // namespace browser_sync

Powered by Google App Engine
This is Rietveld 408576698