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