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