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