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