1 // Copyright (c) 2012 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 #include "chrome/browser/sync/glue/sync_backend_host.h" 6 7 #include <algorithm> 8 #include <map> 9 10 #include "base/bind.h" 11 #include "base/command_line.h" 12 #include "base/compiler_specific.h" 13 #include "base/file_util.h" 14 #include "base/files/file_path.h" 15 #include "base/location.h" 16 #include "base/metrics/histogram.h" 17 #include "base/strings/utf_string_conversions.h" 18 #include "base/threading/thread_restrictions.h" 19 #include "base/timer/timer.h" 20 #include "base/tracked_objects.h" 21 #include "build/build_config.h" 22 #include "chrome/browser/invalidation/invalidation_service.h" 23 #include "chrome/browser/invalidation/invalidation_service_factory.h" 24 #include "chrome/browser/chrome_notification_types.h" 25 #include "chrome/browser/net/network_time_tracker.h" 26 #include "chrome/browser/profiles/profile.h" 27 #include "chrome/browser/signin/token_service.h" 28 #include "chrome/browser/signin/token_service_factory.h" 29 #include "chrome/browser/sync/glue/change_processor.h" 30 #include "chrome/browser/sync/glue/chrome_encryptor.h" 31 #include "chrome/browser/sync/glue/device_info.h" 32 #include "chrome/browser/sync/glue/sync_backend_registrar.h" 33 #include "chrome/browser/sync/glue/synced_device_tracker.h" 34 #include "chrome/browser/sync/sync_prefs.h" 35 #include "chrome/common/chrome_switches.h" 36 #include "chrome/common/chrome_version_info.h" 37 #include "content/public/browser/browser_thread.h" 38 #include "content/public/browser/notification_details.h" 39 #include "content/public/browser/notification_service.h" 40 #include "content/public/browser/notification_source.h" 41 #include "content/public/common/content_client.h" 42 #include "google_apis/gaia/gaia_constants.h" 43 #include "jingle/notifier/base/notification_method.h" 44 #include "jingle/notifier/base/notifier_options.h" 45 #include "net/base/host_port_pair.h" 46 #include "net/url_request/url_request_context_getter.h" 47 #include "sync/internal_api/public/base_transaction.h" 48 #include "sync/internal_api/public/engine/model_safe_worker.h" 49 #include "sync/internal_api/public/http_bridge.h" 50 #include "sync/internal_api/public/internal_components_factory_impl.h" 51 #include "sync/internal_api/public/read_transaction.h" 52 #include "sync/internal_api/public/sync_manager_factory.h" 53 #include "sync/internal_api/public/util/experiments.h" 54 #include "sync/internal_api/public/util/sync_string_conversions.h" 55 #include "sync/protocol/encryption.pb.h" 56 #include "sync/protocol/sync.pb.h" 57 #include "sync/util/nigori.h" 58 59 static const int kSaveChangesIntervalSeconds = 10; 60 static const base::FilePath::CharType kSyncDataFolderName[] = 61 FILE_PATH_LITERAL("Sync Data"); 62 63 typedef TokenService::TokenAvailableDetails TokenAvailableDetails; 64 65 typedef GoogleServiceAuthError AuthError; 66 67 namespace browser_sync { 68 69 using content::BrowserThread; 70 using syncer::InternalComponentsFactory; 71 using syncer::InternalComponentsFactoryImpl; 72 using syncer::sessions::SyncSessionSnapshot; 73 using syncer::SyncCredentials; 74 75 namespace { 76 77 // Helper struct to handle currying params to 78 // SyncBackendHost::Core::DoConfigureSyncer. 79 struct DoConfigureSyncerTypes { 80 DoConfigureSyncerTypes() {} 81 ~DoConfigureSyncerTypes() {} 82 syncer::ModelTypeSet to_download; 83 syncer::ModelTypeSet to_purge; 84 syncer::ModelTypeSet to_journal; 85 syncer::ModelTypeSet to_unapply; 86 }; 87 88 } // namespace 89 90 // Helper macros to log with the syncer thread name; useful when there 91 // are multiple syncers involved. 92 93 #define SLOG(severity) LOG(severity) << name_ << ": " 94 95 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": " 96 97 class SyncBackendHost::Core 98 : public base::RefCountedThreadSafe<SyncBackendHost::Core>, 99 public syncer::SyncEncryptionHandler::Observer, 100 public syncer::SyncManager::Observer { 101 public: 102 Core(const std::string& name, 103 const base::FilePath& sync_data_folder_path, 104 const base::WeakPtr<SyncBackendHost>& backend); 105 106 // SyncManager::Observer implementation. The Core just acts like an air 107 // traffic controller here, forwarding incoming messages to appropriate 108 // landing threads. 109 virtual void OnSyncCycleCompleted( 110 const syncer::sessions::SyncSessionSnapshot& snapshot) OVERRIDE; 111 virtual void OnInitializationComplete( 112 const syncer::WeakHandle<syncer::JsBackend>& js_backend, 113 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& 114 debug_info_listener, 115 bool success, 116 syncer::ModelTypeSet restored_types) OVERRIDE; 117 virtual void OnConnectionStatusChange( 118 syncer::ConnectionStatus status) OVERRIDE; 119 virtual void OnStopSyncingPermanently() OVERRIDE; 120 virtual void OnUpdatedToken(const std::string& token) OVERRIDE; 121 virtual void OnActionableError( 122 const syncer::SyncProtocolError& sync_error) OVERRIDE; 123 124 // SyncEncryptionHandler::Observer implementation. 125 virtual void OnPassphraseRequired( 126 syncer::PassphraseRequiredReason reason, 127 const sync_pb::EncryptedData& pending_keys) OVERRIDE; 128 virtual void OnPassphraseAccepted() OVERRIDE; 129 virtual void OnBootstrapTokenUpdated( 130 const std::string& bootstrap_token, 131 syncer::BootstrapTokenType type) OVERRIDE; 132 virtual void OnEncryptedTypesChanged( 133 syncer::ModelTypeSet encrypted_types, 134 bool encrypt_everything) OVERRIDE; 135 virtual void OnEncryptionComplete() OVERRIDE; 136 virtual void OnCryptographerStateChanged( 137 syncer::Cryptographer* cryptographer) OVERRIDE; 138 virtual void OnPassphraseTypeChanged(syncer::PassphraseType type, 139 base::Time passphrase_time) OVERRIDE; 140 141 // Forwards an invalidation state change to the sync manager. 142 void DoOnInvalidatorStateChange(syncer::InvalidatorState state); 143 144 // Forwards an invalidation to the sync manager. 145 void DoOnIncomingInvalidation( 146 syncer::ObjectIdInvalidationMap invalidation_map); 147 148 // Note: 149 // 150 // The Do* methods are the various entry points from our 151 // SyncBackendHost. They are all called on the sync thread to 152 // actually perform synchronous (and potentially blocking) syncapi 153 // operations. 154 // 155 // Called to perform initialization of the syncapi on behalf of 156 // SyncBackendHost::Initialize. 157 void DoInitialize(scoped_ptr<DoInitializeOptions> options); 158 159 // Called to perform credential update on behalf of 160 // SyncBackendHost::UpdateCredentials. 161 void DoUpdateCredentials(const syncer::SyncCredentials& credentials); 162 163 // Called to tell the syncapi to start syncing (generally after 164 // initialization and authentication). 165 void DoStartSyncing(const syncer::ModelSafeRoutingInfo& routing_info); 166 167 // Called to set the passphrase for encryption. 168 void DoSetEncryptionPassphrase(const std::string& passphrase, 169 bool is_explicit); 170 171 // Called to decrypt the pending keys. 172 void DoSetDecryptionPassphrase(const std::string& passphrase); 173 174 // Called to turn on encryption of all sync data as well as 175 // reencrypt everything. 176 void DoEnableEncryptEverything(); 177 178 // Called at startup to download the control types. Will invoke 179 // DoInitialProcessControlTypes on success, and OnControlTypesDownloadRetry 180 // if an error occurred. 181 void DoDownloadControlTypes(syncer::ConfigureReason reason); 182 183 // Ask the syncer to check for updates for the specified types. 184 void DoRefreshTypes(syncer::ModelTypeSet types); 185 186 // Invoked if we failed to download the necessary control types at startup. 187 // Invokes SyncBackendHost::HandleControlTypesDownloadRetry. 188 void OnControlTypesDownloadRetry(); 189 190 // Called to perform tasks which require the control data to be downloaded. 191 // This includes refreshing encryption, setting up the device info change 192 // processor, etc. 193 void DoInitialProcessControlTypes(); 194 195 // Some parts of DoInitialProcessControlTypes() may be executed on a different 196 // thread. This function asynchronously continues the work started in 197 // DoInitialProcessControlTypes() once that other thread gets back to us. 198 void DoFinishInitialProcessControlTypes(); 199 200 // The shutdown order is a bit complicated: 201 // 1) Call DoStopSyncManagerForShutdown() from |frontend_loop_| to request 202 // sync manager to stop as soon as possible. 203 // 2) Post DoShutdown() to sync loop to clean up backend state, save 204 // directory and destroy sync manager. 205 void DoStopSyncManagerForShutdown(); 206 void DoShutdown(bool sync_disabled); 207 void DoDestroySyncManager(); 208 209 // Configuration methods that must execute on sync loop. 210 void DoConfigureSyncer( 211 syncer::ConfigureReason reason, 212 const DoConfigureSyncerTypes& config_types, 213 const syncer::ModelSafeRoutingInfo routing_info, 214 const base::Callback<void(syncer::ModelTypeSet, 215 syncer::ModelTypeSet)>& ready_task, 216 const base::Closure& retry_callback); 217 void DoFinishConfigureDataTypes( 218 syncer::ModelTypeSet types_to_config, 219 const base::Callback<void(syncer::ModelTypeSet, 220 syncer::ModelTypeSet)>& ready_task); 221 void DoRetryConfiguration( 222 const base::Closure& retry_callback); 223 224 // Set the base request context to use when making HTTP calls. 225 // This method will add a reference to the context to persist it 226 // on the IO thread. Must be removed from IO thread. 227 228 syncer::SyncManager* sync_manager() { return sync_manager_.get(); } 229 230 SyncedDeviceTracker* synced_device_tracker() { 231 return synced_device_tracker_.get(); 232 } 233 234 // Delete the sync data folder to cleanup backend data. Happens the first 235 // time sync is enabled for a user (to prevent accidentally reusing old 236 // sync databases), as well as shutdown when you're no longer syncing. 237 void DeleteSyncDataFolder(); 238 239 private: 240 friend class base::RefCountedThreadSafe<SyncBackendHost::Core>; 241 friend class SyncBackendHostForProfileSyncTest; 242 243 virtual ~Core(); 244 245 // Invoked when initialization of syncapi is complete and we can start 246 // our timer. 247 // This must be called from the thread on which SaveChanges is intended to 248 // be run on; the host's |registrar_->sync_thread()|. 249 void StartSavingChanges(); 250 251 // Invoked periodically to tell the syncapi to persist its state 252 // by writing to disk. 253 // This is called from the thread we were created on (which is sync thread), 254 // using a repeating timer that is kicked off as soon as the SyncManager 255 // tells us it completed initialization. 256 void SaveChanges(); 257 258 // Name used for debugging. 259 const std::string name_; 260 261 // Path of the folder that stores the sync data files. 262 const base::FilePath sync_data_folder_path_; 263 264 // Our parent SyncBackendHost. 265 syncer::WeakHandle<SyncBackendHost> host_; 266 267 // The loop where all the sync backend operations happen. 268 // Non-NULL only between calls to DoInitialize() and ~Core(). 269 base::MessageLoop* sync_loop_; 270 271 // Our parent's registrar (not owned). Non-NULL only between 272 // calls to DoInitialize() and DoShutdown(). 273 SyncBackendRegistrar* registrar_; 274 275 // The timer used to periodically call SaveChanges. 276 scoped_ptr<base::RepeatingTimer<Core> > save_changes_timer_; 277 278 // Our encryptor, which uses Chrome's encryption functions. 279 ChromeEncryptor encryptor_; 280 281 // A special ChangeProcessor that tracks the DEVICE_INFO type for us. 282 scoped_ptr<SyncedDeviceTracker> synced_device_tracker_; 283 284 // The top-level syncapi entry point. Lives on the sync thread. 285 scoped_ptr<syncer::SyncManager> sync_manager_; 286 287 base::WeakPtrFactory<Core> weak_ptr_factory_; 288 289 DISALLOW_COPY_AND_ASSIGN(Core); 290 }; 291 292 SyncBackendHost::SyncBackendHost( 293 const std::string& name, 294 Profile* profile, 295 const base::WeakPtr<SyncPrefs>& sync_prefs) 296 : weak_ptr_factory_(this), 297 frontend_loop_(base::MessageLoop::current()), 298 profile_(profile), 299 name_(name), 300 core_(new Core(name_, profile_->GetPath().Append(kSyncDataFolderName), 301 weak_ptr_factory_.GetWeakPtr())), 302 initialization_state_(NOT_ATTEMPTED), 303 sync_prefs_(sync_prefs), 304 frontend_(NULL), 305 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE), 306 invalidator_( 307 invalidation::InvalidationServiceFactory::GetForProfile(profile)), 308 invalidation_handler_registered_(false) { 309 } 310 311 SyncBackendHost::SyncBackendHost(Profile* profile) 312 : weak_ptr_factory_(this), 313 frontend_loop_(base::MessageLoop::current()), 314 profile_(profile), 315 name_("Unknown"), 316 initialization_state_(NOT_ATTEMPTED), 317 frontend_(NULL), 318 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE), 319 invalidation_handler_registered_(false) { 320 } 321 322 SyncBackendHost::~SyncBackendHost() { 323 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor."; 324 DCHECK(!registrar_.get()); 325 } 326 327 namespace { 328 329 scoped_ptr<syncer::HttpPostProviderFactory> MakeHttpBridgeFactory( 330 const scoped_refptr<net::URLRequestContextGetter>& getter, 331 const NetworkTimeTracker::UpdateCallback& update_callback) { 332 chrome::VersionInfo version_info; 333 return scoped_ptr<syncer::HttpPostProviderFactory>( 334 new syncer::HttpBridgeFactory( 335 getter.get(), 336 DeviceInfo::MakeUserAgentForSyncApi(version_info), 337 update_callback)); 338 } 339 340 } // namespace 341 342 void SyncBackendHost::Initialize( 343 SyncFrontend* frontend, 344 scoped_ptr<base::Thread> sync_thread, 345 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler, 346 const GURL& sync_service_url, 347 const SyncCredentials& credentials, 348 bool delete_sync_data_folder, 349 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory, 350 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler, 351 syncer::ReportUnrecoverableErrorFunction 352 report_unrecoverable_error_function) { 353 registrar_.reset(new SyncBackendRegistrar(name_, 354 profile_, 355 sync_thread.Pass())); 356 CHECK(registrar_->sync_thread()); 357 358 frontend_ = frontend; 359 DCHECK(frontend); 360 361 syncer::ModelSafeRoutingInfo routing_info; 362 std::vector<syncer::ModelSafeWorker*> workers; 363 registrar_->GetModelSafeRoutingInfo(&routing_info); 364 registrar_->GetWorkers(&workers); 365 366 InternalComponentsFactory::Switches factory_switches = { 367 InternalComponentsFactory::ENCRYPTION_KEYSTORE, 368 InternalComponentsFactory::BACKOFF_NORMAL 369 }; 370 371 CommandLine* cl = CommandLine::ForCurrentProcess(); 372 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) { 373 factory_switches.backoff_override = 374 InternalComponentsFactoryImpl::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE; 375 } 376 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) { 377 factory_switches.pre_commit_updates_policy = 378 InternalComponentsFactoryImpl::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE; 379 } 380 381 initialization_state_ = CREATING_SYNC_MANAGER; 382 383 scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions( 384 registrar_->sync_thread()->message_loop(), 385 registrar_.get(), 386 routing_info, 387 workers, 388 extensions_activity_monitor_.GetExtensionsActivity(), 389 event_handler, 390 sync_service_url, 391 base::Bind(&MakeHttpBridgeFactory, 392 make_scoped_refptr(profile_->GetRequestContext()), 393 NetworkTimeTracker::BuildNotifierUpdateCallback()), 394 credentials, 395 invalidator_->GetInvalidatorClientId(), 396 sync_manager_factory.Pass(), 397 delete_sync_data_folder, 398 sync_prefs_->GetEncryptionBootstrapToken(), 399 sync_prefs_->GetKeystoreEncryptionBootstrapToken(), 400 scoped_ptr<InternalComponentsFactory>( 401 new InternalComponentsFactoryImpl(factory_switches)).Pass(), 402 unrecoverable_error_handler.Pass(), 403 report_unrecoverable_error_function, 404 !cl->HasSwitch(switches::kSyncDisableOAuth2Token))); 405 InitCore(init_opts.Pass()); 406 } 407 408 void SyncBackendHost::UpdateCredentials(const SyncCredentials& credentials) { 409 DCHECK(registrar_->sync_thread()->IsRunning()); 410 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, 411 base::Bind(&SyncBackendHost::Core::DoUpdateCredentials, 412 core_.get(), 413 credentials)); 414 } 415 416 void SyncBackendHost::StartSyncingWithServer() { 417 SDVLOG(1) << "SyncBackendHost::StartSyncingWithServer called."; 418 419 syncer::ModelSafeRoutingInfo routing_info; 420 registrar_->GetModelSafeRoutingInfo(&routing_info); 421 422 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, 423 base::Bind(&SyncBackendHost::Core::DoStartSyncing, 424 core_.get(), routing_info)); 425 } 426 427 void SyncBackendHost::SetEncryptionPassphrase(const std::string& passphrase, 428 bool is_explicit) { 429 DCHECK(registrar_->sync_thread()->IsRunning()); 430 if (!IsNigoriEnabled()) { 431 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori" 432 " is disabled."; 433 return; 434 } 435 436 // We should never be called with an empty passphrase. 437 DCHECK(!passphrase.empty()); 438 439 // This should only be called by the frontend. 440 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 441 442 // SetEncryptionPassphrase should never be called if we are currently 443 // encrypted with an explicit passphrase. 444 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE || 445 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE); 446 447 // Post an encryption task on the syncer thread. 448 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, 449 base::Bind(&SyncBackendHost::Core::DoSetEncryptionPassphrase, 450 core_.get(), 451 passphrase, is_explicit)); 452 } 453 454 bool SyncBackendHost::SetDecryptionPassphrase(const std::string& passphrase) { 455 if (!IsNigoriEnabled()) { 456 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori" 457 " is disabled."; 458 return false; 459 } 460 461 // We should never be called with an empty passphrase. 462 DCHECK(!passphrase.empty()); 463 464 // This should only be called by the frontend. 465 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 466 467 // This should only be called when we have cached pending keys. 468 DCHECK(cached_pending_keys_.has_blob()); 469 470 // Check the passphrase that was provided against our local cache of the 471 // cryptographer's pending keys. If this was unsuccessful, the UI layer can 472 // immediately call OnPassphraseRequired without showing the user a spinner. 473 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase)) 474 return false; 475 476 // Post a decryption task on the syncer thread. 477 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, 478 base::Bind(&SyncBackendHost::Core::DoSetDecryptionPassphrase, 479 core_.get(), 480 passphrase)); 481 482 // Since we were able to decrypt the cached pending keys with the passphrase 483 // provided, we immediately alert the UI layer that the passphrase was 484 // accepted. This will avoid the situation where a user enters a passphrase, 485 // clicks OK, immediately reopens the advanced settings dialog, and gets an 486 // unnecessary prompt for a passphrase. 487 // Note: It is not guaranteed that the passphrase will be accepted by the 488 // syncer thread, since we could receive a new nigori node while the task is 489 // pending. This scenario is a valid race, and SetDecryptionPassphrase can 490 // trigger a new OnPassphraseRequired if it needs to. 491 NotifyPassphraseAccepted(); 492 return true; 493 } 494 495 void SyncBackendHost::StopSyncManagerForShutdown() { 496 DCHECK_GT(initialization_state_, NOT_ATTEMPTED); 497 if (initialization_state_ == CREATING_SYNC_MANAGER) { 498 // We post here to implicitly wait for the SyncManager to be created, 499 // if needed. We have to wait, since we need to shutdown immediately, 500 // and we need to tell the SyncManager so it can abort any activity 501 // (net I/O, data application). 502 DCHECK(registrar_->sync_thread()->IsRunning()); 503 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, 504 base::Bind(&SyncBackendHost::Core::DoStopSyncManagerForShutdown, 505 core_.get())); 506 } else { 507 core_->DoStopSyncManagerForShutdown(); 508 } 509 } 510 511 void SyncBackendHost::StopSyncingForShutdown() { 512 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 513 514 // Immediately stop sending messages to the frontend. 515 frontend_ = NULL; 516 517 // Stop listening for and forwarding locally-triggered sync refresh requests. 518 notification_registrar_.RemoveAll(); 519 520 DCHECK(registrar_->sync_thread()->IsRunning()); 521 522 registrar_->RequestWorkerStopOnUIThread(); 523 524 StopSyncManagerForShutdown(); 525 } 526 527 scoped_ptr<base::Thread> SyncBackendHost::Shutdown(ShutdownOption option) { 528 // StopSyncingForShutdown() (which nulls out |frontend_|) should be 529 // called first. 530 DCHECK(!frontend_); 531 DCHECK(registrar_->sync_thread()->IsRunning()); 532 533 bool sync_disabled = (option == DISABLE_AND_CLAIM_THREAD); 534 bool sync_thread_claimed = 535 (option == DISABLE_AND_CLAIM_THREAD || option == STOP_AND_CLAIM_THREAD); 536 537 if (invalidation_handler_registered_) { 538 if (sync_disabled) { 539 UnregisterInvalidationIds(); 540 } 541 invalidator_->UnregisterInvalidationHandler(this); 542 invalidator_ = NULL; 543 } 544 invalidation_handler_registered_ = false; 545 546 // Shut down and destroy sync manager. 547 registrar_->sync_thread()->message_loop()->PostTask( 548 FROM_HERE, 549 base::Bind(&SyncBackendHost::Core::DoShutdown, 550 core_.get(), sync_disabled)); 551 core_ = NULL; 552 553 // Worker cleanup. 554 SyncBackendRegistrar* detached_registrar = registrar_.release(); 555 detached_registrar->sync_thread()->message_loop()->PostTask( 556 FROM_HERE, 557 base::Bind(&SyncBackendRegistrar::Shutdown, 558 base::Unretained(detached_registrar))); 559 560 js_backend_.Reset(); 561 if (sync_thread_claimed) 562 return detached_registrar->ReleaseSyncThread(); 563 else 564 return scoped_ptr<base::Thread>(); 565 } 566 567 void SyncBackendHost::UnregisterInvalidationIds() { 568 if (invalidation_handler_registered_) { 569 invalidator_->UpdateRegisteredInvalidationIds( 570 this, 571 syncer::ObjectIdSet()); 572 } 573 } 574 575 void SyncBackendHost::ConfigureDataTypes( 576 syncer::ConfigureReason reason, 577 const DataTypeConfigStateMap& config_state_map, 578 const base::Callback<void(syncer::ModelTypeSet, 579 syncer::ModelTypeSet)>& ready_task, 580 const base::Callback<void()>& retry_callback) { 581 // Only one configure is allowed at a time. This is guaranteed by our 582 // callers. The SyncBackendHost requests one configure as the backend is 583 // initializing and waits for it to complete. After initialization, all 584 // configurations will pass through the DataTypeManager, which is careful to 585 // never send a new configure request until the current request succeeds. 586 587 DCHECK_EQ(initialization_state_, INITIALIZED); 588 589 // The SyncBackendRegistrar's routing info will be updated by adding the 590 // types_to_add to the list then removing types_to_remove. Any types which 591 // are not in either of those sets will remain untouched. 592 // 593 // Types which were not in the list previously are not fully downloaded, so we 594 // must ask the syncer to download them. Any newly supported datatypes will 595 // not have been in that routing info list, so they will be among the types 596 // downloaded if they are enabled. 597 // 598 // The SyncBackendRegistrar's state was initially derived from the types 599 // detected to have been downloaded in the database. Afterwards it is 600 // modified only by this function. We expect it to remain in sync with the 601 // backend because configuration requests are never aborted; they are retried 602 // until they succeed or the backend is shut down. 603 604 syncer::ModelTypeSet previous_types = registrar_->GetLastConfiguredTypes(); 605 606 syncer::ModelTypeSet disabled_types = 607 GetDataTypesInState(DISABLED, config_state_map); 608 syncer::ModelTypeSet fatal_types = 609 GetDataTypesInState(FATAL, config_state_map); 610 syncer::ModelTypeSet crypto_types = 611 GetDataTypesInState(CRYPTO, config_state_map); 612 disabled_types.PutAll(fatal_types); 613 disabled_types.PutAll(crypto_types); 614 syncer::ModelTypeSet active_types = 615 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map); 616 syncer::ModelTypeSet clean_first_types = 617 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map); 618 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes( 619 syncer::Union(active_types, clean_first_types), 620 disabled_types); 621 types_to_download.PutAll(clean_first_types); 622 types_to_download.RemoveAll(syncer::ProxyTypes()); 623 if (!types_to_download.Empty()) 624 types_to_download.Put(syncer::NIGORI); 625 626 // TODO(sync): crbug.com/137550. 627 // It's dangerous to configure types that have progress markers. Types with 628 // progress markers can trigger a MIGRATION_DONE response. We are not 629 // prepared to handle a migration during a configure, so we must ensure that 630 // all our types_to_download actually contain no data before we sync them. 631 // 632 // One common way to end up in this situation used to be types which 633 // downloaded some or all of their data but have not applied it yet. We avoid 634 // problems with those types by purging the data of any such partially synced 635 // types soon after we load the directory. 636 // 637 // Another possible scenario is that we have newly supported or newly enabled 638 // data types being downloaded here but the nigori type, which is always 639 // included in any GetUpdates request, requires migration. The server has 640 // code to detect this scenario based on the configure reason, the fact that 641 // the nigori type is the only requested type which requires migration, and 642 // that the requested types list includes at least one non-nigori type. It 643 // will not send a MIGRATION_DONE response in that case. We still need to be 644 // careful to not send progress markers for non-nigori types, though. If a 645 // non-nigori type in the request requires migration, a MIGRATION_DONE 646 // response will be sent. 647 648 syncer::ModelSafeRoutingInfo routing_info; 649 registrar_->GetModelSafeRoutingInfo(&routing_info); 650 651 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes(); 652 syncer::ModelTypeSet types_to_purge = 653 syncer::Difference(previous_types, current_types); 654 syncer::ModelTypeSet inactive_types = 655 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map); 656 types_to_purge.RemoveAll(inactive_types); 657 658 DCHECK(syncer::Intersection(current_types, fatal_types).Empty()); 659 DCHECK(syncer::Intersection(current_types, crypto_types).Empty()); 660 DCHECK(current_types.HasAll(types_to_download)); 661 662 SDVLOG(1) << "Types " 663 << syncer::ModelTypeSetToString(types_to_download) 664 << " added; calling DoConfigureSyncer"; 665 // Divide up the types into their corresponding actions (each is mutually 666 // exclusive): 667 // - Types which have just been added to the routing info (types_to_download): 668 // are downloaded. 669 // - Types which have encountered a fatal error (fatal_types) are deleted 670 // from the directory and journaled in the delete journal. 671 // - Types which have encountered a cryptographer error (crypto_types) are 672 // unapplied (local state is purged but sync state is not). 673 // - All other types not in the routing info (types just disabled) are deleted 674 // from the directory. 675 // - Everything else (enabled types and already disabled types) is not 676 // touched. 677 RequestConfigureSyncer(reason, 678 types_to_download, 679 types_to_purge, 680 fatal_types, 681 syncer::Union(crypto_types, clean_first_types), 682 inactive_types, 683 routing_info, 684 ready_task, 685 retry_callback); 686 } 687 688 void SyncBackendHost::EnableEncryptEverything() { 689 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, 690 base::Bind(&SyncBackendHost::Core::DoEnableEncryptEverything, 691 core_.get())); 692 } 693 694 void SyncBackendHost::ActivateDataType( 695 syncer::ModelType type, syncer::ModelSafeGroup group, 696 ChangeProcessor* change_processor) { 697 registrar_->ActivateDataType(type, group, change_processor, GetUserShare()); 698 } 699 700 void SyncBackendHost::DeactivateDataType(syncer::ModelType type) { 701 registrar_->DeactivateDataType(type); 702 } 703 704 syncer::UserShare* SyncBackendHost::GetUserShare() const { 705 return core_->sync_manager()->GetUserShare(); 706 } 707 708 SyncBackendHost::Status SyncBackendHost::GetDetailedStatus() { 709 DCHECK(initialized()); 710 return core_->sync_manager()->GetDetailedStatus(); 711 } 712 713 SyncSessionSnapshot SyncBackendHost::GetLastSessionSnapshot() const { 714 return last_snapshot_; 715 } 716 717 bool SyncBackendHost::HasUnsyncedItems() const { 718 DCHECK(initialized()); 719 return core_->sync_manager()->HasUnsyncedItems(); 720 } 721 722 bool SyncBackendHost::IsNigoriEnabled() const { 723 return registrar_.get() && registrar_->IsNigoriEnabled(); 724 } 725 726 syncer::PassphraseType SyncBackendHost::GetPassphraseType() const { 727 return cached_passphrase_type_; 728 } 729 730 base::Time SyncBackendHost::GetExplicitPassphraseTime() const { 731 return cached_explicit_passphrase_time_; 732 } 733 734 bool SyncBackendHost::IsCryptographerReady( 735 const syncer::BaseTransaction* trans) const { 736 return initialized() && trans->GetCryptographer()->is_ready(); 737 } 738 739 void SyncBackendHost::GetModelSafeRoutingInfo( 740 syncer::ModelSafeRoutingInfo* out) const { 741 if (initialized()) { 742 CHECK(registrar_.get()); 743 registrar_->GetModelSafeRoutingInfo(out); 744 } else { 745 NOTREACHED(); 746 } 747 } 748 749 SyncedDeviceTracker* SyncBackendHost::GetSyncedDeviceTracker() const { 750 if (!initialized()) 751 return NULL; 752 return core_->synced_device_tracker(); 753 } 754 755 void SyncBackendHost::InitCore(scoped_ptr<DoInitializeOptions> options) { 756 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, 757 base::Bind(&SyncBackendHost::Core::DoInitialize, 758 core_.get(), base::Passed(&options))); 759 } 760 761 void SyncBackendHost::RequestConfigureSyncer( 762 syncer::ConfigureReason reason, 763 syncer::ModelTypeSet to_download, 764 syncer::ModelTypeSet to_purge, 765 syncer::ModelTypeSet to_journal, 766 syncer::ModelTypeSet to_unapply, 767 syncer::ModelTypeSet to_ignore, 768 const syncer::ModelSafeRoutingInfo& routing_info, 769 const base::Callback<void(syncer::ModelTypeSet, 770 syncer::ModelTypeSet)>& ready_task, 771 const base::Closure& retry_callback) { 772 DoConfigureSyncerTypes config_types; 773 config_types.to_download = to_download; 774 config_types.to_purge = to_purge; 775 config_types.to_journal = to_journal; 776 config_types.to_unapply = to_unapply; 777 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, 778 base::Bind(&SyncBackendHost::Core::DoConfigureSyncer, 779 core_.get(), 780 reason, 781 config_types, 782 routing_info, 783 ready_task, 784 retry_callback)); 785 } 786 787 void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop( 788 const syncer::ModelTypeSet enabled_types, 789 const syncer::ModelTypeSet succeeded_configuration_types, 790 const syncer::ModelTypeSet failed_configuration_types, 791 const base::Callback<void(syncer::ModelTypeSet, 792 syncer::ModelTypeSet)>& ready_task) { 793 if (!frontend_) 794 return; 795 796 invalidator_->UpdateRegisteredInvalidationIds( 797 this, 798 ModelTypeSetToObjectIdSet(enabled_types)); 799 800 if (!ready_task.is_null()) 801 ready_task.Run(succeeded_configuration_types, failed_configuration_types); 802 } 803 804 void SyncBackendHost::HandleSyncManagerInitializationOnFrontendLoop( 805 const syncer::WeakHandle<syncer::JsBackend>& js_backend, 806 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& 807 debug_info_listener, 808 syncer::ModelTypeSet restored_types) { 809 DCHECK_EQ(initialization_state_, CREATING_SYNC_MANAGER); 810 DCHECK(!js_backend_.IsInitialized()); 811 812 initialization_state_ = INITIALIZATING_CONTROL_TYPES; 813 814 js_backend_ = js_backend; 815 debug_info_listener_ = debug_info_listener; 816 817 invalidator_->RegisterInvalidationHandler(this); 818 invalidation_handler_registered_ = true; 819 820 // Inform the registrar of those types that have been fully downloaded and 821 // applied. 822 registrar_->SetInitialTypes(restored_types); 823 824 // Start forwarding refresh requests to the SyncManager 825 notification_registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, 826 content::Source<Profile>(profile_)); 827 828 syncer::ConfigureReason reason = 829 (sync_prefs_->HasSyncSetupCompleted() ? 830 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE : 831 syncer::CONFIGURE_REASON_NEW_CLIENT); 832 833 // Fake a state change to initialize the SyncManager's cached invalidator 834 // state. 835 OnInvalidatorStateChange(invalidator_->GetInvalidatorState()); 836 837 // Kick off the next step in SyncBackendHost initialization by downloading 838 // any necessary control types. 839 registrar_->sync_thread()->message_loop()->PostTask( 840 FROM_HERE, 841 base::Bind(&SyncBackendHost::Core::DoDownloadControlTypes, 842 core_.get(), 843 reason)); 844 } 845 846 void SyncBackendHost::Observe( 847 int type, 848 const content::NotificationSource& source, 849 const content::NotificationDetails& details) { 850 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 851 DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL); 852 853 content::Details<const syncer::ModelTypeSet> state_details(details); 854 const syncer::ModelTypeSet& types = *(state_details.ptr()); 855 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE, 856 base::Bind(&SyncBackendHost::Core::DoRefreshTypes, core_.get(), types)); 857 } 858 859 SyncBackendHost::DoInitializeOptions::DoInitializeOptions( 860 base::MessageLoop* sync_loop, 861 SyncBackendRegistrar* registrar, 862 const syncer::ModelSafeRoutingInfo& routing_info, 863 const std::vector<syncer::ModelSafeWorker*>& workers, 864 const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity, 865 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler, 866 const GURL& service_url, 867 MakeHttpBridgeFactoryFn make_http_bridge_factory_fn, 868 const syncer::SyncCredentials& credentials, 869 const std::string& invalidator_client_id, 870 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory, 871 bool delete_sync_data_folder, 872 const std::string& restored_key_for_bootstrapping, 873 const std::string& restored_keystore_key_for_bootstrapping, 874 scoped_ptr<InternalComponentsFactory> internal_components_factory, 875 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler, 876 syncer::ReportUnrecoverableErrorFunction 877 report_unrecoverable_error_function, 878 bool use_oauth2_token) 879 : sync_loop(sync_loop), 880 registrar(registrar), 881 routing_info(routing_info), 882 workers(workers), 883 extensions_activity(extensions_activity), 884 event_handler(event_handler), 885 service_url(service_url), 886 make_http_bridge_factory_fn(make_http_bridge_factory_fn), 887 credentials(credentials), 888 invalidator_client_id(invalidator_client_id), 889 sync_manager_factory(sync_manager_factory.Pass()), 890 delete_sync_data_folder(delete_sync_data_folder), 891 restored_key_for_bootstrapping(restored_key_for_bootstrapping), 892 restored_keystore_key_for_bootstrapping( 893 restored_keystore_key_for_bootstrapping), 894 internal_components_factory(internal_components_factory.Pass()), 895 unrecoverable_error_handler(unrecoverable_error_handler.Pass()), 896 report_unrecoverable_error_function( 897 report_unrecoverable_error_function), 898 use_oauth2_token(use_oauth2_token) { 899 } 900 901 SyncBackendHost::DoInitializeOptions::~DoInitializeOptions() {} 902 903 SyncBackendHost::Core::Core(const std::string& name, 904 const base::FilePath& sync_data_folder_path, 905 const base::WeakPtr<SyncBackendHost>& backend) 906 : name_(name), 907 sync_data_folder_path_(sync_data_folder_path), 908 host_(backend), 909 sync_loop_(NULL), 910 registrar_(NULL), 911 weak_ptr_factory_(this) { 912 DCHECK(backend.get()); 913 } 914 915 SyncBackendHost::Core::~Core() { 916 DCHECK(!sync_manager_.get()); 917 } 918 919 void SyncBackendHost::Core::OnSyncCycleCompleted( 920 const SyncSessionSnapshot& snapshot) { 921 if (!sync_loop_) 922 return; 923 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 924 925 host_.Call( 926 FROM_HERE, 927 &SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop, 928 snapshot); 929 } 930 931 void SyncBackendHost::Core::DoDownloadControlTypes( 932 syncer::ConfigureReason reason) { 933 syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes( 934 syncer::ControlTypes(), syncer::ModelTypeSet()); 935 syncer::ModelSafeRoutingInfo routing_info; 936 registrar_->GetModelSafeRoutingInfo(&routing_info); 937 SDVLOG(1) << "Control Types " 938 << syncer::ModelTypeSetToString(new_control_types) 939 << " added; calling ConfigureSyncer"; 940 941 syncer::ModelTypeSet types_to_purge = 942 syncer::Difference(syncer::ModelTypeSet::All(), 943 GetRoutingInfoTypes(routing_info)); 944 945 sync_manager_->ConfigureSyncer( 946 reason, 947 new_control_types, 948 types_to_purge, 949 syncer::ModelTypeSet(), 950 syncer::ModelTypeSet(), 951 routing_info, 952 base::Bind(&SyncBackendHost::Core::DoInitialProcessControlTypes, 953 weak_ptr_factory_.GetWeakPtr()), 954 base::Bind(&SyncBackendHost::Core::OnControlTypesDownloadRetry, 955 weak_ptr_factory_.GetWeakPtr())); 956 } 957 958 void SyncBackendHost::Core::DoRefreshTypes(syncer::ModelTypeSet types) { 959 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 960 sync_manager_->RefreshTypes(types); 961 } 962 963 void SyncBackendHost::Core::OnControlTypesDownloadRetry() { 964 host_.Call(FROM_HERE, 965 &SyncBackendHost::HandleControlTypesDownloadRetry); 966 } 967 968 void SyncBackendHost::Core::OnInitializationComplete( 969 const syncer::WeakHandle<syncer::JsBackend>& js_backend, 970 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& 971 debug_info_listener, 972 bool success, 973 const syncer::ModelTypeSet restored_types) { 974 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 975 976 if (!success) { 977 DoDestroySyncManager(); 978 host_.Call(FROM_HERE, 979 &SyncBackendHost::HandleInitializationCompletedOnFrontendLoop, 980 false); 981 return; 982 } 983 984 // Register for encryption related changes now. We have to do this before 985 // the initializing downloading control types or initializing the encryption 986 // handler in order to receive notifications triggered during encryption 987 // startup. 988 sync_manager_->GetEncryptionHandler()->AddObserver(this); 989 990 // Sync manager initialization is complete, so we can schedule recurring 991 // SaveChanges. 992 sync_loop_->PostTask(FROM_HERE, 993 base::Bind(&Core::StartSavingChanges, 994 weak_ptr_factory_.GetWeakPtr())); 995 996 host_.Call(FROM_HERE, 997 &SyncBackendHost::HandleSyncManagerInitializationOnFrontendLoop, 998 js_backend, 999 debug_info_listener, 1000 restored_types); 1001 } 1002 1003 void SyncBackendHost::Core::OnConnectionStatusChange( 1004 syncer::ConnectionStatus status) { 1005 if (!sync_loop_) 1006 return; 1007 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1008 host_.Call( 1009 FROM_HERE, 1010 &SyncBackendHost::HandleConnectionStatusChangeOnFrontendLoop, status); 1011 } 1012 1013 void SyncBackendHost::Core::OnPassphraseRequired( 1014 syncer::PassphraseRequiredReason reason, 1015 const sync_pb::EncryptedData& pending_keys) { 1016 if (!sync_loop_) 1017 return; 1018 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1019 host_.Call( 1020 FROM_HERE, 1021 &SyncBackendHost::NotifyPassphraseRequired, reason, pending_keys); 1022 } 1023 1024 void SyncBackendHost::Core::OnPassphraseAccepted() { 1025 if (!sync_loop_) 1026 return; 1027 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1028 host_.Call( 1029 FROM_HERE, 1030 &SyncBackendHost::NotifyPassphraseAccepted); 1031 } 1032 1033 void SyncBackendHost::Core::OnBootstrapTokenUpdated( 1034 const std::string& bootstrap_token, 1035 syncer::BootstrapTokenType type) { 1036 if (!sync_loop_) 1037 return; 1038 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1039 host_.Call(FROM_HERE, 1040 &SyncBackendHost::PersistEncryptionBootstrapToken, 1041 bootstrap_token, 1042 type); 1043 } 1044 1045 void SyncBackendHost::Core::OnStopSyncingPermanently() { 1046 if (!sync_loop_) 1047 return; 1048 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1049 host_.Call( 1050 FROM_HERE, 1051 &SyncBackendHost::HandleStopSyncingPermanentlyOnFrontendLoop); 1052 } 1053 1054 void SyncBackendHost::Core::OnUpdatedToken(const std::string& token) { 1055 if (!sync_loop_) 1056 return; 1057 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1058 host_.Call( 1059 FROM_HERE, 1060 &SyncBackendHost::NotifyUpdatedToken, token); 1061 } 1062 1063 void SyncBackendHost::Core::OnEncryptedTypesChanged( 1064 syncer::ModelTypeSet encrypted_types, 1065 bool encrypt_everything) { 1066 if (!sync_loop_) 1067 return; 1068 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1069 // NOTE: We're in a transaction. 1070 host_.Call( 1071 FROM_HERE, 1072 &SyncBackendHost::NotifyEncryptedTypesChanged, 1073 encrypted_types, encrypt_everything); 1074 } 1075 1076 void SyncBackendHost::Core::OnEncryptionComplete() { 1077 if (!sync_loop_) 1078 return; 1079 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1080 // NOTE: We're in a transaction. 1081 host_.Call( 1082 FROM_HERE, 1083 &SyncBackendHost::NotifyEncryptionComplete); 1084 } 1085 1086 void SyncBackendHost::Core::OnCryptographerStateChanged( 1087 syncer::Cryptographer* cryptographer) { 1088 // Do nothing. 1089 } 1090 1091 void SyncBackendHost::Core::OnPassphraseTypeChanged( 1092 syncer::PassphraseType type, base::Time passphrase_time) { 1093 host_.Call( 1094 FROM_HERE, 1095 &SyncBackendHost::HandlePassphraseTypeChangedOnFrontendLoop, 1096 type, passphrase_time); 1097 } 1098 1099 void SyncBackendHost::Core::OnActionableError( 1100 const syncer::SyncProtocolError& sync_error) { 1101 if (!sync_loop_) 1102 return; 1103 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1104 host_.Call( 1105 FROM_HERE, 1106 &SyncBackendHost::HandleActionableErrorEventOnFrontendLoop, 1107 sync_error); 1108 } 1109 1110 void SyncBackendHost::Core::DoOnInvalidatorStateChange( 1111 syncer::InvalidatorState state) { 1112 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1113 sync_manager_->OnInvalidatorStateChange(state); 1114 } 1115 1116 void SyncBackendHost::Core::DoOnIncomingInvalidation( 1117 syncer::ObjectIdInvalidationMap invalidation_map) { 1118 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1119 sync_manager_->OnIncomingInvalidation(invalidation_map); 1120 } 1121 1122 void SyncBackendHost::Core::DoInitialize( 1123 scoped_ptr<DoInitializeOptions> options) { 1124 DCHECK(!sync_loop_); 1125 sync_loop_ = options->sync_loop; 1126 DCHECK(sync_loop_); 1127 1128 // Blow away the partial or corrupt sync data folder before doing any more 1129 // initialization, if necessary. 1130 if (options->delete_sync_data_folder) { 1131 DeleteSyncDataFolder(); 1132 } 1133 1134 // Make sure that the directory exists before initializing the backend. 1135 // If it already exists, this will do no harm. 1136 if (!file_util::CreateDirectory(sync_data_folder_path_)) { 1137 DLOG(FATAL) << "Sync Data directory creation failed."; 1138 } 1139 1140 DCHECK(!registrar_); 1141 registrar_ = options->registrar; 1142 DCHECK(registrar_); 1143 1144 sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_); 1145 sync_manager_->AddObserver(this); 1146 sync_manager_->Init(sync_data_folder_path_, 1147 options->event_handler, 1148 options->service_url.host() + options->service_url.path(), 1149 options->service_url.EffectiveIntPort(), 1150 options->service_url.SchemeIsSecure(), 1151 options->make_http_bridge_factory_fn.Run().Pass(), 1152 options->workers, 1153 options->extensions_activity, 1154 options->registrar /* as SyncManager::ChangeDelegate */, 1155 options->credentials, 1156 options->invalidator_client_id, 1157 options->restored_key_for_bootstrapping, 1158 options->restored_keystore_key_for_bootstrapping, 1159 options->internal_components_factory.get(), 1160 &encryptor_, 1161 options->unrecoverable_error_handler.Pass(), 1162 options->report_unrecoverable_error_function, 1163 options->use_oauth2_token); 1164 1165 // |sync_manager_| may end up being NULL here in tests (in 1166 // synchronous initialization mode). 1167 // 1168 // TODO(akalin): Fix this behavior (see http://crbug.com/140354). 1169 if (sync_manager_) { 1170 // Now check the command line to see if we need to simulate an 1171 // unrecoverable error for testing purpose. Note the error is thrown 1172 // only if the initialization succeeded. Also it makes sense to use this 1173 // flag only when restarting the browser with an account already setup. If 1174 // you use this before setting up the setup would not succeed as an error 1175 // would be encountered. 1176 if (CommandLine::ForCurrentProcess()->HasSwitch( 1177 switches::kSyncThrowUnrecoverableError)) { 1178 sync_manager_->ThrowUnrecoverableError(); 1179 } 1180 } 1181 } 1182 1183 void SyncBackendHost::Core::DoUpdateCredentials( 1184 const SyncCredentials& credentials) { 1185 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1186 // UpdateCredentials can be called during backend initialization, possibly 1187 // when backend initialization has failed but hasn't notified the UI thread 1188 // yet. In that case, the sync manager may have been destroyed on the sync 1189 // thread before this task was executed, so we do nothing. 1190 if (sync_manager_) { 1191 sync_manager_->UpdateCredentials(credentials); 1192 } 1193 } 1194 1195 void SyncBackendHost::Core::DoStartSyncing( 1196 const syncer::ModelSafeRoutingInfo& routing_info) { 1197 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1198 sync_manager_->StartSyncingNormally(routing_info); 1199 } 1200 1201 void SyncBackendHost::Core::DoSetEncryptionPassphrase( 1202 const std::string& passphrase, 1203 bool is_explicit) { 1204 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1205 sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase( 1206 passphrase, is_explicit); 1207 } 1208 1209 void SyncBackendHost::Core::DoInitialProcessControlTypes() { 1210 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1211 1212 DVLOG(1) << "Initilalizing Control Types"; 1213 1214 // Initialize encryption. 1215 sync_manager_->GetEncryptionHandler()->Init(); 1216 1217 // Note: experiments are currently handled via SBH::AddExperimentalTypes, 1218 // which is called at the end of every sync cycle. 1219 // TODO(zea): eventually add an experiment handler and initialize it here. 1220 1221 if (!sync_manager_->GetUserShare()) { // NULL in some tests. 1222 DVLOG(1) << "Skipping initialization of DeviceInfo"; 1223 host_.Call( 1224 FROM_HERE, 1225 &SyncBackendHost::HandleInitializationCompletedOnFrontendLoop, 1226 true); 1227 return; 1228 } 1229 1230 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) { 1231 LOG(ERROR) << "Failed to download control types"; 1232 host_.Call( 1233 FROM_HERE, 1234 &SyncBackendHost::HandleInitializationCompletedOnFrontendLoop, 1235 false); 1236 return; 1237 } 1238 1239 // Initialize device info. This is asynchronous on some platforms, so we 1240 // provide a callback for when it finishes. 1241 synced_device_tracker_.reset( 1242 new SyncedDeviceTracker(sync_manager_->GetUserShare(), 1243 sync_manager_->cache_guid())); 1244 synced_device_tracker_->InitLocalDeviceInfo( 1245 base::Bind(&SyncBackendHost::Core::DoFinishInitialProcessControlTypes, 1246 weak_ptr_factory_.GetWeakPtr())); 1247 } 1248 1249 void SyncBackendHost::Core::DoFinishInitialProcessControlTypes() { 1250 registrar_->ActivateDataType(syncer::DEVICE_INFO, 1251 syncer::GROUP_PASSIVE, 1252 synced_device_tracker_.get(), 1253 sync_manager_->GetUserShare()); 1254 1255 host_.Call( 1256 FROM_HERE, 1257 &SyncBackendHost::HandleInitializationCompletedOnFrontendLoop, 1258 true); 1259 } 1260 1261 void SyncBackendHost::Core::DoSetDecryptionPassphrase( 1262 const std::string& passphrase) { 1263 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1264 sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase( 1265 passphrase); 1266 } 1267 1268 void SyncBackendHost::Core::DoEnableEncryptEverything() { 1269 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1270 sync_manager_->GetEncryptionHandler()->EnableEncryptEverything(); 1271 } 1272 1273 void SyncBackendHost::Core::DoStopSyncManagerForShutdown() { 1274 if (sync_manager_) 1275 sync_manager_->StopSyncingForShutdown(); 1276 } 1277 1278 void SyncBackendHost::Core::DoShutdown(bool sync_disabled) { 1279 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1280 // It's safe to do this even if the type was never activated. 1281 registrar_->DeactivateDataType(syncer::DEVICE_INFO); 1282 synced_device_tracker_.reset(); 1283 1284 DoDestroySyncManager(); 1285 1286 registrar_ = NULL; 1287 1288 if (sync_disabled) 1289 DeleteSyncDataFolder(); 1290 1291 host_.Reset(); 1292 weak_ptr_factory_.InvalidateWeakPtrs(); 1293 } 1294 1295 void SyncBackendHost::Core::DoDestroySyncManager() { 1296 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1297 if (sync_manager_) { 1298 save_changes_timer_.reset(); 1299 sync_manager_->RemoveObserver(this); 1300 sync_manager_->ShutdownOnSyncThread(); 1301 sync_manager_.reset(); 1302 } 1303 } 1304 1305 void SyncBackendHost::Core::DoConfigureSyncer( 1306 syncer::ConfigureReason reason, 1307 const DoConfigureSyncerTypes& config_types, 1308 const syncer::ModelSafeRoutingInfo routing_info, 1309 const base::Callback<void(syncer::ModelTypeSet, 1310 syncer::ModelTypeSet)>& ready_task, 1311 const base::Closure& retry_callback) { 1312 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1313 sync_manager_->ConfigureSyncer( 1314 reason, 1315 config_types.to_download, 1316 config_types.to_purge, 1317 config_types.to_journal, 1318 config_types.to_unapply, 1319 routing_info, 1320 base::Bind(&SyncBackendHost::Core::DoFinishConfigureDataTypes, 1321 weak_ptr_factory_.GetWeakPtr(), 1322 config_types.to_download, 1323 ready_task), 1324 base::Bind(&SyncBackendHost::Core::DoRetryConfiguration, 1325 weak_ptr_factory_.GetWeakPtr(), 1326 retry_callback)); 1327 } 1328 1329 void SyncBackendHost::Core::DoFinishConfigureDataTypes( 1330 syncer::ModelTypeSet types_to_config, 1331 const base::Callback<void(syncer::ModelTypeSet, 1332 syncer::ModelTypeSet)>& ready_task) { 1333 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1334 1335 // Update the enabled types for the bridge and sync manager. 1336 syncer::ModelSafeRoutingInfo routing_info; 1337 registrar_->GetModelSafeRoutingInfo(&routing_info); 1338 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info); 1339 enabled_types.RemoveAll(syncer::ProxyTypes()); 1340 1341 const syncer::ModelTypeSet failed_configuration_types = 1342 Difference(types_to_config, sync_manager_->InitialSyncEndedTypes()); 1343 const syncer::ModelTypeSet succeeded_configuration_types = 1344 Difference(types_to_config, failed_configuration_types); 1345 host_.Call(FROM_HERE, 1346 &SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop, 1347 enabled_types, 1348 succeeded_configuration_types, 1349 failed_configuration_types, 1350 ready_task); 1351 } 1352 1353 void SyncBackendHost::Core::DoRetryConfiguration( 1354 const base::Closure& retry_callback) { 1355 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1356 host_.Call(FROM_HERE, 1357 &SyncBackendHost::RetryConfigurationOnFrontendLoop, 1358 retry_callback); 1359 } 1360 1361 void SyncBackendHost::Core::DeleteSyncDataFolder() { 1362 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1363 if (base::DirectoryExists(sync_data_folder_path_)) { 1364 if (!base::DeleteFile(sync_data_folder_path_, true)) 1365 SLOG(DFATAL) << "Could not delete the Sync Data folder."; 1366 } 1367 } 1368 1369 void SyncBackendHost::Core::StartSavingChanges() { 1370 // We may already be shut down. 1371 if (!sync_loop_) 1372 return; 1373 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1374 DCHECK(!save_changes_timer_.get()); 1375 save_changes_timer_.reset(new base::RepeatingTimer<Core>()); 1376 save_changes_timer_->Start(FROM_HERE, 1377 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds), 1378 this, &Core::SaveChanges); 1379 } 1380 1381 void SyncBackendHost::Core::SaveChanges() { 1382 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 1383 sync_manager_->SaveChanges(); 1384 } 1385 1386 void SyncBackendHost::AddExperimentalTypes() { 1387 CHECK(initialized()); 1388 syncer::Experiments experiments; 1389 if (core_->sync_manager()->ReceivedExperiment(&experiments)) 1390 frontend_->OnExperimentsChanged(experiments); 1391 } 1392 1393 void SyncBackendHost::HandleControlTypesDownloadRetry() { 1394 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1395 if (!frontend_) 1396 return; 1397 1398 frontend_->OnSyncConfigureRetry(); 1399 } 1400 1401 void SyncBackendHost::HandleInitializationCompletedOnFrontendLoop( 1402 bool success) { 1403 DCHECK_NE(initialization_state_, NOT_ATTEMPTED); 1404 if (!frontend_) 1405 return; 1406 1407 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1408 if (!success) { 1409 js_backend_.Reset(); 1410 initialization_state_ = NOT_INITIALIZED; 1411 frontend_->OnBackendInitialized( 1412 syncer::WeakHandle<syncer::JsBackend>(), 1413 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), 1414 false); 1415 return; 1416 } 1417 1418 initialization_state_ = INITIALIZED; 1419 1420 // Now that we've downloaded the control types, we can see if there are any 1421 // experimental types to enable. This should be done before we inform 1422 // the frontend to ensure they're visible in the customize screen. 1423 AddExperimentalTypes(); 1424 frontend_->OnBackendInitialized(js_backend_, 1425 debug_info_listener_, 1426 true); 1427 js_backend_.Reset(); 1428 } 1429 1430 void SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop( 1431 const SyncSessionSnapshot& snapshot) { 1432 if (!frontend_) 1433 return; 1434 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1435 1436 last_snapshot_ = snapshot; 1437 1438 SDVLOG(1) << "Got snapshot " << snapshot.ToString(); 1439 1440 const syncer::ModelTypeSet to_migrate = 1441 snapshot.model_neutral_state().types_needing_local_migration; 1442 if (!to_migrate.Empty()) 1443 frontend_->OnMigrationNeededForTypes(to_migrate); 1444 1445 // Process any changes to the datatypes we're syncing. 1446 // TODO(sync): add support for removing types. 1447 if (initialized()) 1448 AddExperimentalTypes(); 1449 1450 if (initialized()) 1451 frontend_->OnSyncCycleCompleted(); 1452 } 1453 1454 void SyncBackendHost::RetryConfigurationOnFrontendLoop( 1455 const base::Closure& retry_callback) { 1456 SDVLOG(1) << "Failed to complete configuration, informing of retry."; 1457 retry_callback.Run(); 1458 } 1459 1460 void SyncBackendHost::PersistEncryptionBootstrapToken( 1461 const std::string& token, 1462 syncer::BootstrapTokenType token_type) { 1463 CHECK(sync_prefs_.get()); 1464 DCHECK(!token.empty()); 1465 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN) 1466 sync_prefs_->SetEncryptionBootstrapToken(token); 1467 else 1468 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token); 1469 } 1470 1471 void SyncBackendHost::HandleActionableErrorEventOnFrontendLoop( 1472 const syncer::SyncProtocolError& sync_error) { 1473 if (!frontend_) 1474 return; 1475 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1476 frontend_->OnActionableError(sync_error); 1477 } 1478 1479 void SyncBackendHost::OnInvalidatorStateChange(syncer::InvalidatorState state) { 1480 registrar_->sync_thread()->message_loop()->PostTask( 1481 FROM_HERE, 1482 base::Bind(&SyncBackendHost::Core::DoOnInvalidatorStateChange, 1483 core_.get(), 1484 state)); 1485 } 1486 1487 void SyncBackendHost::OnIncomingInvalidation( 1488 const syncer::ObjectIdInvalidationMap& invalidation_map) { 1489 // TODO(dcheng): Acknowledge immediately for now. Fix this once the 1490 // invalidator doesn't repeatedly ping for unacknowledged invaliations, since 1491 // it conflicts with the sync scheduler's internal backoff algorithm. 1492 // See http://crbug.com/124149 for more information. 1493 for (syncer::ObjectIdInvalidationMap::const_iterator it = 1494 invalidation_map.begin(); it != invalidation_map.end(); ++it) { 1495 invalidator_->AcknowledgeInvalidation(it->first, it->second.ack_handle); 1496 } 1497 1498 registrar_->sync_thread()->message_loop()->PostTask( 1499 FROM_HERE, 1500 base::Bind(&SyncBackendHost::Core::DoOnIncomingInvalidation, 1501 core_.get(), 1502 invalidation_map)); 1503 } 1504 1505 bool SyncBackendHost::CheckPassphraseAgainstCachedPendingKeys( 1506 const std::string& passphrase) const { 1507 DCHECK(cached_pending_keys_.has_blob()); 1508 DCHECK(!passphrase.empty()); 1509 syncer::Nigori nigori; 1510 nigori.InitByDerivation("localhost", "dummy", passphrase); 1511 std::string plaintext; 1512 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext); 1513 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys."; 1514 return result; 1515 } 1516 1517 void SyncBackendHost::NotifyPassphraseRequired( 1518 syncer::PassphraseRequiredReason reason, 1519 sync_pb::EncryptedData pending_keys) { 1520 if (!frontend_) 1521 return; 1522 1523 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1524 1525 // Update our cache of the cryptographer's pending keys. 1526 cached_pending_keys_ = pending_keys; 1527 1528 frontend_->OnPassphraseRequired(reason, pending_keys); 1529 } 1530 1531 void SyncBackendHost::NotifyPassphraseAccepted() { 1532 if (!frontend_) 1533 return; 1534 1535 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1536 1537 // Clear our cache of the cryptographer's pending keys. 1538 cached_pending_keys_.clear_blob(); 1539 frontend_->OnPassphraseAccepted(); 1540 } 1541 1542 void SyncBackendHost::NotifyUpdatedToken(const std::string& token) { 1543 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1544 TokenAvailableDetails details(GaiaConstants::kSyncService, token); 1545 1546 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); 1547 CHECK(token_service); 1548 token_service->AddAuthTokenManually(details.service(), details.token()); 1549 } 1550 1551 void SyncBackendHost::NotifyEncryptedTypesChanged( 1552 syncer::ModelTypeSet encrypted_types, 1553 bool encrypt_everything) { 1554 if (!frontend_) 1555 return; 1556 1557 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1558 frontend_->OnEncryptedTypesChanged( 1559 encrypted_types, encrypt_everything); 1560 } 1561 1562 void SyncBackendHost::NotifyEncryptionComplete() { 1563 if (!frontend_) 1564 return; 1565 1566 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1567 frontend_->OnEncryptionComplete(); 1568 } 1569 1570 void SyncBackendHost::HandlePassphraseTypeChangedOnFrontendLoop( 1571 syncer::PassphraseType type, 1572 base::Time explicit_passphrase_time) { 1573 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1574 DVLOG(1) << "Passphrase type changed to " 1575 << syncer::PassphraseTypeToString(type); 1576 cached_passphrase_type_ = type; 1577 cached_explicit_passphrase_time_ = explicit_passphrase_time; 1578 } 1579 1580 void SyncBackendHost::HandleStopSyncingPermanentlyOnFrontendLoop() { 1581 if (!frontend_) 1582 return; 1583 frontend_->OnStopSyncingPermanently(); 1584 } 1585 1586 void SyncBackendHost::HandleConnectionStatusChangeOnFrontendLoop( 1587 syncer::ConnectionStatus status) { 1588 if (!frontend_) 1589 return; 1590 1591 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); 1592 1593 DVLOG(1) << "Connection status changed: " 1594 << syncer::ConnectionStatusToString(status); 1595 frontend_->OnConnectionStatusChange(status); 1596 } 1597 1598 base::MessageLoop* SyncBackendHost::GetSyncLoopForTesting() { 1599 return registrar_->sync_thread()->message_loop(); 1600 } 1601 1602 #undef SDVLOG 1603 1604 #undef SLOG 1605 1606 } // namespace browser_sync 1607