• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SyncFrontend()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.
~SyncFrontend()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 
sync_data_folder_path()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 
syncapi()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.
DoInitializeForTest(const std::wstring & test_user,sync_api::HttpPostProviderFactory * factory,bool delete_sync_data_folder)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 
core_loop()545   MessageLoop* core_loop() { return core_thread_.message_loop(); }
546 
set_syncapi_initialized()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