| // Copyright (c) 2011 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. |
| |
| #ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_ |
| #define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_ |
| #pragma once |
| |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include "base/file_path.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/message_loop.h" |
| #include "base/synchronization/lock.h" |
| #include "base/threading/thread.h" |
| #include "base/timer.h" |
| #include "base/utf_string_conversions.h" |
| #include "chrome/browser/sync/engine/syncapi.h" |
| #include "chrome/browser/sync/engine/model_safe_worker.h" |
| #include "chrome/browser/sync/js_backend.h" |
| #include "chrome/browser/sync/js_sync_manager_observer.h" |
| #include "chrome/browser/sync/glue/data_type_controller.h" |
| #include "chrome/browser/sync/glue/ui_model_worker.h" |
| #include "chrome/browser/sync/js_event_router.h" |
| #include "chrome/browser/sync/syncable/model_type.h" |
| #include "chrome/common/net/gaia/google_service_auth_error.h" |
| #include "googleurl/src/gurl.h" |
| #include "net/url_request/url_request_context_getter.h" |
| |
| class CancelableTask; |
| class Profile; |
| |
| namespace net { |
| class URLRequestContextGetter; |
| } |
| |
| namespace sync_notifier { |
| class SyncNotifier; |
| } // namespace sync_notifier |
| |
| namespace browser_sync { |
| |
| namespace sessions { |
| struct SyncSessionSnapshot; |
| } |
| |
| class ChangeProcessor; |
| class DataTypeController; |
| class JsArgList; |
| |
| // SyncFrontend is the interface used by SyncBackendHost to communicate with |
| // the entity that created it and, presumably, is interested in sync-related |
| // activity. |
| // NOTE: All methods will be invoked by a SyncBackendHost on the same thread |
| // used to create that SyncBackendHost. |
| class SyncFrontend { |
| public: |
| SyncFrontend() {} |
| |
| // The backend has completed initialization and it is now ready to accept and |
| // process changes. |
| virtual void OnBackendInitialized() = 0; |
| |
| // The backend queried the server recently and received some updates. |
| virtual void OnSyncCycleCompleted() = 0; |
| |
| // The backend encountered an authentication problem and requests new |
| // credentials to be provided. See SyncBackendHost::Authenticate for details. |
| virtual void OnAuthError() = 0; |
| |
| // We are no longer permitted to communicate with the server. Sync should |
| // be disabled and state cleaned up at once. |
| virtual void OnStopSyncingPermanently() = 0; |
| |
| // Called to handle success/failure of clearing server data |
| virtual void OnClearServerDataSucceeded() = 0; |
| virtual void OnClearServerDataFailed() = 0; |
| |
| // The syncer requires a passphrase to decrypt sensitive |
| // updates. This is called when the first sensitive data type is |
| // setup by the user as well as anytime any the passphrase is |
| // changed in another synced client. if |
| // |passphrase_required_for_decryption| is false, the passphrase is |
| // required only for encryption. |
| virtual void OnPassphraseRequired(bool for_decryption) = 0; |
| |
| // Called when the passphrase provided by the user is |
| // accepted. After this is called, updates to sensitive nodes are |
| // encrypted using the accepted passphrase. |
| virtual void OnPassphraseAccepted() = 0; |
| |
| virtual void OnEncryptionComplete( |
| const syncable::ModelTypeSet& encrypted_types) = 0; |
| |
| // Called to perform migration of |types|. |
| virtual void OnMigrationNeededForTypes( |
| const syncable::ModelTypeSet& types) = 0; |
| |
| protected: |
| // Don't delete through SyncFrontend interface. |
| virtual ~SyncFrontend() { |
| } |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SyncFrontend); |
| }; |
| |
| // A UI-thread safe API into the sync backend that "hosts" the top-level |
| // syncapi element, the SyncManager, on its own thread. This class handles |
| // dispatch of potentially blocking calls to appropriate threads and ensures |
| // that the SyncFrontend is only accessed on the UI loop. |
| class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar { |
| public: |
| typedef sync_api::SyncManager::Status::Summary StatusSummary; |
| typedef sync_api::SyncManager::Status Status; |
| typedef std::map<ModelSafeGroup, |
| scoped_refptr<browser_sync::ModelSafeWorker> > WorkerMap; |
| |
| // Create a SyncBackendHost with a reference to the |frontend| that it serves |
| // and communicates to via the SyncFrontend interface (on the same thread |
| // it used to call the constructor). |
| explicit SyncBackendHost(Profile* profile); |
| // For testing. |
| // TODO(skrul): Extract an interface so this is not needed. |
| SyncBackendHost(); |
| virtual ~SyncBackendHost(); |
| |
| // Called on |frontend_loop_| to kick off asynchronous initialization. |
| // As a fallback when no cached auth information is available, try to |
| // bootstrap authentication using |lsid|, if it isn't empty. |
| // Optionally delete the Sync Data folder (if it's corrupt). |
| void Initialize(SyncFrontend* frontend, |
| const GURL& service_url, |
| const syncable::ModelTypeSet& types, |
| net::URLRequestContextGetter* baseline_context_getter, |
| const sync_api::SyncCredentials& credentials, |
| bool delete_sync_data_folder); |
| |
| // Called from |frontend_loop| to update SyncCredentials. |
| void UpdateCredentials(const sync_api::SyncCredentials& credentials); |
| |
| // This starts the SyncerThread running a Syncer object to communicate with |
| // sync servers. Until this is called, no changes will leave or enter this |
| // browser from the cloud / sync servers. |
| // Called on |frontend_loop_|. |
| virtual void StartSyncingWithServer(); |
| |
| // Called on |frontend_loop_| to asynchronously set the passphrase. |
| // |is_explicit| is true if the call is in response to the user explicitly |
| // setting a passphrase as opposed to implicitly (from the users' perspective) |
| // using their Google Account password. An implicit SetPassphrase will *not* |
| // *not* override an explicit passphrase set previously. |
| void SetPassphrase(const std::string& passphrase, bool is_explicit); |
| |
| // Called on |frontend_loop_| to kick off shutdown. |
| // |sync_disabled| indicates if syncing is being disabled or not. |
| // See the implementation and Core::DoShutdown for details. |
| void Shutdown(bool sync_disabled); |
| |
| // Changes the set of data types that are currently being synced. |
| // The ready_task will be run when all of the requested data types |
| // are up-to-date and ready for activation. The task will cancelled |
| // upon shutdown. The method takes ownership of the task pointer. |
| virtual void ConfigureDataTypes( |
| const DataTypeController::TypeMap& data_type_controllers, |
| const syncable::ModelTypeSet& types, |
| CancelableTask* ready_task); |
| |
| // Makes an asynchronous call to syncer to switch to config mode. When done |
| // syncer will call us back on FinishConfigureDataTypes. |
| virtual void StartConfiguration(Callback0::Type* callback); |
| |
| // Encrypts the specified datatypes and marks them as needing encryption on |
| // other machines. This affects all machines synced to this account and all |
| // data belonging to the specified types. |
| // Note: actual work is done on core_thread_'s message loop. |
| virtual void EncryptDataTypes( |
| const syncable::ModelTypeSet& encrypted_types); |
| |
| syncable::AutofillMigrationState |
| GetAutofillMigrationState(); |
| |
| void SetAutofillMigrationState( |
| syncable::AutofillMigrationState state); |
| |
| syncable::AutofillMigrationDebugInfo |
| GetAutofillMigrationDebugInfo(); |
| |
| void SetAutofillMigrationDebugInfo( |
| syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set, |
| const syncable::AutofillMigrationDebugInfo& info); |
| |
| // Activates change processing for the given data type. This must |
| // be called synchronously with the data type's model association so |
| // no changes are dropped between model association and change |
| // processor activation. |
| void ActivateDataType(DataTypeController* data_type_controller, |
| ChangeProcessor* change_processor); |
| |
| // Deactivates change processing for the given data type. |
| void DeactivateDataType(DataTypeController* data_type_controller, |
| ChangeProcessor* change_processor); |
| |
| // Asks the server to clear all data associated with ChromeSync. |
| virtual bool RequestClearServerData(); |
| |
| // Called on |frontend_loop_| to obtain a handle to the UserShare needed |
| // for creating transactions. |
| sync_api::UserShare* GetUserShare() const; |
| |
| // Called from any thread to obtain current status information in detailed or |
| // summarized form. |
| Status GetDetailedStatus(); |
| StatusSummary GetStatusSummary(); |
| const GoogleServiceAuthError& GetAuthError() const; |
| const sessions::SyncSessionSnapshot* GetLastSessionSnapshot() const; |
| |
| const FilePath& sync_data_folder_path() const { |
| return sync_data_folder_path_; |
| } |
| |
| // Returns the authenticated username of the sync user, or empty if none |
| // exists. It will only exist if the authentication service provider (e.g |
| // GAIA) has confirmed the username is authentic. |
| string16 GetAuthenticatedUsername() const; |
| |
| // ModelSafeWorkerRegistrar implementation. |
| virtual void GetWorkers(std::vector<browser_sync::ModelSafeWorker*>* out); |
| virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out); |
| |
| // Determines if the underlying sync engine has made any local changes to |
| // items that have not yet been synced with the server. |
| // ONLY CALL THIS IF OnInitializationComplete was called! |
| bool HasUnsyncedItems() const; |
| |
| // Whether or not we are syncing encryption keys. |
| bool IsNigoriEnabled() const; |
| |
| // Whether or not the Nigori node is encrypted using an explicit passphrase. |
| bool IsUsingExplicitPassphrase(); |
| |
| // True if the cryptographer has any keys available to attempt decryption. |
| // Could mean we've downloaded and loaded Nigori objects, or we bootstrapped |
| // using a token previously received. |
| bool IsCryptographerReady(const sync_api::BaseTransaction* trans) const; |
| |
| // Returns a pointer to the JsBackend (which is owned by the |
| // service). Must be called only after the sync backend has been |
| // initialized, and never returns NULL if you do so. Overrideable |
| // for testing purposes. |
| virtual JsBackend* GetJsBackend(); |
| |
| // TODO(akalin): Write unit tests for the JsBackend, finding a way |
| // to make this class testable in general. |
| |
| protected: |
| // The real guts of SyncBackendHost, to keep the public client API clean. |
| class Core : public base::RefCountedThreadSafe<SyncBackendHost::Core>, |
| public sync_api::SyncManager::Observer, |
| public JsBackend, |
| public JsEventRouter { |
| public: |
| explicit Core(SyncBackendHost* backend); |
| |
| // SyncManager::Observer implementation. The Core just acts like an air |
| // traffic controller here, forwarding incoming messages to appropriate |
| // landing threads. |
| virtual void OnChangesApplied( |
| syncable::ModelType model_type, |
| const sync_api::BaseTransaction* trans, |
| const sync_api::SyncManager::ChangeRecord* changes, |
| int change_count); |
| virtual void OnChangesComplete(syncable::ModelType model_type); |
| virtual void OnSyncCycleCompleted( |
| const sessions::SyncSessionSnapshot* snapshot); |
| virtual void OnInitializationComplete(); |
| virtual void OnAuthError(const GoogleServiceAuthError& auth_error); |
| virtual void OnPassphraseRequired(bool for_decryption); |
| virtual void OnPassphraseFailed(); |
| virtual void OnPassphraseAccepted(const std::string& bootstrap_token); |
| virtual void OnStopSyncingPermanently(); |
| virtual void OnUpdatedToken(const std::string& token); |
| virtual void OnClearServerDataFailed(); |
| virtual void OnClearServerDataSucceeded(); |
| virtual void OnEncryptionComplete( |
| const syncable::ModelTypeSet& encrypted_types); |
| |
| // JsBackend implementation. |
| virtual void SetParentJsEventRouter(JsEventRouter* router); |
| virtual void RemoveParentJsEventRouter(); |
| virtual const JsEventRouter* GetParentJsEventRouter() const; |
| virtual void ProcessMessage(const std::string& name, const JsArgList& args, |
| const JsEventHandler* sender); |
| |
| // JsEventRouter implementation. |
| virtual void RouteJsEvent(const std::string& event_name, |
| const JsArgList& args, |
| const JsEventHandler* dst); |
| |
| struct DoInitializeOptions { |
| DoInitializeOptions( |
| const GURL& service_url, |
| sync_api::HttpPostProviderFactory* http_bridge_factory, |
| const sync_api::SyncCredentials& credentials, |
| bool delete_sync_data_folder, |
| const std::string& restored_key_for_bootstrapping, |
| bool setup_for_test_mode); |
| ~DoInitializeOptions(); |
| |
| GURL service_url; |
| sync_api::HttpPostProviderFactory* http_bridge_factory; |
| sync_api::SyncCredentials credentials; |
| std::string lsid; |
| bool delete_sync_data_folder; |
| std::string restored_key_for_bootstrapping; |
| bool setup_for_test_mode; |
| }; |
| |
| // Called on |frontend_loop_|. |
| void CreateSyncNotifier(const scoped_refptr<net::URLRequestContextGetter>& |
| request_context_getter); |
| |
| // Note: |
| // |
| // The Do* methods are the various entry points from our SyncBackendHost. |
| // It calls us on a dedicated thread to actually perform synchronous |
| // (and potentially blocking) syncapi operations. |
| // |
| // Called on the SyncBackendHost core_thread_ to perform initialization |
| // of the syncapi on behalf of SyncBackendHost::Initialize. |
| void DoInitialize(const DoInitializeOptions& options); |
| |
| // Called on our SyncBackendHost's core_thread_ to perform credential |
| // update on behalf of SyncBackendHost::UpdateCredentials |
| void DoUpdateCredentials(const sync_api::SyncCredentials& credentials); |
| |
| // Called when the user disables or enables a sync type. |
| void DoUpdateEnabledTypes(); |
| |
| // Called on the SyncBackendHost core_thread_ to tell the syncapi to start |
| // syncing (generally after initialization and authentication). |
| void DoStartSyncing(); |
| |
| // Called on the SyncBackendHost core_thread_ to nudge/pause/resume the |
| // syncer. |
| void DoRequestNudge(const tracked_objects::Location& location); |
| void DoRequestClearServerData(); |
| |
| // Sets |deferred_nudge_for_cleanup_requested_| to true. See comment below. |
| void DeferNudgeForCleanup(); |
| |
| // Called on our SyncBackendHost's |core_thread_| to set the passphrase |
| // on behalf of SyncBackendHost::SupplyPassphrase. |
| void DoSetPassphrase(const std::string& passphrase, bool is_explicit); |
| |
| // Getter/setter for whether we are waiting on SetPassphrase to process a |
| // passphrase. Set by SetPassphrase, cleared by OnPassphraseFailed or |
| // OnPassphraseAccepted. |
| bool processing_passphrase() const; |
| void set_processing_passphrase(); |
| |
| // Called on SyncBackendHost's |core_thread_| to set the datatypes we need |
| // to encrypt as well as encrypt all local data of that type. |
| void DoEncryptDataTypes(const syncable::ModelTypeSet& encrypted_types); |
| |
| // The shutdown order is a bit complicated: |
| // 1) From |core_thread_|, invoke the syncapi Shutdown call to do a final |
| // SaveChanges, close sqlite handles, and halt the syncer thread (which |
| // could potentially block for 1 minute). |
| // 2) Then, from |frontend_loop_|, halt the core_thread_. This causes |
| // syncapi thread-exit handlers to run and make use of cached pointers to |
| // various components owned implicitly by us. |
| // 3) Destroy this Core. That will delete syncapi components in a safe order |
| // because the thread that was using them has exited (in step 2). |
| void DoShutdown(bool stopping_sync); |
| |
| // Posts a config request on the core thread. |
| virtual void DoRequestConfig(const syncable::ModelTypeBitSet& added_types); |
| |
| // Start the configuration mode. |
| virtual void DoStartConfiguration(Callback0::Type* 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. |
| |
| sync_api::SyncManager* syncapi() { return syncapi_.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(); |
| |
| void ConnectChildJsEventRouter(); |
| |
| void DisconnectChildJsEventRouter(); |
| |
| void DoProcessMessage( |
| const std::string& name, const JsArgList& args, |
| const JsEventHandler* sender); |
| |
| // A callback from the SyncerThread when it is safe to continue config. |
| void FinishConfigureDataTypes(); |
| |
| #if defined(UNIT_TEST) |
| // Special form of initialization that does not try and authenticate the |
| // last known user (since it will fail in test mode) and does some extra |
| // setup to nudge the syncapi into a usable state. |
| void DoInitializeForTest(const std::wstring& test_user, |
| sync_api::HttpPostProviderFactory* factory, |
| bool delete_sync_data_folder) { |
| // Construct dummy credentials for test. |
| sync_api::SyncCredentials credentials; |
| credentials.email = WideToUTF8(test_user); |
| credentials.sync_token = "token"; |
| DoInitialize(DoInitializeOptions(GURL(), factory, credentials, |
| delete_sync_data_folder, |
| "", true)); |
| } |
| #endif |
| |
| private: |
| friend class base::RefCountedThreadSafe<SyncBackendHost::Core>; |
| friend class SyncBackendHostForProfileSyncTest; |
| |
| virtual ~Core(); |
| |
| // Return change processor for a particular model (return NULL on failure). |
| ChangeProcessor* GetProcessor(syncable::ModelType modeltype); |
| |
| // 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 |core_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 the |
| // SyncBackendHost |core_thread_|), using a repeating timer that is kicked |
| // off as soon as the SyncManager tells us it completed |
| // initialization. |
| void SaveChanges(); |
| |
| // Dispatched to from HandleAuthErrorEventOnCoreLoop to handle updating |
| // frontend UI components. |
| void HandleAuthErrorEventOnFrontendLoop( |
| const GoogleServiceAuthError& new_auth_error); |
| |
| // Invoked when a passphrase is required to decrypt a set of Nigori keys, |
| // or for encrypting. If the reason is decryption, |for_decryption| will |
| // be true. |
| void NotifyPassphraseRequired(bool for_decryption); |
| |
| // Invoked when the syncer attempts to set a passphrase but fails to decrypt |
| // the cryptographer's pending keys. This tells the profile sync service |
| // that a new passphrase is required. |
| void NotifyPassphraseFailed(); |
| |
| // Invoked when the passphrase provided by the user has been accepted. |
| void NotifyPassphraseAccepted(const std::string& bootstrap_token); |
| |
| // Invoked when an updated token is available from the sync server. |
| void NotifyUpdatedToken(const std::string& token); |
| |
| // Invoked when sync finishes encrypting new datatypes or has become aware |
| // of new datatypes requiring encryption. |
| void NotifyEncryptionComplete(const syncable::ModelTypeSet& |
| encrypted_types); |
| |
| // Called from Core::OnSyncCycleCompleted to handle updating frontend |
| // thread components. |
| void HandleSyncCycleCompletedOnFrontendLoop( |
| sessions::SyncSessionSnapshot* snapshot); |
| |
| void HandleStopSyncingPermanentlyOnFrontendLoop(); |
| |
| // Called to handle success/failure of clearing server data |
| void HandleClearServerDataSucceededOnFrontendLoop(); |
| void HandleClearServerDataFailedOnFrontendLoop(); |
| |
| // Called from Core::OnInitializationComplete to handle updating |
| // frontend thread components. |
| void HandleInitalizationCompletedOnFrontendLoop(); |
| |
| void RouteJsEventOnFrontendLoop( |
| const std::string& name, const JsArgList& args, |
| const JsEventHandler* dst); |
| |
| void FinishConfigureDataTypesOnFrontendLoop(); |
| |
| // Return true if a model lives on the current thread. |
| bool IsCurrentThreadSafeForModel(syncable::ModelType model_type); |
| |
| // Our parent SyncBackendHost |
| SyncBackendHost* host_; |
| |
| // The timer used to periodically call SaveChanges. |
| base::RepeatingTimer<Core> save_changes_timer_; |
| |
| // The top-level syncapi entry point. |
| scoped_ptr<sync_api::SyncManager> syncapi_; |
| |
| scoped_ptr<sync_notifier::SyncNotifier> sync_notifier_; |
| |
| JsSyncManagerObserver sync_manager_observer_; |
| |
| JsEventRouter* parent_router_; |
| |
| // Denotes if the core is currently attempting to set a passphrase. While |
| // this is true, OnPassphraseRequired calls are dropped. |
| // Note: after initialization, this variable should only ever be accessed or |
| // modified from within the frontend_loop_ (UI thread). |
| bool processing_passphrase_; |
| |
| // True when a datatype has been disabled so that we nudge once sync is |
| // resumed (after configuration is finished). |
| bool deferred_nudge_for_cleanup_requested_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Core); |
| }; |
| |
| // InitializationComplete passes through the SyncBackendHost to forward |
| // on to |frontend_|, and so that tests can intercept here if they need to |
| // set up initial conditions. |
| virtual void HandleInitializationCompletedOnFrontendLoop(); |
| |
| // Posts a nudge request on the core thread. |
| virtual void RequestNudge(const tracked_objects::Location& location); |
| |
| // Called to finish the job of ConfigureDataTypes once the syncer is in |
| // configuration mode. |
| void FinishConfigureDataTypes(); |
| void FinishConfigureDataTypesOnFrontendLoop(); |
| |
| // Allows tests to perform alternate core initialization work. |
| virtual void InitCore(const Core::DoInitializeOptions& options); |
| |
| // Factory method for HttpPostProviderFactories. |
| virtual sync_api::HttpPostProviderFactory* MakeHttpBridgeFactory( |
| net::URLRequestContextGetter* getter); |
| |
| MessageLoop* core_loop() { return core_thread_.message_loop(); } |
| |
| void set_syncapi_initialized() { syncapi_initialized_ = true; } |
| |
| // Helpers to persist a token that can be used to bootstrap sync encryption |
| // across browser restart to avoid requiring the user to re-enter their |
| // passphrase. |token| must be valid UTF-8 as we use the PrefService for |
| // storage. |
| void PersistEncryptionBootstrapToken(const std::string& token); |
| std::string RestoreEncryptionBootstrapToken(); |
| |
| // Our core, which communicates directly to the syncapi. |
| scoped_refptr<Core> core_; |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(SyncBackendHostTest, MakePendingConfigModeState); |
| |
| struct PendingConfigureDataTypesState { |
| PendingConfigureDataTypesState(); |
| ~PendingConfigureDataTypesState(); |
| |
| // A task that should be called once data type configuration is |
| // complete. |
| scoped_ptr<CancelableTask> ready_task; |
| |
| // The set of types that we are waiting to be initially synced in a |
| // configuration cycle. |
| syncable::ModelTypeSet initial_types; |
| |
| // Additional details about which types were added / removed. |
| bool deleted_type; |
| syncable::ModelTypeBitSet added_types; |
| }; |
| |
| UIModelWorker* ui_worker(); |
| |
| void ConfigureAutofillMigration(); |
| |
| // Helper function for ConfigureDataTypes(). Caller owns return |
| // value. Takes ownership of |ready_task| (but not |routing_info|). |
| static PendingConfigureDataTypesState* MakePendingConfigModeState( |
| const DataTypeController::TypeMap& data_type_controllers, |
| const syncable::ModelTypeSet& types, |
| CancelableTask* ready_task, |
| ModelSafeRoutingInfo* routing_info); |
| |
| // A thread we dedicate for use by our Core to perform initialization, |
| // authentication, handle messages from the syncapi, and periodically tell |
| // the syncapi to persist itself. |
| base::Thread core_thread_; |
| |
| // A reference to the MessageLoop used to construct |this|, so we know how |
| // to safely talk back to the SyncFrontend. |
| MessageLoop* const frontend_loop_; |
| |
| Profile* profile_; |
| |
| // This is state required to implement ModelSafeWorkerRegistrar. |
| struct { |
| // We maintain ownership of all workers. In some cases, we need to ensure |
| // shutdown occurs in an expected sequence by Stop()ing certain workers. |
| // They are guaranteed to be valid because we only destroy elements of |
| // |workers_| after the syncapi has been destroyed. Unless a worker is no |
| // longer needed because all types that get routed to it have been disabled |
| // (from syncing). In that case, we'll destroy on demand *after* routing |
| // any dependent types to GROUP_PASSIVE, so that the syncapi doesn't call |
| // into garbage. If a key is present, it means at least one ModelType that |
| // routes to that model safe group is being synced. |
| WorkerMap workers; |
| browser_sync::ModelSafeRoutingInfo routing_info; |
| } registrar_; |
| |
| // The user can incur changes to registrar_ at any time from the UI thread. |
| // The syncapi needs to periodically get a consistent snapshot of the state, |
| // and it does so from a different thread. Therefore, we protect creation, |
| // destruction, and re-routing events by acquiring this lock. Note that the |
| // SyncBackendHost may read (on the UI thread or core thread) from registrar_ |
| // without acquiring the lock (which is typically "read ModelSafeWorker |
| // pointer value", and then invoke methods), because lifetimes are managed on |
| // the UI thread. Of course, this comment only applies to ModelSafeWorker |
| // impls that are themselves thread-safe, such as UIModelWorker. |
| mutable base::Lock registrar_lock_; |
| |
| // The frontend which we serve (and are owned by). |
| SyncFrontend* frontend_; |
| |
| // The change processors that handle the different data types. |
| std::map<syncable::ModelType, ChangeProcessor*> processors_; |
| |
| // Path of the folder that stores the sync data files. |
| FilePath sync_data_folder_path_; |
| |
| scoped_ptr<PendingConfigureDataTypesState> pending_download_state_; |
| scoped_ptr<PendingConfigureDataTypesState> pending_config_mode_state_; |
| |
| // UI-thread cache of the last AuthErrorState received from syncapi. |
| GoogleServiceAuthError last_auth_error_; |
| |
| // UI-thread cache of the last SyncSessionSnapshot received from syncapi. |
| scoped_ptr<sessions::SyncSessionSnapshot> last_snapshot_; |
| |
| // Whether we've processed the initialization complete callback. |
| bool syncapi_initialized_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SyncBackendHost); |
| }; |
| |
| } // namespace browser_sync |
| |
| #endif // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_ |