Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
      6 #define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
      7 #pragma once
      8 
      9 #include <map>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/file_path.h"
     14 #include "base/gtest_prod_util.h"
     15 #include "base/memory/ref_counted.h"
     16 #include "base/message_loop.h"
     17 #include "base/synchronization/lock.h"
     18 #include "base/threading/thread.h"
     19 #include "base/timer.h"
     20 #include "base/utf_string_conversions.h"
     21 #include "chrome/browser/sync/engine/syncapi.h"
     22 #include "chrome/browser/sync/engine/model_safe_worker.h"
     23 #include "chrome/browser/sync/js_backend.h"
     24 #include "chrome/browser/sync/js_sync_manager_observer.h"
     25 #include "chrome/browser/sync/glue/data_type_controller.h"
     26 #include "chrome/browser/sync/glue/ui_model_worker.h"
     27 #include "chrome/browser/sync/js_event_router.h"
     28 #include "chrome/browser/sync/syncable/model_type.h"
     29 #include "chrome/common/net/gaia/google_service_auth_error.h"
     30 #include "googleurl/src/gurl.h"
     31 #include "net/url_request/url_request_context_getter.h"
     32 
     33 class CancelableTask;
     34 class Profile;
     35 
     36 namespace net {
     37 class URLRequestContextGetter;
     38 }
     39 
     40 namespace sync_notifier {
     41 class SyncNotifier;
     42 }  // namespace sync_notifier
     43 
     44 namespace browser_sync {
     45 
     46 namespace sessions {
     47 struct SyncSessionSnapshot;
     48 }
     49 
     50 class ChangeProcessor;
     51 class DataTypeController;
     52 class JsArgList;
     53 
     54 // SyncFrontend is the interface used by SyncBackendHost to communicate with
     55 // the entity that created it and, presumably, is interested in sync-related
     56 // activity.
     57 // NOTE: All methods will be invoked by a SyncBackendHost on the same thread
     58 // used to create that SyncBackendHost.
     59 class SyncFrontend {
     60  public:
     61   SyncFrontend() {}
     62 
     63   // The backend has completed initialization and it is now ready to accept and
     64   // process changes.
     65   virtual void OnBackendInitialized() = 0;
     66 
     67   // The backend queried the server recently and received some updates.
     68   virtual void OnSyncCycleCompleted() = 0;
     69 
     70   // The backend encountered an authentication problem and requests new
     71   // credentials to be provided. See SyncBackendHost::Authenticate for details.
     72   virtual void OnAuthError() = 0;
     73 
     74   // We are no longer permitted to communicate with the server. Sync should
     75   // be disabled and state cleaned up at once.
     76   virtual void OnStopSyncingPermanently() = 0;
     77 
     78   // Called to handle success/failure of clearing server data
     79   virtual void OnClearServerDataSucceeded() = 0;
     80   virtual void OnClearServerDataFailed() = 0;
     81 
     82   // The syncer requires a passphrase to decrypt sensitive
     83   // updates. This is called when the first sensitive data type is
     84   // setup by the user as well as anytime any the passphrase is
     85   // changed in another synced client.  if
     86   // |passphrase_required_for_decryption| is false, the passphrase is
     87   // required only for encryption.
     88   virtual void OnPassphraseRequired(bool for_decryption) = 0;
     89 
     90   // Called when the passphrase provided by the user is
     91   // accepted. After this is called, updates to sensitive nodes are
     92   // encrypted using the accepted passphrase.
     93   virtual void OnPassphraseAccepted() = 0;
     94 
     95   virtual void OnEncryptionComplete(
     96       const syncable::ModelTypeSet& encrypted_types) = 0;
     97 
     98   // Called to perform migration of |types|.
     99   virtual void OnMigrationNeededForTypes(
    100       const syncable::ModelTypeSet& types) = 0;
    101 
    102  protected:
    103   // Don't delete through SyncFrontend interface.
    104   virtual ~SyncFrontend() {
    105   }
    106  private:
    107   DISALLOW_COPY_AND_ASSIGN(SyncFrontend);
    108 };
    109 
    110 // A UI-thread safe API into the sync backend that "hosts" the top-level
    111 // syncapi element, the SyncManager, on its own thread. This class handles
    112 // dispatch of potentially blocking calls to appropriate threads and ensures
    113 // that the SyncFrontend is only accessed on the UI loop.
    114 class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
    115  public:
    116   typedef sync_api::SyncManager::Status::Summary StatusSummary;
    117   typedef sync_api::SyncManager::Status Status;
    118   typedef std::map<ModelSafeGroup,
    119                    scoped_refptr<browser_sync::ModelSafeWorker> > WorkerMap;
    120 
    121   // Create a SyncBackendHost with a reference to the |frontend| that it serves
    122   // and communicates to via the SyncFrontend interface (on the same thread
    123   // it used to call the constructor).
    124   explicit SyncBackendHost(Profile* profile);
    125   // For testing.
    126   // TODO(skrul): Extract an interface so this is not needed.
    127   SyncBackendHost();
    128   virtual ~SyncBackendHost();
    129 
    130   // Called on |frontend_loop_| to kick off asynchronous initialization.
    131   // As a fallback when no cached auth information is available, try to
    132   // bootstrap authentication using |lsid|, if it isn't empty.
    133   // Optionally delete the Sync Data folder (if it's corrupt).
    134   void Initialize(SyncFrontend* frontend,
    135                   const GURL& service_url,
    136                   const syncable::ModelTypeSet& types,
    137                   net::URLRequestContextGetter* baseline_context_getter,
    138                   const sync_api::SyncCredentials& credentials,
    139                   bool delete_sync_data_folder);
    140 
    141   // Called from |frontend_loop| to update SyncCredentials.
    142   void UpdateCredentials(const sync_api::SyncCredentials& credentials);
    143 
    144   // This starts the SyncerThread running a Syncer object to communicate with
    145   // sync servers.  Until this is called, no changes will leave or enter this
    146   // browser from the cloud / sync servers.
    147   // Called on |frontend_loop_|.
    148   virtual void StartSyncingWithServer();
    149 
    150   // Called on |frontend_loop_| to asynchronously set the passphrase.
    151   // |is_explicit| is true if the call is in response to the user explicitly
    152   // setting a passphrase as opposed to implicitly (from the users' perspective)
    153   // using their Google Account password.  An implicit SetPassphrase will *not*
    154   // *not* override an explicit passphrase set previously.
    155   void SetPassphrase(const std::string& passphrase, bool is_explicit);
    156 
    157   // Called on |frontend_loop_| to kick off shutdown.
    158   // |sync_disabled| indicates if syncing is being disabled or not.
    159   // See the implementation and Core::DoShutdown for details.
    160   void Shutdown(bool sync_disabled);
    161 
    162   // Changes the set of data types that are currently being synced.
    163   // The ready_task will be run when all of the requested data types
    164   // are up-to-date and ready for activation.  The task will cancelled
    165   // upon shutdown.  The method takes ownership of the task pointer.
    166   virtual void ConfigureDataTypes(
    167       const DataTypeController::TypeMap& data_type_controllers,
    168       const syncable::ModelTypeSet& types,
    169       CancelableTask* ready_task);
    170 
    171   // Makes an asynchronous call to syncer to switch to config mode. When done
    172   // syncer will call us back on FinishConfigureDataTypes.
    173   virtual void StartConfiguration(Callback0::Type* callback);
    174 
    175   // Encrypts the specified datatypes and marks them as needing encryption on
    176   // other machines. This affects all machines synced to this account and all
    177   // data belonging to the specified types.
    178   // Note: actual work is done on core_thread_'s message loop.
    179   virtual void EncryptDataTypes(
    180       const syncable::ModelTypeSet& encrypted_types);
    181 
    182   syncable::AutofillMigrationState
    183       GetAutofillMigrationState();
    184 
    185   void SetAutofillMigrationState(
    186       syncable::AutofillMigrationState state);
    187 
    188   syncable::AutofillMigrationDebugInfo
    189       GetAutofillMigrationDebugInfo();
    190 
    191   void SetAutofillMigrationDebugInfo(
    192       syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
    193       const syncable::AutofillMigrationDebugInfo& info);
    194 
    195   // Activates change processing for the given data type.  This must
    196   // be called synchronously with the data type's model association so
    197   // no changes are dropped between model association and change
    198   // processor activation.
    199   void ActivateDataType(DataTypeController* data_type_controller,
    200                         ChangeProcessor* change_processor);
    201 
    202   // Deactivates change processing for the given data type.
    203   void DeactivateDataType(DataTypeController* data_type_controller,
    204                           ChangeProcessor* change_processor);
    205 
    206   // Asks the server to clear all data associated with ChromeSync.
    207   virtual bool RequestClearServerData();
    208 
    209   // Called on |frontend_loop_| to obtain a handle to the UserShare needed
    210   // for creating transactions.
    211   sync_api::UserShare* GetUserShare() const;
    212 
    213   // Called from any thread to obtain current status information in detailed or
    214   // summarized form.
    215   Status GetDetailedStatus();
    216   StatusSummary GetStatusSummary();
    217   const GoogleServiceAuthError& GetAuthError() const;
    218   const sessions::SyncSessionSnapshot* GetLastSessionSnapshot() const;
    219 
    220   const FilePath& sync_data_folder_path() const {
    221     return sync_data_folder_path_;
    222   }
    223 
    224   // Returns the authenticated username of the sync user, or empty if none
    225   // exists. It will only exist if the authentication service provider (e.g
    226   // GAIA) has confirmed the username is authentic.
    227   string16 GetAuthenticatedUsername() const;
    228 
    229   // ModelSafeWorkerRegistrar implementation.
    230   virtual void GetWorkers(std::vector<browser_sync::ModelSafeWorker*>* out);
    231   virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out);
    232 
    233   // Determines if the underlying sync engine has made any local changes to
    234   // items that have not yet been synced with the server.
    235   // ONLY CALL THIS IF OnInitializationComplete was called!
    236   bool HasUnsyncedItems() const;
    237 
    238   // Whether or not we are syncing encryption keys.
    239   bool IsNigoriEnabled() const;
    240 
    241   // Whether or not the Nigori node is encrypted using an explicit passphrase.
    242   bool IsUsingExplicitPassphrase();
    243 
    244   // True if the cryptographer has any keys available to attempt decryption.
    245   // Could mean we've downloaded and loaded Nigori objects, or we bootstrapped
    246   // using a token previously received.
    247   bool IsCryptographerReady(const sync_api::BaseTransaction* trans) const;
    248 
    249   // Returns a pointer to the JsBackend (which is owned by the
    250   // service).  Must be called only after the sync backend has been
    251   // initialized, and never returns NULL if you do so.  Overrideable
    252   // for testing purposes.
    253   virtual JsBackend* GetJsBackend();
    254 
    255   // TODO(akalin): Write unit tests for the JsBackend, finding a way
    256   // to make this class testable in general.
    257 
    258  protected:
    259   // The real guts of SyncBackendHost, to keep the public client API clean.
    260   class Core : public base::RefCountedThreadSafe<SyncBackendHost::Core>,
    261                public sync_api::SyncManager::Observer,
    262                public JsBackend,
    263                public JsEventRouter {
    264    public:
    265     explicit Core(SyncBackendHost* backend);
    266 
    267     // SyncManager::Observer implementation.  The Core just acts like an air
    268     // traffic controller here, forwarding incoming messages to appropriate
    269     // landing threads.
    270     virtual void OnChangesApplied(
    271         syncable::ModelType model_type,
    272         const sync_api::BaseTransaction* trans,
    273         const sync_api::SyncManager::ChangeRecord* changes,
    274         int change_count);
    275     virtual void OnChangesComplete(syncable::ModelType model_type);
    276     virtual void OnSyncCycleCompleted(
    277         const sessions::SyncSessionSnapshot* snapshot);
    278     virtual void OnInitializationComplete();
    279     virtual void OnAuthError(const GoogleServiceAuthError& auth_error);
    280     virtual void OnPassphraseRequired(bool for_decryption);
    281     virtual void OnPassphraseFailed();
    282     virtual void OnPassphraseAccepted(const std::string& bootstrap_token);
    283     virtual void OnStopSyncingPermanently();
    284     virtual void OnUpdatedToken(const std::string& token);
    285     virtual void OnClearServerDataFailed();
    286     virtual void OnClearServerDataSucceeded();
    287     virtual void OnEncryptionComplete(
    288         const syncable::ModelTypeSet& encrypted_types);
    289 
    290     // JsBackend implementation.
    291     virtual void SetParentJsEventRouter(JsEventRouter* router);
    292     virtual void RemoveParentJsEventRouter();
    293     virtual const JsEventRouter* GetParentJsEventRouter() const;
    294     virtual void ProcessMessage(const std::string& name, const JsArgList& args,
    295                                 const JsEventHandler* sender);
    296 
    297     // JsEventRouter implementation.
    298     virtual void RouteJsEvent(const std::string& event_name,
    299                               const JsArgList& args,
    300                               const JsEventHandler* dst);
    301 
    302     struct DoInitializeOptions {
    303       DoInitializeOptions(
    304           const GURL& service_url,
    305           sync_api::HttpPostProviderFactory* http_bridge_factory,
    306           const sync_api::SyncCredentials& credentials,
    307           bool delete_sync_data_folder,
    308           const std::string& restored_key_for_bootstrapping,
    309           bool setup_for_test_mode);
    310       ~DoInitializeOptions();
    311 
    312       GURL service_url;
    313       sync_api::HttpPostProviderFactory* http_bridge_factory;
    314       sync_api::SyncCredentials credentials;
    315       std::string lsid;
    316       bool delete_sync_data_folder;
    317       std::string restored_key_for_bootstrapping;
    318       bool setup_for_test_mode;
    319     };
    320 
    321     // Called on |frontend_loop_|.
    322     void CreateSyncNotifier(const scoped_refptr<net::URLRequestContextGetter>&
    323         request_context_getter);
    324 
    325     // Note:
    326     //
    327     // The Do* methods are the various entry points from our SyncBackendHost.
    328     // It calls us on a dedicated thread to actually perform synchronous
    329     // (and potentially blocking) syncapi operations.
    330     //
    331     // Called on the SyncBackendHost core_thread_ to perform initialization
    332     // of the syncapi on behalf of SyncBackendHost::Initialize.
    333     void DoInitialize(const DoInitializeOptions& options);
    334 
    335     // Called on our SyncBackendHost's core_thread_ to perform credential
    336     // update on behalf of SyncBackendHost::UpdateCredentials
    337     void DoUpdateCredentials(const sync_api::SyncCredentials& credentials);
    338 
    339     // Called when the user disables or enables a sync type.
    340     void DoUpdateEnabledTypes();
    341 
    342     // Called on the SyncBackendHost core_thread_ to tell the syncapi to start
    343     // syncing (generally after initialization and authentication).
    344     void DoStartSyncing();
    345 
    346     // Called on the SyncBackendHost core_thread_ to nudge/pause/resume the
    347     // syncer.
    348     void DoRequestNudge(const tracked_objects::Location& location);
    349     void DoRequestClearServerData();
    350 
    351     // Sets |deferred_nudge_for_cleanup_requested_| to true. See comment below.
    352     void DeferNudgeForCleanup();
    353 
    354     // Called on our SyncBackendHost's |core_thread_| to set the passphrase
    355     // on behalf of SyncBackendHost::SupplyPassphrase.
    356     void DoSetPassphrase(const std::string& passphrase, bool is_explicit);
    357 
    358     // Getter/setter for whether we are waiting on SetPassphrase to process a
    359     // passphrase. Set by SetPassphrase, cleared by OnPassphraseFailed or
    360     // OnPassphraseAccepted.
    361     bool processing_passphrase() const;
    362     void set_processing_passphrase();
    363 
    364     // Called on SyncBackendHost's |core_thread_| to set the datatypes we need
    365     // to encrypt as well as encrypt all local data of that type.
    366     void DoEncryptDataTypes(const syncable::ModelTypeSet& encrypted_types);
    367 
    368     // The shutdown order is a bit complicated:
    369     // 1) From |core_thread_|, invoke the syncapi Shutdown call to do a final
    370     //    SaveChanges, close sqlite handles, and halt the syncer thread (which
    371     //    could potentially block for 1 minute).
    372     // 2) Then, from |frontend_loop_|, halt the core_thread_. This causes
    373     //    syncapi thread-exit handlers to run and make use of cached pointers to
    374     //    various components owned implicitly by us.
    375     // 3) Destroy this Core. That will delete syncapi components in a safe order
    376     //    because the thread that was using them has exited (in step 2).
    377     void DoShutdown(bool stopping_sync);
    378 
    379     // Posts a config request on the core thread.
    380     virtual void DoRequestConfig(const syncable::ModelTypeBitSet& added_types);
    381 
    382     // Start the configuration mode.
    383     virtual void DoStartConfiguration(Callback0::Type* callback);
    384 
    385     // Set the base request context to use when making HTTP calls.
    386     // This method will add a reference to the context to persist it
    387     // on the IO thread. Must be removed from IO thread.
    388 
    389     sync_api::SyncManager* syncapi() { return syncapi_.get(); }
    390 
    391     // Delete the sync data folder to cleanup backend data.  Happens the first
    392     // time sync is enabled for a user (to prevent accidentally reusing old
    393     // sync databases), as well as shutdown when you're no longer syncing.
    394     void DeleteSyncDataFolder();
    395 
    396     void ConnectChildJsEventRouter();
    397 
    398     void DisconnectChildJsEventRouter();
    399 
    400     void DoProcessMessage(
    401         const std::string& name, const JsArgList& args,
    402         const JsEventHandler* sender);
    403 
    404     // A callback from the SyncerThread when it is safe to continue config.
    405     void FinishConfigureDataTypes();
    406 
    407 #if defined(UNIT_TEST)
    408     // Special form of initialization that does not try and authenticate the
    409     // last known user (since it will fail in test mode) and does some extra
    410     // setup to nudge the syncapi into a usable state.
    411     void DoInitializeForTest(const std::wstring& test_user,
    412                              sync_api::HttpPostProviderFactory* factory,
    413                              bool delete_sync_data_folder) {
    414       // Construct dummy credentials for test.
    415       sync_api::SyncCredentials credentials;
    416       credentials.email = WideToUTF8(test_user);
    417       credentials.sync_token = "token";
    418       DoInitialize(DoInitializeOptions(GURL(), factory, credentials,
    419                                        delete_sync_data_folder,
    420                                        "", true));
    421     }
    422 #endif
    423 
    424    private:
    425     friend class base::RefCountedThreadSafe<SyncBackendHost::Core>;
    426     friend class SyncBackendHostForProfileSyncTest;
    427 
    428     virtual ~Core();
    429 
    430     // Return change processor for a particular model (return NULL on failure).
    431     ChangeProcessor* GetProcessor(syncable::ModelType modeltype);
    432 
    433     // Invoked when initialization of syncapi is complete and we can start
    434     // our timer.
    435     // This must be called from the thread on which SaveChanges is intended to
    436     // be run on; the host's |core_thread_|.
    437     void StartSavingChanges();
    438 
    439     // Invoked periodically to tell the syncapi to persist its state
    440     // by writing to disk.
    441     // This is called from the thread we were created on (which is the
    442     // SyncBackendHost |core_thread_|), using a repeating timer that is kicked
    443     // off as soon as the SyncManager tells us it completed
    444     // initialization.
    445     void SaveChanges();
    446 
    447     // Dispatched to from HandleAuthErrorEventOnCoreLoop to handle updating
    448     // frontend UI components.
    449     void HandleAuthErrorEventOnFrontendLoop(
    450         const GoogleServiceAuthError& new_auth_error);
    451 
    452     // Invoked when a passphrase is required to decrypt a set of Nigori keys,
    453     // or for encrypting.  If the reason is decryption, |for_decryption| will
    454     // be true.
    455     void NotifyPassphraseRequired(bool for_decryption);
    456 
    457     // Invoked when the syncer attempts to set a passphrase but fails to decrypt
    458     // the cryptographer's pending keys. This tells the profile sync service
    459     // that a new passphrase is required.
    460     void NotifyPassphraseFailed();
    461 
    462     // Invoked when the passphrase provided by the user has been accepted.
    463     void NotifyPassphraseAccepted(const std::string& bootstrap_token);
    464 
    465     // Invoked when an updated token is available from the sync server.
    466     void NotifyUpdatedToken(const std::string& token);
    467 
    468     // Invoked when sync finishes encrypting new datatypes or has become aware
    469     // of new datatypes requiring encryption.
    470     void NotifyEncryptionComplete(const syncable::ModelTypeSet&
    471                                       encrypted_types);
    472 
    473     // Called from Core::OnSyncCycleCompleted to handle updating frontend
    474     // thread components.
    475     void HandleSyncCycleCompletedOnFrontendLoop(
    476         sessions::SyncSessionSnapshot* snapshot);
    477 
    478     void HandleStopSyncingPermanentlyOnFrontendLoop();
    479 
    480     // Called to handle success/failure of clearing server data
    481     void HandleClearServerDataSucceededOnFrontendLoop();
    482     void HandleClearServerDataFailedOnFrontendLoop();
    483 
    484     // Called from Core::OnInitializationComplete to handle updating
    485     // frontend thread components.
    486     void HandleInitalizationCompletedOnFrontendLoop();
    487 
    488     void RouteJsEventOnFrontendLoop(
    489         const std::string& name, const JsArgList& args,
    490         const JsEventHandler* dst);
    491 
    492     void FinishConfigureDataTypesOnFrontendLoop();
    493 
    494     // Return true if a model lives on the current thread.
    495     bool IsCurrentThreadSafeForModel(syncable::ModelType model_type);
    496 
    497     // Our parent SyncBackendHost
    498     SyncBackendHost* host_;
    499 
    500     // The timer used to periodically call SaveChanges.
    501     base::RepeatingTimer<Core> save_changes_timer_;
    502 
    503     // The top-level syncapi entry point.
    504     scoped_ptr<sync_api::SyncManager> syncapi_;
    505 
    506     scoped_ptr<sync_notifier::SyncNotifier> sync_notifier_;
    507 
    508     JsSyncManagerObserver sync_manager_observer_;
    509 
    510     JsEventRouter* parent_router_;
    511 
    512     // Denotes if the core is currently attempting to set a passphrase. While
    513     // this is true, OnPassphraseRequired calls are dropped.
    514     // Note: after initialization, this variable should only ever be accessed or
    515     // modified from within the frontend_loop_ (UI thread).
    516     bool processing_passphrase_;
    517 
    518     // True when a datatype has been disabled so that we nudge once sync is
    519     // resumed (after configuration is finished).
    520     bool deferred_nudge_for_cleanup_requested_;
    521 
    522     DISALLOW_COPY_AND_ASSIGN(Core);
    523   };
    524 
    525   // InitializationComplete passes through the SyncBackendHost to forward
    526   // on to |frontend_|, and so that tests can intercept here if they need to
    527   // set up initial conditions.
    528   virtual void HandleInitializationCompletedOnFrontendLoop();
    529 
    530   // Posts a nudge request on the core thread.
    531   virtual void RequestNudge(const tracked_objects::Location& location);
    532 
    533   // Called to finish the job of ConfigureDataTypes once the syncer is in
    534   // configuration mode.
    535   void FinishConfigureDataTypes();
    536   void FinishConfigureDataTypesOnFrontendLoop();
    537 
    538   // Allows tests to perform alternate core initialization work.
    539   virtual void InitCore(const Core::DoInitializeOptions& options);
    540 
    541   // Factory method for HttpPostProviderFactories.
    542   virtual sync_api::HttpPostProviderFactory* MakeHttpBridgeFactory(
    543       net::URLRequestContextGetter* getter);
    544 
    545   MessageLoop* core_loop() { return core_thread_.message_loop(); }
    546 
    547   void set_syncapi_initialized() { syncapi_initialized_ = true; }
    548 
    549   // Helpers to persist a token that can be used to bootstrap sync encryption
    550   // across browser restart to avoid requiring the user to re-enter their
    551   // passphrase.  |token| must be valid UTF-8 as we use the PrefService for
    552   // storage.
    553   void PersistEncryptionBootstrapToken(const std::string& token);
    554   std::string RestoreEncryptionBootstrapToken();
    555 
    556   // Our core, which communicates directly to the syncapi.
    557   scoped_refptr<Core> core_;
    558 
    559  private:
    560   FRIEND_TEST_ALL_PREFIXES(SyncBackendHostTest, MakePendingConfigModeState);
    561 
    562   struct PendingConfigureDataTypesState {
    563     PendingConfigureDataTypesState();
    564     ~PendingConfigureDataTypesState();
    565 
    566     // A task that should be called once data type configuration is
    567     // complete.
    568     scoped_ptr<CancelableTask> ready_task;
    569 
    570     // The set of types that we are waiting to be initially synced in a
    571     // configuration cycle.
    572     syncable::ModelTypeSet initial_types;
    573 
    574     // Additional details about which types were added / removed.
    575     bool deleted_type;
    576     syncable::ModelTypeBitSet added_types;
    577   };
    578 
    579   UIModelWorker* ui_worker();
    580 
    581   void ConfigureAutofillMigration();
    582 
    583   // Helper function for ConfigureDataTypes().  Caller owns return
    584   // value.  Takes ownership of |ready_task| (but not |routing_info|).
    585   static PendingConfigureDataTypesState* MakePendingConfigModeState(
    586       const DataTypeController::TypeMap& data_type_controllers,
    587       const syncable::ModelTypeSet& types,
    588       CancelableTask* ready_task,
    589       ModelSafeRoutingInfo* routing_info);
    590 
    591   // A thread we dedicate for use by our Core to perform initialization,
    592   // authentication, handle messages from the syncapi, and periodically tell
    593   // the syncapi to persist itself.
    594   base::Thread core_thread_;
    595 
    596   // A reference to the MessageLoop used to construct |this|, so we know how
    597   // to safely talk back to the SyncFrontend.
    598   MessageLoop* const frontend_loop_;
    599 
    600   Profile* profile_;
    601 
    602   // This is state required to implement ModelSafeWorkerRegistrar.
    603   struct {
    604     // We maintain ownership of all workers.  In some cases, we need to ensure
    605     // shutdown occurs in an expected sequence by Stop()ing certain workers.
    606     // They are guaranteed to be valid because we only destroy elements of
    607     // |workers_| after the syncapi has been destroyed.  Unless a worker is no
    608     // longer needed because all types that get routed to it have been disabled
    609     // (from syncing). In that case, we'll destroy on demand *after* routing
    610     // any dependent types to GROUP_PASSIVE, so that the syncapi doesn't call
    611     // into garbage.  If a key is present, it means at least one ModelType that
    612     // routes to that model safe group is being synced.
    613     WorkerMap workers;
    614     browser_sync::ModelSafeRoutingInfo routing_info;
    615   } registrar_;
    616 
    617   // The user can incur changes to registrar_ at any time from the UI thread.
    618   // The syncapi needs to periodically get a consistent snapshot of the state,
    619   // and it does so from a different thread.  Therefore, we protect creation,
    620   // destruction, and re-routing events by acquiring this lock.  Note that the
    621   // SyncBackendHost may read (on the UI thread or core thread) from registrar_
    622   // without acquiring the lock (which is typically "read ModelSafeWorker
    623   // pointer value", and then invoke methods), because lifetimes are managed on
    624   // the UI thread.  Of course, this comment only applies to ModelSafeWorker
    625   // impls that are themselves thread-safe, such as UIModelWorker.
    626   mutable base::Lock registrar_lock_;
    627 
    628   // The frontend which we serve (and are owned by).
    629   SyncFrontend* frontend_;
    630 
    631   // The change processors that handle the different data types.
    632   std::map<syncable::ModelType, ChangeProcessor*> processors_;
    633 
    634   // Path of the folder that stores the sync data files.
    635   FilePath sync_data_folder_path_;
    636 
    637   scoped_ptr<PendingConfigureDataTypesState> pending_download_state_;
    638   scoped_ptr<PendingConfigureDataTypesState> pending_config_mode_state_;
    639 
    640   // UI-thread cache of the last AuthErrorState received from syncapi.
    641   GoogleServiceAuthError last_auth_error_;
    642 
    643   // UI-thread cache of the last SyncSessionSnapshot received from syncapi.
    644   scoped_ptr<sessions::SyncSessionSnapshot> last_snapshot_;
    645 
    646   // Whether we've processed the initialization complete callback.
    647   bool syncapi_initialized_;
    648 
    649   DISALLOW_COPY_AND_ASSIGN(SyncBackendHost);
    650 };
    651 
    652 }  // namespace browser_sync
    653 
    654 #endif  // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
    655