1 // Copyright 2013 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_core.h" 6 7 #include "base/files/file_util.h" 8 #include "base/metrics/histogram.h" 9 #include "chrome/browser/sync/glue/invalidation_adapter.h" 10 #include "chrome/browser/sync/glue/local_device_info_provider_impl.h" 11 #include "chrome/browser/sync/glue/sync_backend_registrar.h" 12 #include "chrome/common/chrome_version_info.h" 13 #include "components/invalidation/invalidation_util.h" 14 #include "components/invalidation/object_id_invalidation_map.h" 15 #include "sync/internal_api/public/events/protocol_event.h" 16 #include "sync/internal_api/public/http_post_provider_factory.h" 17 #include "sync/internal_api/public/internal_components_factory.h" 18 #include "sync/internal_api/public/sessions/commit_counters.h" 19 #include "sync/internal_api/public/sessions/status_counters.h" 20 #include "sync/internal_api/public/sessions/sync_session_snapshot.h" 21 #include "sync/internal_api/public/sessions/update_counters.h" 22 #include "sync/internal_api/public/sync_context_proxy.h" 23 #include "sync/internal_api/public/sync_manager.h" 24 #include "sync/internal_api/public/sync_manager_factory.h" 25 #include "url/gurl.h" 26 27 // Helper macros to log with the syncer thread name; useful when there 28 // are multiple syncers involved. 29 30 #define SLOG(severity) LOG(severity) << name_ << ": " 31 32 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": " 33 34 static const int kSaveChangesIntervalSeconds = 10; 35 36 namespace syncer { 37 class InternalComponentsFactory; 38 } // namespace syncer 39 40 namespace { 41 42 // Enums for UMAs. 43 enum SyncBackendInitState { 44 SETUP_COMPLETED_FOUND_RESTORED_TYPES = 0, 45 SETUP_COMPLETED_NO_RESTORED_TYPES, 46 FIRST_SETUP_NO_RESTORED_TYPES, 47 FIRST_SETUP_RESTORED_TYPES, 48 SYNC_BACKEND_INIT_STATE_COUNT 49 }; 50 51 } // namespace 52 53 namespace browser_sync { 54 55 DoInitializeOptions::DoInitializeOptions( 56 base::MessageLoop* sync_loop, 57 SyncBackendRegistrar* registrar, 58 const syncer::ModelSafeRoutingInfo& routing_info, 59 const std::vector<scoped_refptr<syncer::ModelSafeWorker> >& workers, 60 const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity, 61 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler, 62 const GURL& service_url, 63 scoped_ptr<syncer::HttpPostProviderFactory> http_bridge_factory, 64 const syncer::SyncCredentials& credentials, 65 const std::string& invalidator_client_id, 66 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory, 67 bool delete_sync_data_folder, 68 const std::string& restored_key_for_bootstrapping, 69 const std::string& restored_keystore_key_for_bootstrapping, 70 scoped_ptr<syncer::InternalComponentsFactory> internal_components_factory, 71 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler, 72 syncer::ReportUnrecoverableErrorFunction 73 report_unrecoverable_error_function) 74 : sync_loop(sync_loop), 75 registrar(registrar), 76 routing_info(routing_info), 77 workers(workers), 78 extensions_activity(extensions_activity), 79 event_handler(event_handler), 80 service_url(service_url), 81 http_bridge_factory(http_bridge_factory.Pass()), 82 credentials(credentials), 83 invalidator_client_id(invalidator_client_id), 84 sync_manager_factory(sync_manager_factory.Pass()), 85 delete_sync_data_folder(delete_sync_data_folder), 86 restored_key_for_bootstrapping(restored_key_for_bootstrapping), 87 restored_keystore_key_for_bootstrapping( 88 restored_keystore_key_for_bootstrapping), 89 internal_components_factory(internal_components_factory.Pass()), 90 unrecoverable_error_handler(unrecoverable_error_handler.Pass()), 91 report_unrecoverable_error_function(report_unrecoverable_error_function) { 92 } 93 94 DoInitializeOptions::~DoInitializeOptions() {} 95 96 DoConfigureSyncerTypes::DoConfigureSyncerTypes() {} 97 98 DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {} 99 100 SyncBackendHostCore::SyncBackendHostCore( 101 const std::string& name, 102 const base::FilePath& sync_data_folder_path, 103 bool has_sync_setup_completed, 104 const base::WeakPtr<SyncBackendHostImpl>& backend) 105 : name_(name), 106 sync_data_folder_path_(sync_data_folder_path), 107 host_(backend), 108 sync_loop_(NULL), 109 registrar_(NULL), 110 has_sync_setup_completed_(has_sync_setup_completed), 111 forward_protocol_events_(false), 112 forward_type_info_(false), 113 weak_ptr_factory_(this) { 114 DCHECK(backend.get()); 115 } 116 117 SyncBackendHostCore::~SyncBackendHostCore() { 118 DCHECK(!sync_manager_.get()); 119 } 120 121 void SyncBackendHostCore::OnSyncCycleCompleted( 122 const syncer::sessions::SyncSessionSnapshot& snapshot) { 123 if (!sync_loop_) 124 return; 125 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 126 127 host_.Call( 128 FROM_HERE, 129 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop, 130 snapshot); 131 } 132 133 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) { 134 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 135 sync_manager_->RefreshTypes(types); 136 } 137 138 void SyncBackendHostCore::OnControlTypesDownloadRetry() { 139 host_.Call(FROM_HERE, 140 &SyncBackendHostImpl::HandleControlTypesDownloadRetry); 141 } 142 143 void SyncBackendHostCore::OnInitializationComplete( 144 const syncer::WeakHandle<syncer::JsBackend>& js_backend, 145 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& 146 debug_info_listener, 147 bool success, 148 const syncer::ModelTypeSet restored_types) { 149 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 150 151 if (!success) { 152 DoDestroySyncManager(syncer::STOP_SYNC); 153 host_.Call(FROM_HERE, 154 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop); 155 return; 156 } 157 158 // Register for encryption related changes now. We have to do this before 159 // the initializing downloading control types or initializing the encryption 160 // handler in order to receive notifications triggered during encryption 161 // startup. 162 sync_manager_->GetEncryptionHandler()->AddObserver(this); 163 164 // Sync manager initialization is complete, so we can schedule recurring 165 // SaveChanges. 166 sync_loop_->PostTask(FROM_HERE, 167 base::Bind(&SyncBackendHostCore::StartSavingChanges, 168 weak_ptr_factory_.GetWeakPtr())); 169 170 // Hang on to these for a while longer. We're not ready to hand them back to 171 // the UI thread yet. 172 js_backend_ = js_backend; 173 debug_info_listener_ = debug_info_listener; 174 175 // Track whether or not sync DB and preferences were in sync. 176 SyncBackendInitState backend_init_state; 177 if (has_sync_setup_completed_ && !restored_types.Empty()) { 178 backend_init_state = SETUP_COMPLETED_FOUND_RESTORED_TYPES; 179 } else if (has_sync_setup_completed_ && restored_types.Empty()) { 180 backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES; 181 } else if (!has_sync_setup_completed_ && restored_types.Empty()) { 182 backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES; 183 } else { // (!has_sync_setup_completed_ && !restored_types.Empty()) 184 backend_init_state = FIRST_SETUP_RESTORED_TYPES; 185 } 186 187 UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState", 188 backend_init_state, 189 SYNC_BACKEND_INIT_STATE_COUNT); 190 191 // Before proceeding any further, we need to download the control types and 192 // purge any partial data (ie. data downloaded for a type that was on its way 193 // to being initially synced, but didn't quite make it.). The following 194 // configure cycle will take care of this. It depends on the registrar state 195 // which we initialize below to ensure that we don't perform any downloads if 196 // all control types have already completed their initial sync. 197 registrar_->SetInitialTypes(restored_types); 198 199 syncer::ConfigureReason reason = 200 restored_types.Empty() ? 201 syncer::CONFIGURE_REASON_NEW_CLIENT : 202 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE; 203 204 syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes( 205 syncer::ControlTypes(), syncer::ModelTypeSet()); 206 syncer::ModelSafeRoutingInfo routing_info; 207 registrar_->GetModelSafeRoutingInfo(&routing_info); 208 SDVLOG(1) << "Control Types " 209 << syncer::ModelTypeSetToString(new_control_types) 210 << " added; calling ConfigureSyncer"; 211 212 syncer::ModelTypeSet types_to_purge = 213 syncer::Difference(syncer::ModelTypeSet::All(), 214 GetRoutingInfoTypes(routing_info)); 215 216 sync_manager_->ConfigureSyncer( 217 reason, 218 new_control_types, 219 types_to_purge, 220 syncer::ModelTypeSet(), 221 syncer::ModelTypeSet(), 222 routing_info, 223 base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes, 224 weak_ptr_factory_.GetWeakPtr()), 225 base::Bind(&SyncBackendHostCore::OnControlTypesDownloadRetry, 226 weak_ptr_factory_.GetWeakPtr())); 227 } 228 229 void SyncBackendHostCore::OnConnectionStatusChange( 230 syncer::ConnectionStatus status) { 231 if (!sync_loop_) 232 return; 233 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 234 host_.Call( 235 FROM_HERE, 236 &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop, status); 237 } 238 239 void SyncBackendHostCore::OnPassphraseRequired( 240 syncer::PassphraseRequiredReason reason, 241 const sync_pb::EncryptedData& pending_keys) { 242 if (!sync_loop_) 243 return; 244 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 245 host_.Call( 246 FROM_HERE, 247 &SyncBackendHostImpl::NotifyPassphraseRequired, reason, pending_keys); 248 } 249 250 void SyncBackendHostCore::OnPassphraseAccepted() { 251 if (!sync_loop_) 252 return; 253 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 254 host_.Call( 255 FROM_HERE, 256 &SyncBackendHostImpl::NotifyPassphraseAccepted); 257 } 258 259 void SyncBackendHostCore::OnBootstrapTokenUpdated( 260 const std::string& bootstrap_token, 261 syncer::BootstrapTokenType type) { 262 if (!sync_loop_) 263 return; 264 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 265 host_.Call(FROM_HERE, 266 &SyncBackendHostImpl::PersistEncryptionBootstrapToken, 267 bootstrap_token, 268 type); 269 } 270 271 void SyncBackendHostCore::OnEncryptedTypesChanged( 272 syncer::ModelTypeSet encrypted_types, 273 bool encrypt_everything) { 274 if (!sync_loop_) 275 return; 276 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 277 // NOTE: We're in a transaction. 278 host_.Call( 279 FROM_HERE, 280 &SyncBackendHostImpl::NotifyEncryptedTypesChanged, 281 encrypted_types, encrypt_everything); 282 } 283 284 void SyncBackendHostCore::OnEncryptionComplete() { 285 if (!sync_loop_) 286 return; 287 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 288 // NOTE: We're in a transaction. 289 host_.Call( 290 FROM_HERE, 291 &SyncBackendHostImpl::NotifyEncryptionComplete); 292 } 293 294 void SyncBackendHostCore::OnCryptographerStateChanged( 295 syncer::Cryptographer* cryptographer) { 296 // Do nothing. 297 } 298 299 void SyncBackendHostCore::OnPassphraseTypeChanged( 300 syncer::PassphraseType type, base::Time passphrase_time) { 301 host_.Call( 302 FROM_HERE, 303 &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop, 304 type, passphrase_time); 305 } 306 307 void SyncBackendHostCore::OnCommitCountersUpdated( 308 syncer::ModelType type, 309 const syncer::CommitCounters& counters) { 310 host_.Call( 311 FROM_HERE, 312 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop, 313 type, counters); 314 } 315 316 void SyncBackendHostCore::OnUpdateCountersUpdated( 317 syncer::ModelType type, 318 const syncer::UpdateCounters& counters) { 319 host_.Call( 320 FROM_HERE, 321 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop, 322 type, counters); 323 } 324 325 void SyncBackendHostCore::OnStatusCountersUpdated( 326 syncer::ModelType type, 327 const syncer::StatusCounters& counters) { 328 host_.Call( 329 FROM_HERE, 330 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop, 331 type, counters); 332 } 333 334 void SyncBackendHostCore::OnActionableError( 335 const syncer::SyncProtocolError& sync_error) { 336 if (!sync_loop_) 337 return; 338 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 339 host_.Call( 340 FROM_HERE, 341 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop, 342 sync_error); 343 } 344 345 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types) { 346 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 347 host_.Call( 348 FROM_HERE, 349 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop, 350 types); 351 } 352 353 void SyncBackendHostCore::OnProtocolEvent( 354 const syncer::ProtocolEvent& event) { 355 // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr. 356 if (forward_protocol_events_) { 357 scoped_ptr<syncer::ProtocolEvent> event_clone(event.Clone()); 358 host_.Call( 359 FROM_HERE, 360 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop, 361 event_clone.release()); 362 } 363 } 364 365 void SyncBackendHostCore::DoOnInvalidatorStateChange( 366 syncer::InvalidatorState state) { 367 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 368 sync_manager_->SetInvalidatorEnabled(state == syncer::INVALIDATIONS_ENABLED); 369 } 370 371 void SyncBackendHostCore::DoOnIncomingInvalidation( 372 const syncer::ObjectIdInvalidationMap& invalidation_map) { 373 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 374 375 syncer::ObjectIdSet ids = invalidation_map.GetObjectIds(); 376 for (syncer::ObjectIdSet::const_iterator ids_it = ids.begin(); 377 ids_it != ids.end(); 378 ++ids_it) { 379 syncer::ModelType type; 380 if (!NotificationTypeToRealModelType(ids_it->name(), &type)) { 381 DLOG(WARNING) << "Notification has invalid id: " 382 << syncer::ObjectIdToString(*ids_it); 383 } else { 384 syncer::SingleObjectInvalidationSet invalidation_set = 385 invalidation_map.ForObject(*ids_it); 386 for (syncer::SingleObjectInvalidationSet::const_iterator inv_it = 387 invalidation_set.begin(); 388 inv_it != invalidation_set.end(); 389 ++inv_it) { 390 scoped_ptr<syncer::InvalidationInterface> inv_adapter( 391 new InvalidationAdapter(*inv_it)); 392 sync_manager_->OnIncomingInvalidation(type, inv_adapter.Pass()); 393 } 394 } 395 } 396 } 397 398 void SyncBackendHostCore::DoInitialize( 399 scoped_ptr<DoInitializeOptions> options) { 400 DCHECK(!sync_loop_); 401 sync_loop_ = options->sync_loop; 402 DCHECK(sync_loop_); 403 404 // Finish initializing the HttpBridgeFactory. We do this here because 405 // building the user agent may block on some platforms. 406 chrome::VersionInfo version_info; 407 options->http_bridge_factory->Init( 408 LocalDeviceInfoProviderImpl::MakeUserAgentForSyncApi(version_info)); 409 410 // Blow away the partial or corrupt sync data folder before doing any more 411 // initialization, if necessary. 412 if (options->delete_sync_data_folder) { 413 DeleteSyncDataFolder(); 414 } 415 416 // Make sure that the directory exists before initializing the backend. 417 // If it already exists, this will do no harm. 418 if (!base::CreateDirectory(sync_data_folder_path_)) { 419 DLOG(FATAL) << "Sync Data directory creation failed."; 420 } 421 422 DCHECK(!registrar_); 423 registrar_ = options->registrar; 424 DCHECK(registrar_); 425 426 sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_); 427 sync_manager_->AddObserver(this); 428 429 syncer::SyncManager::InitArgs args; 430 args.database_location = sync_data_folder_path_; 431 args.event_handler = options->event_handler; 432 args.service_url = options->service_url; 433 args.post_factory = options->http_bridge_factory.Pass(); 434 args.workers = options->workers; 435 args.extensions_activity = options->extensions_activity.get(); 436 args.change_delegate = options->registrar; // as SyncManager::ChangeDelegate 437 args.credentials = options->credentials; 438 args.invalidator_client_id = options->invalidator_client_id; 439 args.restored_key_for_bootstrapping = options->restored_key_for_bootstrapping; 440 args.restored_keystore_key_for_bootstrapping = 441 options->restored_keystore_key_for_bootstrapping; 442 args.internal_components_factory = 443 options->internal_components_factory.Pass(); 444 args.encryptor = &encryptor_; 445 args.unrecoverable_error_handler = 446 options->unrecoverable_error_handler.Pass(); 447 args.report_unrecoverable_error_function = 448 options->report_unrecoverable_error_function; 449 args.cancelation_signal = &stop_syncing_signal_; 450 sync_manager_->Init(&args); 451 } 452 453 void SyncBackendHostCore::DoUpdateCredentials( 454 const syncer::SyncCredentials& credentials) { 455 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 456 // UpdateCredentials can be called during backend initialization, possibly 457 // when backend initialization has failed but hasn't notified the UI thread 458 // yet. In that case, the sync manager may have been destroyed on the sync 459 // thread before this task was executed, so we do nothing. 460 if (sync_manager_) { 461 sync_manager_->UpdateCredentials(credentials); 462 } 463 } 464 465 void SyncBackendHostCore::DoStartSyncing( 466 const syncer::ModelSafeRoutingInfo& routing_info) { 467 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 468 sync_manager_->StartSyncingNormally(routing_info); 469 } 470 471 void SyncBackendHostCore::DoSetEncryptionPassphrase( 472 const std::string& passphrase, 473 bool is_explicit) { 474 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 475 sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase( 476 passphrase, is_explicit); 477 } 478 479 void SyncBackendHostCore::DoInitialProcessControlTypes() { 480 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 481 482 DVLOG(1) << "Initilalizing Control Types"; 483 484 // Initialize encryption. 485 sync_manager_->GetEncryptionHandler()->Init(); 486 487 // Note: experiments are currently handled via SBH::AddExperimentalTypes, 488 // which is called at the end of every sync cycle. 489 // TODO(zea): eventually add an experiment handler and initialize it here. 490 491 if (!sync_manager_->GetUserShare()) { // NULL in some tests. 492 DVLOG(1) << "Skipping initialization of DeviceInfo"; 493 host_.Call( 494 FROM_HERE, 495 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop); 496 return; 497 } 498 499 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) { 500 LOG(ERROR) << "Failed to download control types"; 501 host_.Call( 502 FROM_HERE, 503 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop); 504 return; 505 } 506 507 host_.Call(FROM_HERE, 508 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop, 509 js_backend_, 510 debug_info_listener_, 511 sync_manager_->GetSyncContextProxy(), 512 sync_manager_->cache_guid()); 513 514 js_backend_.Reset(); 515 debug_info_listener_.Reset(); 516 } 517 518 void SyncBackendHostCore::DoSetDecryptionPassphrase( 519 const std::string& passphrase) { 520 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 521 sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase( 522 passphrase); 523 } 524 525 void SyncBackendHostCore::DoEnableEncryptEverything() { 526 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 527 sync_manager_->GetEncryptionHandler()->EnableEncryptEverything(); 528 } 529 530 void SyncBackendHostCore::ShutdownOnUIThread() { 531 // This will cut short any blocking network tasks, cut short any in-progress 532 // sync cycles, and prevent the creation of new blocking network tasks and new 533 // sync cycles. If there was an in-progress network request, it would have 534 // had a reference to the RequestContextGetter. This reference will be 535 // dropped by the time this function returns. 536 // 537 // It is safe to call this even if Sync's backend classes have not been 538 // initialized yet. Those classes will receive the message when the sync 539 // thread finally getes around to constructing them. 540 stop_syncing_signal_.Signal(); 541 542 // This will drop the HttpBridgeFactory's reference to the 543 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can 544 // no longer be used to create new HttpBridge instances. We can get away with 545 // this because the stop_syncing_signal_ has already been signalled, which 546 // guarantees that the ServerConnectionManager will no longer attempt to 547 // create new connections. 548 release_request_context_signal_.Signal(); 549 } 550 551 void SyncBackendHostCore::DoShutdown(syncer::ShutdownReason reason) { 552 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 553 554 DoDestroySyncManager(reason); 555 556 registrar_ = NULL; 557 558 if (reason == syncer::DISABLE_SYNC) 559 DeleteSyncDataFolder(); 560 561 host_.Reset(); 562 weak_ptr_factory_.InvalidateWeakPtrs(); 563 } 564 565 void SyncBackendHostCore::DoDestroySyncManager(syncer::ShutdownReason reason) { 566 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 567 if (sync_manager_) { 568 DisableDirectoryTypeDebugInfoForwarding(); 569 save_changes_timer_.reset(); 570 sync_manager_->RemoveObserver(this); 571 sync_manager_->ShutdownOnSyncThread(reason); 572 sync_manager_.reset(); 573 } 574 } 575 576 void SyncBackendHostCore::DoConfigureSyncer( 577 syncer::ConfigureReason reason, 578 const DoConfigureSyncerTypes& config_types, 579 const syncer::ModelSafeRoutingInfo routing_info, 580 const base::Callback<void(syncer::ModelTypeSet, 581 syncer::ModelTypeSet)>& ready_task, 582 const base::Closure& retry_callback) { 583 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 584 DCHECK(!ready_task.is_null()); 585 DCHECK(!retry_callback.is_null()); 586 base::Closure chained_ready_task( 587 base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes, 588 weak_ptr_factory_.GetWeakPtr(), 589 config_types.to_download, 590 ready_task)); 591 base::Closure chained_retry_task( 592 base::Bind(&SyncBackendHostCore::DoRetryConfiguration, 593 weak_ptr_factory_.GetWeakPtr(), 594 retry_callback)); 595 sync_manager_->ConfigureSyncer(reason, 596 config_types.to_download, 597 config_types.to_purge, 598 config_types.to_journal, 599 config_types.to_unapply, 600 routing_info, 601 chained_ready_task, 602 chained_retry_task); 603 } 604 605 void SyncBackendHostCore::DoFinishConfigureDataTypes( 606 syncer::ModelTypeSet types_to_config, 607 const base::Callback<void(syncer::ModelTypeSet, 608 syncer::ModelTypeSet)>& ready_task) { 609 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 610 611 // Update the enabled types for the bridge and sync manager. 612 syncer::ModelSafeRoutingInfo routing_info; 613 registrar_->GetModelSafeRoutingInfo(&routing_info); 614 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info); 615 enabled_types.RemoveAll(syncer::ProxyTypes()); 616 617 const syncer::ModelTypeSet failed_configuration_types = 618 Difference(types_to_config, sync_manager_->InitialSyncEndedTypes()); 619 const syncer::ModelTypeSet succeeded_configuration_types = 620 Difference(types_to_config, failed_configuration_types); 621 host_.Call(FROM_HERE, 622 &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop, 623 enabled_types, 624 succeeded_configuration_types, 625 failed_configuration_types, 626 ready_task); 627 } 628 629 void SyncBackendHostCore::DoRetryConfiguration( 630 const base::Closure& retry_callback) { 631 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 632 host_.Call(FROM_HERE, 633 &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop, 634 retry_callback); 635 } 636 637 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() { 638 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 639 forward_protocol_events_ = true; 640 641 if (sync_manager_) { 642 // Grab our own copy of the buffered events. 643 // The buffer is not modified by this operation. 644 std::vector<syncer::ProtocolEvent*> buffered_events; 645 sync_manager_->GetBufferedProtocolEvents().release(&buffered_events); 646 647 // Send them all over the fence to the host. 648 for (std::vector<syncer::ProtocolEvent*>::iterator it = 649 buffered_events.begin(); it != buffered_events.end(); ++it) { 650 // TODO(rlarocque): Make it explicit that host_ takes ownership. 651 host_.Call( 652 FROM_HERE, 653 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop, 654 *it); 655 } 656 } 657 } 658 659 void SyncBackendHostCore::DisableProtocolEventForwarding() { 660 forward_protocol_events_ = false; 661 } 662 663 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() { 664 DCHECK(sync_manager_); 665 666 forward_type_info_ = true; 667 668 if (!sync_manager_->HasDirectoryTypeDebugInfoObserver(this)) 669 sync_manager_->RegisterDirectoryTypeDebugInfoObserver(this); 670 sync_manager_->RequestEmitDebugInfo(); 671 } 672 673 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() { 674 DCHECK(sync_manager_); 675 676 if (!forward_type_info_) 677 return; 678 679 forward_type_info_ = false; 680 681 if (sync_manager_->HasDirectoryTypeDebugInfoObserver(this)) 682 sync_manager_->UnregisterDirectoryTypeDebugInfoObserver(this); 683 } 684 685 void SyncBackendHostCore::DeleteSyncDataFolder() { 686 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 687 if (base::DirectoryExists(sync_data_folder_path_)) { 688 if (!base::DeleteFile(sync_data_folder_path_, true)) 689 SLOG(DFATAL) << "Could not delete the Sync Data folder."; 690 } 691 } 692 693 void SyncBackendHostCore::GetAllNodesForTypes( 694 syncer::ModelTypeSet types, 695 scoped_refptr<base::SequencedTaskRunner> task_runner, 696 base::Callback<void(const std::vector<syncer::ModelType>& type, 697 ScopedVector<base::ListValue>)> callback) { 698 std::vector<syncer::ModelType> types_vector; 699 ScopedVector<base::ListValue> node_lists; 700 701 syncer::ModelSafeRoutingInfo routes; 702 registrar_->GetModelSafeRoutingInfo(&routes); 703 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routes); 704 705 for (syncer::ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { 706 types_vector.push_back(it.Get()); 707 if (!enabled_types.Has(it.Get())) { 708 node_lists.push_back(new base::ListValue()); 709 } else { 710 node_lists.push_back( 711 sync_manager_->GetAllNodesForType(it.Get()).release()); 712 } 713 } 714 715 task_runner->PostTask( 716 FROM_HERE, 717 base::Bind(callback, types_vector, base::Passed(&node_lists))); 718 } 719 720 void SyncBackendHostCore::StartSavingChanges() { 721 // We may already be shut down. 722 if (!sync_loop_) 723 return; 724 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 725 DCHECK(!save_changes_timer_.get()); 726 save_changes_timer_.reset(new base::RepeatingTimer<SyncBackendHostCore>()); 727 save_changes_timer_->Start(FROM_HERE, 728 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds), 729 this, &SyncBackendHostCore::SaveChanges); 730 } 731 732 void SyncBackendHostCore::SaveChanges() { 733 DCHECK_EQ(base::MessageLoop::current(), sync_loop_); 734 sync_manager_->SaveChanges(); 735 } 736 737 } // namespace browser_sync 738