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