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
33class CancelableTask;
34class Profile;
35
36namespace net {
37class URLRequestContextGetter;
38}
39
40namespace sync_notifier {
41class SyncNotifier;
42}  // namespace sync_notifier
43
44namespace browser_sync {
45
46namespace sessions {
47struct SyncSessionSnapshot;
48}
49
50class ChangeProcessor;
51class DataTypeController;
52class 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.
59class 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.
114class 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