| 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 "components/sync_driver/glue/sync_backend_host_impl.h" | |
| 6 | |
| 7 #include <map> | |
| 8 #include <utility> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/command_line.h" | |
| 12 #include "base/feature_list.h" | |
| 13 #include "base/location.h" | |
| 14 #include "base/logging.h" | |
| 15 #include "base/threading/thread_task_runner_handle.h" | |
| 16 #include "components/invalidation/public/invalidation_service.h" | |
| 17 #include "components/invalidation/public/object_id_invalidation_map.h" | |
| 18 #include "components/signin/core/browser/signin_client.h" | |
| 19 #include "components/sync/base/experiments.h" | |
| 20 #include "components/sync/base/sync_string_conversions.h" | |
| 21 #include "components/sync/core/activation_context.h" | |
| 22 #include "components/sync/core/base_transaction.h" | |
| 23 #include "components/sync/core/http_bridge.h" | |
| 24 #include "components/sync/core/internal_components_factory.h" | |
| 25 #include "components/sync/core/internal_components_factory_impl.h" | |
| 26 #include "components/sync/core/sync_manager.h" | |
| 27 #include "components/sync/core/sync_manager_factory.h" | |
| 28 #include "components/sync/engine/events/protocol_event.h" | |
| 29 #include "components/sync_driver/glue/sync_backend_host_core.h" | |
| 30 #include "components/sync_driver/glue/sync_backend_registrar.h" | |
| 31 #include "components/sync_driver/invalidation_helper.h" | |
| 32 #include "components/sync_driver/sync_client.h" | |
| 33 #include "components/sync_driver/sync_driver_switches.h" | |
| 34 #include "components/sync_driver/sync_frontend.h" | |
| 35 #include "components/sync_driver/sync_prefs.h" | |
| 36 | |
| 37 // Helper macros to log with the syncer thread name; useful when there | |
| 38 // are multiple syncers involved. | |
| 39 | |
| 40 #define SLOG(severity) LOG(severity) << name_ << ": " | |
| 41 | |
| 42 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": " | |
| 43 | |
| 44 using syncer::InternalComponentsFactory; | |
| 45 | |
| 46 namespace browser_sync { | |
| 47 | |
| 48 SyncBackendHostImpl::SyncBackendHostImpl( | |
| 49 const std::string& name, | |
| 50 sync_driver::SyncClient* sync_client, | |
| 51 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, | |
| 52 invalidation::InvalidationService* invalidator, | |
| 53 const base::WeakPtr<sync_driver::SyncPrefs>& sync_prefs, | |
| 54 const base::FilePath& sync_folder) | |
| 55 : frontend_task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
| 56 sync_client_(sync_client), | |
| 57 ui_thread_(ui_thread), | |
| 58 name_(name), | |
| 59 initialized_(false), | |
| 60 sync_prefs_(sync_prefs), | |
| 61 frontend_(NULL), | |
| 62 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE), | |
| 63 invalidator_(invalidator), | |
| 64 invalidation_handler_registered_(false), | |
| 65 weak_ptr_factory_(this) { | |
| 66 core_ = new SyncBackendHostCore(name_, sync_folder, | |
| 67 sync_prefs_->IsFirstSetupComplete(), | |
| 68 weak_ptr_factory_.GetWeakPtr()); | |
| 69 } | |
| 70 | |
| 71 SyncBackendHostImpl::~SyncBackendHostImpl() { | |
| 72 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor."; | |
| 73 DCHECK(!registrar_.get()); | |
| 74 } | |
| 75 | |
| 76 void SyncBackendHostImpl::Initialize( | |
| 77 sync_driver::SyncFrontend* frontend, | |
| 78 std::unique_ptr<base::Thread> sync_thread, | |
| 79 const scoped_refptr<base::SingleThreadTaskRunner>& db_thread, | |
| 80 const scoped_refptr<base::SingleThreadTaskRunner>& file_thread, | |
| 81 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler, | |
| 82 const GURL& sync_service_url, | |
| 83 const std::string& sync_user_agent, | |
| 84 const syncer::SyncCredentials& credentials, | |
| 85 bool delete_sync_data_folder, | |
| 86 std::unique_ptr<syncer::SyncManagerFactory> sync_manager_factory, | |
| 87 const syncer::WeakHandle<syncer::UnrecoverableErrorHandler>& | |
| 88 unrecoverable_error_handler, | |
| 89 const base::Closure& report_unrecoverable_error_function, | |
| 90 const HttpPostProviderFactoryGetter& http_post_provider_factory_getter, | |
| 91 std::unique_ptr<syncer::SyncEncryptionHandler::NigoriState> | |
| 92 saved_nigori_state) { | |
| 93 registrar_.reset(new browser_sync::SyncBackendRegistrar( | |
| 94 name_, sync_client_, std::move(sync_thread), ui_thread_, db_thread, | |
| 95 file_thread)); | |
| 96 CHECK(registrar_->sync_thread()); | |
| 97 | |
| 98 frontend_ = frontend; | |
| 99 DCHECK(frontend); | |
| 100 | |
| 101 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers; | |
| 102 registrar_->GetWorkers(&workers); | |
| 103 | |
| 104 InternalComponentsFactory::Switches factory_switches = { | |
| 105 InternalComponentsFactory::ENCRYPTION_KEYSTORE, | |
| 106 InternalComponentsFactory::BACKOFF_NORMAL | |
| 107 }; | |
| 108 | |
| 109 base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); | |
| 110 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) { | |
| 111 factory_switches.backoff_override = | |
| 112 InternalComponentsFactory::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE; | |
| 113 } | |
| 114 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) { | |
| 115 factory_switches.pre_commit_updates_policy = | |
| 116 InternalComponentsFactory::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE; | |
| 117 } | |
| 118 | |
| 119 std::map<syncer::ModelType, int64_t> invalidation_versions; | |
| 120 sync_prefs_->GetInvalidationVersions(&invalidation_versions); | |
| 121 | |
| 122 std::unique_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions( | |
| 123 registrar_->sync_thread()->message_loop(), registrar_.get(), workers, | |
| 124 sync_client_->GetExtensionsActivity(), event_handler, sync_service_url, | |
| 125 sync_user_agent, http_post_provider_factory_getter.Run( | |
| 126 core_->GetRequestContextCancelationSignal()), | |
| 127 credentials, invalidator_ ? invalidator_->GetInvalidatorClientId() : "", | |
| 128 std::move(sync_manager_factory), delete_sync_data_folder, | |
| 129 sync_prefs_->GetEncryptionBootstrapToken(), | |
| 130 sync_prefs_->GetKeystoreEncryptionBootstrapToken(), | |
| 131 std::unique_ptr<InternalComponentsFactory>( | |
| 132 new syncer::InternalComponentsFactoryImpl(factory_switches)), | |
| 133 unrecoverable_error_handler, report_unrecoverable_error_function, | |
| 134 std::move(saved_nigori_state), invalidation_versions)); | |
| 135 InitCore(std::move(init_opts)); | |
| 136 } | |
| 137 | |
| 138 void SyncBackendHostImpl::TriggerRefresh(const syncer::ModelTypeSet& types) { | |
| 139 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
| 140 registrar_->sync_thread()->task_runner()->PostTask( | |
| 141 FROM_HERE, | |
| 142 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types)); | |
| 143 } | |
| 144 | |
| 145 void SyncBackendHostImpl::UpdateCredentials( | |
| 146 const syncer::SyncCredentials& credentials) { | |
| 147 DCHECK(registrar_->sync_thread()->IsRunning()); | |
| 148 registrar_->sync_thread()->task_runner()->PostTask( | |
| 149 FROM_HERE, base::Bind(&SyncBackendHostCore::DoUpdateCredentials, | |
| 150 core_.get(), credentials)); | |
| 151 } | |
| 152 | |
| 153 void SyncBackendHostImpl::StartSyncingWithServer() { | |
| 154 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called."; | |
| 155 | |
| 156 syncer::ModelSafeRoutingInfo routing_info; | |
| 157 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
| 158 | |
| 159 registrar_->sync_thread()->task_runner()->PostTask( | |
| 160 FROM_HERE, base::Bind(&SyncBackendHostCore::DoStartSyncing, core_.get(), | |
| 161 routing_info, sync_prefs_->GetLastPollTime())); | |
| 162 } | |
| 163 | |
| 164 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase, | |
| 165 bool is_explicit) { | |
| 166 DCHECK(registrar_->sync_thread()->IsRunning()); | |
| 167 if (!IsNigoriEnabled()) { | |
| 168 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori" | |
| 169 " is disabled."; | |
| 170 return; | |
| 171 } | |
| 172 | |
| 173 // We should never be called with an empty passphrase. | |
| 174 DCHECK(!passphrase.empty()); | |
| 175 | |
| 176 // This should only be called by the frontend. | |
| 177 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 178 | |
| 179 // SetEncryptionPassphrase should never be called if we are currently | |
| 180 // encrypted with an explicit passphrase. | |
| 181 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE || | |
| 182 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE); | |
| 183 | |
| 184 // Post an encryption task on the syncer thread. | |
| 185 registrar_->sync_thread()->task_runner()->PostTask( | |
| 186 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase, | |
| 187 core_.get(), passphrase, is_explicit)); | |
| 188 } | |
| 189 | |
| 190 bool SyncBackendHostImpl::SetDecryptionPassphrase( | |
| 191 const std::string& passphrase) { | |
| 192 if (!IsNigoriEnabled()) { | |
| 193 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori" | |
| 194 " is disabled."; | |
| 195 return false; | |
| 196 } | |
| 197 | |
| 198 // We should never be called with an empty passphrase. | |
| 199 DCHECK(!passphrase.empty()); | |
| 200 | |
| 201 // This should only be called by the frontend. | |
| 202 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 203 | |
| 204 // This should only be called when we have cached pending keys. | |
| 205 DCHECK(cached_pending_keys_.has_blob()); | |
| 206 | |
| 207 // Check the passphrase that was provided against our local cache of the | |
| 208 // cryptographer's pending keys. If this was unsuccessful, the UI layer can | |
| 209 // immediately call OnPassphraseRequired without showing the user a spinner. | |
| 210 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase)) | |
| 211 return false; | |
| 212 | |
| 213 // Post a decryption task on the syncer thread. | |
| 214 registrar_->sync_thread()->task_runner()->PostTask( | |
| 215 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase, | |
| 216 core_.get(), passphrase)); | |
| 217 | |
| 218 // Since we were able to decrypt the cached pending keys with the passphrase | |
| 219 // provided, we immediately alert the UI layer that the passphrase was | |
| 220 // accepted. This will avoid the situation where a user enters a passphrase, | |
| 221 // clicks OK, immediately reopens the advanced settings dialog, and gets an | |
| 222 // unnecessary prompt for a passphrase. | |
| 223 // Note: It is not guaranteed that the passphrase will be accepted by the | |
| 224 // syncer thread, since we could receive a new nigori node while the task is | |
| 225 // pending. This scenario is a valid race, and SetDecryptionPassphrase can | |
| 226 // trigger a new OnPassphraseRequired if it needs to. | |
| 227 NotifyPassphraseAccepted(); | |
| 228 return true; | |
| 229 } | |
| 230 | |
| 231 void SyncBackendHostImpl::StopSyncingForShutdown() { | |
| 232 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 233 | |
| 234 // Immediately stop sending messages to the frontend. | |
| 235 frontend_ = NULL; | |
| 236 | |
| 237 DCHECK(registrar_->sync_thread()->IsRunning()); | |
| 238 | |
| 239 registrar_->RequestWorkerStopOnUIThread(); | |
| 240 | |
| 241 core_->ShutdownOnUIThread(); | |
| 242 } | |
| 243 | |
| 244 std::unique_ptr<base::Thread> SyncBackendHostImpl::Shutdown( | |
| 245 syncer::ShutdownReason reason) { | |
| 246 // StopSyncingForShutdown() (which nulls out |frontend_|) should be | |
| 247 // called first. | |
| 248 DCHECK(!frontend_); | |
| 249 DCHECK(registrar_->sync_thread()->IsRunning()); | |
| 250 | |
| 251 bool sync_thread_claimed = (reason != syncer::BROWSER_SHUTDOWN); | |
| 252 | |
| 253 if (invalidation_handler_registered_) { | |
| 254 if (reason == syncer::DISABLE_SYNC) { | |
| 255 UnregisterInvalidationIds(); | |
| 256 } | |
| 257 invalidator_->UnregisterInvalidationHandler(this); | |
| 258 invalidator_ = NULL; | |
| 259 } | |
| 260 invalidation_handler_registered_ = false; | |
| 261 | |
| 262 model_type_connector_.reset(); | |
| 263 | |
| 264 // Shut down and destroy sync manager. | |
| 265 registrar_->sync_thread()->task_runner()->PostTask( | |
| 266 FROM_HERE, | |
| 267 base::Bind(&SyncBackendHostCore::DoShutdown, core_.get(), reason)); | |
| 268 core_ = NULL; | |
| 269 | |
| 270 // Worker cleanup. | |
| 271 SyncBackendRegistrar* detached_registrar = registrar_.release(); | |
| 272 detached_registrar->sync_thread()->task_runner()->PostTask( | |
| 273 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown, | |
| 274 base::Unretained(detached_registrar))); | |
| 275 | |
| 276 if (sync_thread_claimed) | |
| 277 return detached_registrar->ReleaseSyncThread(); | |
| 278 else | |
| 279 return std::unique_ptr<base::Thread>(); | |
| 280 } | |
| 281 | |
| 282 void SyncBackendHostImpl::UnregisterInvalidationIds() { | |
| 283 if (invalidation_handler_registered_) { | |
| 284 CHECK(invalidator_->UpdateRegisteredInvalidationIds(this, | |
| 285 syncer::ObjectIdSet())); | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 syncer::ModelTypeSet SyncBackendHostImpl::ConfigureDataTypes( | |
| 290 syncer::ConfigureReason reason, | |
| 291 const DataTypeConfigStateMap& config_state_map, | |
| 292 const base::Callback<void(syncer::ModelTypeSet, syncer::ModelTypeSet)>& | |
| 293 ready_task, | |
| 294 const base::Callback<void()>& retry_callback) { | |
| 295 // Only one configure is allowed at a time. This is guaranteed by our | |
| 296 // callers. The SyncBackendHostImpl requests one configure as the backend is | |
| 297 // initializing and waits for it to complete. After initialization, all | |
| 298 // configurations will pass through the DataTypeManager, which is careful to | |
| 299 // never send a new configure request until the current request succeeds. | |
| 300 | |
| 301 // The SyncBackendRegistrar's routing info will be updated by adding the | |
| 302 // types_to_add to the list then removing types_to_remove. Any types which | |
| 303 // are not in either of those sets will remain untouched. | |
| 304 // | |
| 305 // Types which were not in the list previously are not fully downloaded, so we | |
| 306 // must ask the syncer to download them. Any newly supported datatypes will | |
| 307 // not have been in that routing info list, so they will be among the types | |
| 308 // downloaded if they are enabled. | |
| 309 // | |
| 310 // The SyncBackendRegistrar's state was initially derived from the types | |
| 311 // detected to have been downloaded in the database. Afterwards it is | |
| 312 // modified only by this function. We expect it to remain in sync with the | |
| 313 // backend because configuration requests are never aborted; they are retried | |
| 314 // until they succeed or the backend is shut down. | |
| 315 | |
| 316 syncer::ModelTypeSet disabled_types = | |
| 317 GetDataTypesInState(DISABLED, config_state_map); | |
| 318 syncer::ModelTypeSet fatal_types = | |
| 319 GetDataTypesInState(FATAL, config_state_map); | |
| 320 syncer::ModelTypeSet crypto_types = | |
| 321 GetDataTypesInState(CRYPTO, config_state_map); | |
| 322 syncer::ModelTypeSet unready_types = | |
| 323 GetDataTypesInState(UNREADY, config_state_map); | |
| 324 | |
| 325 disabled_types.PutAll(fatal_types); | |
| 326 disabled_types.PutAll(crypto_types); | |
| 327 disabled_types.PutAll(unready_types); | |
| 328 | |
| 329 syncer::ModelTypeSet active_types = | |
| 330 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map); | |
| 331 syncer::ModelTypeSet clean_first_types = | |
| 332 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map); | |
| 333 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes( | |
| 334 syncer::Union(active_types, clean_first_types), | |
| 335 disabled_types); | |
| 336 types_to_download.PutAll(clean_first_types); | |
| 337 types_to_download.RemoveAll(syncer::ProxyTypes()); | |
| 338 if (!types_to_download.Empty()) | |
| 339 types_to_download.Put(syncer::NIGORI); | |
| 340 | |
| 341 // TODO(sync): crbug.com/137550. | |
| 342 // It's dangerous to configure types that have progress markers. Types with | |
| 343 // progress markers can trigger a MIGRATION_DONE response. We are not | |
| 344 // prepared to handle a migration during a configure, so we must ensure that | |
| 345 // all our types_to_download actually contain no data before we sync them. | |
| 346 // | |
| 347 // One common way to end up in this situation used to be types which | |
| 348 // downloaded some or all of their data but have not applied it yet. We avoid | |
| 349 // problems with those types by purging the data of any such partially synced | |
| 350 // types soon after we load the directory. | |
| 351 // | |
| 352 // Another possible scenario is that we have newly supported or newly enabled | |
| 353 // data types being downloaded here but the nigori type, which is always | |
| 354 // included in any GetUpdates request, requires migration. The server has | |
| 355 // code to detect this scenario based on the configure reason, the fact that | |
| 356 // the nigori type is the only requested type which requires migration, and | |
| 357 // that the requested types list includes at least one non-nigori type. It | |
| 358 // will not send a MIGRATION_DONE response in that case. We still need to be | |
| 359 // careful to not send progress markers for non-nigori types, though. If a | |
| 360 // non-nigori type in the request requires migration, a MIGRATION_DONE | |
| 361 // response will be sent. | |
| 362 | |
| 363 syncer::ModelSafeRoutingInfo routing_info; | |
| 364 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
| 365 | |
| 366 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes(); | |
| 367 syncer::ModelTypeSet types_to_purge = | |
| 368 syncer::Difference(syncer::ModelTypeSet::All(), current_types); | |
| 369 syncer::ModelTypeSet inactive_types = | |
| 370 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map); | |
| 371 types_to_purge.RemoveAll(inactive_types); | |
| 372 types_to_purge.RemoveAll(unready_types); | |
| 373 | |
| 374 // If a type has already been disabled and unapplied or journaled, it will | |
| 375 // not be part of the |types_to_purge| set, and therefore does not need | |
| 376 // to be acted on again. | |
| 377 fatal_types.RetainAll(types_to_purge); | |
| 378 syncer::ModelTypeSet unapply_types = | |
| 379 syncer::Union(crypto_types, clean_first_types); | |
| 380 unapply_types.RetainAll(types_to_purge); | |
| 381 | |
| 382 DCHECK(syncer::Intersection(current_types, fatal_types).Empty()); | |
| 383 DCHECK(syncer::Intersection(current_types, crypto_types).Empty()); | |
| 384 DCHECK(current_types.HasAll(types_to_download)); | |
| 385 | |
| 386 SDVLOG(1) << "Types " | |
| 387 << syncer::ModelTypeSetToString(types_to_download) | |
| 388 << " added; calling DoConfigureSyncer"; | |
| 389 // Divide up the types into their corresponding actions (each is mutually | |
| 390 // exclusive): | |
| 391 // - Types which have just been added to the routing info (types_to_download): | |
| 392 // are downloaded. | |
| 393 // - Types which have encountered a fatal error (fatal_types) are deleted | |
| 394 // from the directory and journaled in the delete journal. | |
| 395 // - Types which have encountered a cryptographer error (crypto_types) are | |
| 396 // unapplied (local state is purged but sync state is not). | |
| 397 // - All other types not in the routing info (types just disabled) are deleted | |
| 398 // from the directory. | |
| 399 // - Everything else (enabled types and already disabled types) is not | |
| 400 // touched. | |
| 401 RequestConfigureSyncer(reason, | |
| 402 types_to_download, | |
| 403 types_to_purge, | |
| 404 fatal_types, | |
| 405 unapply_types, | |
| 406 inactive_types, | |
| 407 routing_info, | |
| 408 ready_task, | |
| 409 retry_callback); | |
| 410 | |
| 411 DCHECK(syncer::Intersection(active_types, types_to_purge).Empty()); | |
| 412 DCHECK(syncer::Intersection(active_types, fatal_types).Empty()); | |
| 413 DCHECK(syncer::Intersection(active_types, unapply_types).Empty()); | |
| 414 DCHECK(syncer::Intersection(active_types, inactive_types).Empty()); | |
| 415 return syncer::Difference(active_types, types_to_download); | |
| 416 } | |
| 417 | |
| 418 void SyncBackendHostImpl::EnableEncryptEverything() { | |
| 419 registrar_->sync_thread()->task_runner()->PostTask( | |
| 420 FROM_HERE, | |
| 421 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything, core_.get())); | |
| 422 } | |
| 423 | |
| 424 void SyncBackendHostImpl::ActivateDirectoryDataType( | |
| 425 syncer::ModelType type, | |
| 426 syncer::ModelSafeGroup group, | |
| 427 sync_driver::ChangeProcessor* change_processor) { | |
| 428 registrar_->ActivateDataType(type, group, change_processor, GetUserShare()); | |
| 429 } | |
| 430 | |
| 431 void SyncBackendHostImpl::DeactivateDirectoryDataType(syncer::ModelType type) { | |
| 432 registrar_->DeactivateDataType(type); | |
| 433 } | |
| 434 | |
| 435 void SyncBackendHostImpl::ActivateNonBlockingDataType( | |
| 436 syncer::ModelType type, | |
| 437 std::unique_ptr<syncer_v2::ActivationContext> activation_context) { | |
| 438 registrar_->RegisterNonBlockingType(type); | |
| 439 if (activation_context->data_type_state.initial_sync_done()) | |
| 440 registrar_->AddRestoredNonBlockingType(type); | |
| 441 model_type_connector_->ConnectType(type, std::move(activation_context)); | |
| 442 } | |
| 443 | |
| 444 void SyncBackendHostImpl::DeactivateNonBlockingDataType( | |
| 445 syncer::ModelType type) { | |
| 446 model_type_connector_->DisconnectType(type); | |
| 447 } | |
| 448 | |
| 449 syncer::UserShare* SyncBackendHostImpl::GetUserShare() const { | |
| 450 return core_->sync_manager()->GetUserShare(); | |
| 451 } | |
| 452 | |
| 453 SyncBackendHostImpl::Status SyncBackendHostImpl::GetDetailedStatus() { | |
| 454 DCHECK(initialized()); | |
| 455 return core_->sync_manager()->GetDetailedStatus(); | |
| 456 } | |
| 457 | |
| 458 syncer::sessions::SyncSessionSnapshot | |
| 459 SyncBackendHostImpl::GetLastSessionSnapshot() const { | |
| 460 return last_snapshot_; | |
| 461 } | |
| 462 | |
| 463 bool SyncBackendHostImpl::HasUnsyncedItems() const { | |
| 464 DCHECK(initialized()); | |
| 465 return core_->sync_manager()->HasUnsyncedItems(); | |
| 466 } | |
| 467 | |
| 468 bool SyncBackendHostImpl::IsNigoriEnabled() const { | |
| 469 return registrar_.get() && registrar_->IsNigoriEnabled(); | |
| 470 } | |
| 471 | |
| 472 syncer::PassphraseType SyncBackendHostImpl::GetPassphraseType() const { | |
| 473 return cached_passphrase_type_; | |
| 474 } | |
| 475 | |
| 476 base::Time SyncBackendHostImpl::GetExplicitPassphraseTime() const { | |
| 477 return cached_explicit_passphrase_time_; | |
| 478 } | |
| 479 | |
| 480 bool SyncBackendHostImpl::IsCryptographerReady( | |
| 481 const syncer::BaseTransaction* trans) const { | |
| 482 return initialized() && trans->GetCryptographer() && | |
| 483 trans->GetCryptographer()->is_ready(); | |
| 484 } | |
| 485 | |
| 486 void SyncBackendHostImpl::GetModelSafeRoutingInfo( | |
| 487 syncer::ModelSafeRoutingInfo* out) const { | |
| 488 if (initialized()) { | |
| 489 CHECK(registrar_.get()); | |
| 490 registrar_->GetModelSafeRoutingInfo(out); | |
| 491 } else { | |
| 492 NOTREACHED(); | |
| 493 } | |
| 494 } | |
| 495 | |
| 496 void SyncBackendHostImpl::FlushDirectory() const { | |
| 497 DCHECK(initialized()); | |
| 498 registrar_->sync_thread()->task_runner()->PostTask( | |
| 499 FROM_HERE, base::Bind(&SyncBackendHostCore::SaveChanges, core_)); | |
| 500 } | |
| 501 | |
| 502 void SyncBackendHostImpl::RequestBufferedProtocolEventsAndEnableForwarding() { | |
| 503 registrar_->sync_thread()->task_runner()->PostTask( | |
| 504 FROM_HERE, | |
| 505 base::Bind( | |
| 506 &SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding, | |
| 507 core_)); | |
| 508 } | |
| 509 | |
| 510 void SyncBackendHostImpl::DisableProtocolEventForwarding() { | |
| 511 registrar_->sync_thread()->task_runner()->PostTask( | |
| 512 FROM_HERE, | |
| 513 base::Bind(&SyncBackendHostCore::DisableProtocolEventForwarding, core_)); | |
| 514 } | |
| 515 | |
| 516 void SyncBackendHostImpl::EnableDirectoryTypeDebugInfoForwarding() { | |
| 517 DCHECK(initialized()); | |
| 518 registrar_->sync_thread()->task_runner()->PostTask( | |
| 519 FROM_HERE, | |
| 520 base::Bind(&SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding, | |
| 521 core_)); | |
| 522 } | |
| 523 | |
| 524 void SyncBackendHostImpl::DisableDirectoryTypeDebugInfoForwarding() { | |
| 525 DCHECK(initialized()); | |
| 526 registrar_->sync_thread()->task_runner()->PostTask( | |
| 527 FROM_HERE, | |
| 528 base::Bind(&SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding, | |
| 529 core_)); | |
| 530 } | |
| 531 | |
| 532 void SyncBackendHostImpl::GetAllNodesForTypes( | |
| 533 syncer::ModelTypeSet types, | |
| 534 base::Callback<void(const std::vector<syncer::ModelType>&, | |
| 535 ScopedVector<base::ListValue>)> callback) { | |
| 536 DCHECK(initialized()); | |
| 537 registrar_->sync_thread()->task_runner()->PostTask( | |
| 538 FROM_HERE, base::Bind(&SyncBackendHostCore::GetAllNodesForTypes, core_, | |
| 539 types, frontend_task_runner_, callback)); | |
| 540 } | |
| 541 | |
| 542 void SyncBackendHostImpl::InitCore( | |
| 543 std::unique_ptr<DoInitializeOptions> options) { | |
| 544 registrar_->sync_thread()->task_runner()->PostTask( | |
| 545 FROM_HERE, base::Bind(&SyncBackendHostCore::DoInitialize, core_.get(), | |
| 546 base::Passed(&options))); | |
| 547 } | |
| 548 | |
| 549 void SyncBackendHostImpl::RequestConfigureSyncer( | |
| 550 syncer::ConfigureReason reason, | |
| 551 syncer::ModelTypeSet to_download, | |
| 552 syncer::ModelTypeSet to_purge, | |
| 553 syncer::ModelTypeSet to_journal, | |
| 554 syncer::ModelTypeSet to_unapply, | |
| 555 syncer::ModelTypeSet to_ignore, | |
| 556 const syncer::ModelSafeRoutingInfo& routing_info, | |
| 557 const base::Callback<void(syncer::ModelTypeSet, | |
| 558 syncer::ModelTypeSet)>& ready_task, | |
| 559 const base::Closure& retry_callback) { | |
| 560 DoConfigureSyncerTypes config_types; | |
| 561 config_types.to_download = to_download; | |
| 562 config_types.to_purge = to_purge; | |
| 563 config_types.to_journal = to_journal; | |
| 564 config_types.to_unapply = to_unapply; | |
| 565 registrar_->sync_thread()->task_runner()->PostTask( | |
| 566 FROM_HERE, | |
| 567 base::Bind(&SyncBackendHostCore::DoConfigureSyncer, core_.get(), reason, | |
| 568 config_types, routing_info, ready_task, retry_callback)); | |
| 569 } | |
| 570 | |
| 571 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop( | |
| 572 const syncer::ModelTypeSet enabled_types, | |
| 573 const syncer::ModelTypeSet succeeded_configuration_types, | |
| 574 const syncer::ModelTypeSet failed_configuration_types, | |
| 575 const base::Callback<void(syncer::ModelTypeSet, | |
| 576 syncer::ModelTypeSet)>& ready_task) { | |
| 577 if (!frontend_) | |
| 578 return; | |
| 579 | |
| 580 if (invalidator_) { | |
| 581 CHECK(invalidator_->UpdateRegisteredInvalidationIds( | |
| 582 this, ModelTypeSetToObjectIdSet(enabled_types))); | |
| 583 } | |
| 584 | |
| 585 if (!ready_task.is_null()) | |
| 586 ready_task.Run(succeeded_configuration_types, failed_configuration_types); | |
| 587 } | |
| 588 | |
| 589 void SyncBackendHostImpl::AddExperimentalTypes() { | |
| 590 CHECK(initialized()); | |
| 591 syncer::Experiments experiments; | |
| 592 if (core_->sync_manager()->ReceivedExperiment(&experiments)) | |
| 593 frontend_->OnExperimentsChanged(experiments); | |
| 594 } | |
| 595 | |
| 596 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop( | |
| 597 const syncer::WeakHandle<syncer::JsBackend> js_backend, | |
| 598 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener> | |
| 599 debug_info_listener, | |
| 600 std::unique_ptr<syncer_v2::ModelTypeConnector> model_type_connector, | |
| 601 const std::string& cache_guid) { | |
| 602 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 603 | |
| 604 model_type_connector_ = std::move(model_type_connector); | |
| 605 | |
| 606 if (!frontend_) | |
| 607 return; | |
| 608 | |
| 609 initialized_ = true; | |
| 610 | |
| 611 if (invalidator_) { | |
| 612 invalidator_->RegisterInvalidationHandler(this); | |
| 613 invalidation_handler_registered_ = true; | |
| 614 | |
| 615 // Fake a state change to initialize the SyncManager's cached invalidator | |
| 616 // state. | |
| 617 OnInvalidatorStateChange(invalidator_->GetInvalidatorState()); | |
| 618 } | |
| 619 | |
| 620 // Now that we've downloaded the control types, we can see if there are any | |
| 621 // experimental types to enable. This should be done before we inform | |
| 622 // the frontend to ensure they're visible in the customize screen. | |
| 623 AddExperimentalTypes(); | |
| 624 frontend_->OnBackendInitialized(js_backend, | |
| 625 debug_info_listener, | |
| 626 cache_guid, | |
| 627 true); | |
| 628 } | |
| 629 | |
| 630 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() { | |
| 631 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 632 if (!frontend_) | |
| 633 return; | |
| 634 | |
| 635 frontend_->OnBackendInitialized( | |
| 636 syncer::WeakHandle<syncer::JsBackend>(), | |
| 637 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), | |
| 638 "", | |
| 639 false); | |
| 640 } | |
| 641 | |
| 642 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop( | |
| 643 const syncer::sessions::SyncSessionSnapshot& snapshot) { | |
| 644 if (!frontend_) | |
| 645 return; | |
| 646 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 647 | |
| 648 last_snapshot_ = snapshot; | |
| 649 | |
| 650 SDVLOG(1) << "Got snapshot " << snapshot.ToString(); | |
| 651 | |
| 652 if (!snapshot.poll_finish_time().is_null()) | |
| 653 sync_prefs_->SetLastPollTime(snapshot.poll_finish_time()); | |
| 654 | |
| 655 // Process any changes to the datatypes we're syncing. | |
| 656 // TODO(sync): add support for removing types. | |
| 657 if (initialized()) | |
| 658 AddExperimentalTypes(); | |
| 659 | |
| 660 if (initialized()) | |
| 661 frontend_->OnSyncCycleCompleted(); | |
| 662 } | |
| 663 | |
| 664 void SyncBackendHostImpl::RetryConfigurationOnFrontendLoop( | |
| 665 const base::Closure& retry_callback) { | |
| 666 SDVLOG(1) << "Failed to complete configuration, informing of retry."; | |
| 667 retry_callback.Run(); | |
| 668 } | |
| 669 | |
| 670 void SyncBackendHostImpl::PersistEncryptionBootstrapToken( | |
| 671 const std::string& token, | |
| 672 syncer::BootstrapTokenType token_type) { | |
| 673 CHECK(sync_prefs_.get()); | |
| 674 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN) | |
| 675 sync_prefs_->SetEncryptionBootstrapToken(token); | |
| 676 else | |
| 677 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token); | |
| 678 } | |
| 679 | |
| 680 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop( | |
| 681 const syncer::SyncProtocolError& sync_error) { | |
| 682 if (!frontend_) | |
| 683 return; | |
| 684 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 685 frontend_->OnActionableError(sync_error); | |
| 686 } | |
| 687 | |
| 688 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop( | |
| 689 syncer::ModelTypeSet types) { | |
| 690 if (!frontend_) | |
| 691 return; | |
| 692 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 693 frontend_->OnMigrationNeededForTypes(types); | |
| 694 } | |
| 695 | |
| 696 void SyncBackendHostImpl::OnInvalidatorStateChange( | |
| 697 syncer::InvalidatorState state) { | |
| 698 registrar_->sync_thread()->task_runner()->PostTask( | |
| 699 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnInvalidatorStateChange, | |
| 700 core_.get(), state)); | |
| 701 } | |
| 702 | |
| 703 void SyncBackendHostImpl::OnIncomingInvalidation( | |
| 704 const syncer::ObjectIdInvalidationMap& invalidation_map) { | |
| 705 registrar_->sync_thread()->task_runner()->PostTask( | |
| 706 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnIncomingInvalidation, | |
| 707 core_.get(), invalidation_map)); | |
| 708 } | |
| 709 | |
| 710 std::string SyncBackendHostImpl::GetOwnerName() const { | |
| 711 return "SyncBackendHostImpl"; | |
| 712 } | |
| 713 | |
| 714 bool SyncBackendHostImpl::CheckPassphraseAgainstCachedPendingKeys( | |
| 715 const std::string& passphrase) const { | |
| 716 DCHECK(cached_pending_keys_.has_blob()); | |
| 717 DCHECK(!passphrase.empty()); | |
| 718 syncer::Nigori nigori; | |
| 719 nigori.InitByDerivation("localhost", "dummy", passphrase); | |
| 720 std::string plaintext; | |
| 721 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext); | |
| 722 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys."; | |
| 723 return result; | |
| 724 } | |
| 725 | |
| 726 void SyncBackendHostImpl::NotifyPassphraseRequired( | |
| 727 syncer::PassphraseRequiredReason reason, | |
| 728 sync_pb::EncryptedData pending_keys) { | |
| 729 if (!frontend_) | |
| 730 return; | |
| 731 | |
| 732 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 733 | |
| 734 // Update our cache of the cryptographer's pending keys. | |
| 735 cached_pending_keys_ = pending_keys; | |
| 736 | |
| 737 frontend_->OnPassphraseRequired(reason, pending_keys); | |
| 738 } | |
| 739 | |
| 740 void SyncBackendHostImpl::NotifyPassphraseAccepted() { | |
| 741 if (!frontend_) | |
| 742 return; | |
| 743 | |
| 744 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 745 | |
| 746 // Clear our cache of the cryptographer's pending keys. | |
| 747 cached_pending_keys_.clear_blob(); | |
| 748 frontend_->OnPassphraseAccepted(); | |
| 749 } | |
| 750 | |
| 751 void SyncBackendHostImpl::NotifyEncryptedTypesChanged( | |
| 752 syncer::ModelTypeSet encrypted_types, | |
| 753 bool encrypt_everything) { | |
| 754 if (!frontend_) | |
| 755 return; | |
| 756 | |
| 757 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 758 frontend_->OnEncryptedTypesChanged( | |
| 759 encrypted_types, encrypt_everything); | |
| 760 } | |
| 761 | |
| 762 void SyncBackendHostImpl::NotifyEncryptionComplete() { | |
| 763 if (!frontend_) | |
| 764 return; | |
| 765 | |
| 766 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 767 frontend_->OnEncryptionComplete(); | |
| 768 } | |
| 769 | |
| 770 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop( | |
| 771 syncer::PassphraseType type, | |
| 772 base::Time explicit_passphrase_time) { | |
| 773 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 774 DVLOG(1) << "Passphrase type changed to " | |
| 775 << syncer::PassphraseTypeToString(type); | |
| 776 cached_passphrase_type_ = type; | |
| 777 cached_explicit_passphrase_time_ = explicit_passphrase_time; | |
| 778 } | |
| 779 | |
| 780 void SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop( | |
| 781 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) { | |
| 782 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 783 frontend_->OnLocalSetPassphraseEncryption(nigori_state); | |
| 784 } | |
| 785 | |
| 786 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop( | |
| 787 syncer::ConnectionStatus status) { | |
| 788 if (!frontend_) | |
| 789 return; | |
| 790 | |
| 791 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
| 792 | |
| 793 DVLOG(1) << "Connection status changed: " | |
| 794 << syncer::ConnectionStatusToString(status); | |
| 795 frontend_->OnConnectionStatusChange(status); | |
| 796 } | |
| 797 | |
| 798 void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop( | |
| 799 syncer::ProtocolEvent* event) { | |
| 800 std::unique_ptr<syncer::ProtocolEvent> scoped_event(event); | |
| 801 if (!frontend_) | |
| 802 return; | |
| 803 frontend_->OnProtocolEvent(*scoped_event); | |
| 804 } | |
| 805 | |
| 806 void SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop( | |
| 807 syncer::ModelType type, | |
| 808 const syncer::CommitCounters& counters) { | |
| 809 if (!frontend_) | |
| 810 return; | |
| 811 frontend_->OnDirectoryTypeCommitCounterUpdated(type, counters); | |
| 812 } | |
| 813 | |
| 814 void SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop( | |
| 815 syncer::ModelType type, | |
| 816 const syncer::UpdateCounters& counters) { | |
| 817 if (!frontend_) | |
| 818 return; | |
| 819 frontend_->OnDirectoryTypeUpdateCounterUpdated(type, counters); | |
| 820 } | |
| 821 | |
| 822 void SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop( | |
| 823 syncer::ModelType type, | |
| 824 const syncer::StatusCounters& counters) { | |
| 825 if (!frontend_) | |
| 826 return; | |
| 827 frontend_->OnDirectoryTypeStatusCounterUpdated(type, counters); | |
| 828 } | |
| 829 | |
| 830 void SyncBackendHostImpl::UpdateInvalidationVersions( | |
| 831 const std::map<syncer::ModelType, int64_t>& invalidation_versions) { | |
| 832 sync_prefs_->UpdateInvalidationVersions(invalidation_versions); | |
| 833 } | |
| 834 | |
| 835 base::MessageLoop* SyncBackendHostImpl::GetSyncLoopForTesting() { | |
| 836 return registrar_->sync_thread()->message_loop(); | |
| 837 } | |
| 838 | |
| 839 void SyncBackendHostImpl::RefreshTypesForTest(syncer::ModelTypeSet types) { | |
| 840 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
| 841 | |
| 842 registrar_->sync_thread()->task_runner()->PostTask( | |
| 843 FROM_HERE, | |
| 844 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types)); | |
| 845 } | |
| 846 | |
| 847 void SyncBackendHostImpl::ClearServerData( | |
| 848 const syncer::SyncManager::ClearServerDataCallback& callback) { | |
| 849 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
| 850 registrar_->sync_thread()->task_runner()->PostTask( | |
| 851 FROM_HERE, base::Bind(&SyncBackendHostCore::DoClearServerData, | |
| 852 core_.get(), callback)); | |
| 853 } | |
| 854 | |
| 855 void SyncBackendHostImpl::OnCookieJarChanged(bool account_mismatch, | |
| 856 bool empty_jar) { | |
| 857 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
| 858 registrar_->sync_thread()->task_runner()->PostTask( | |
| 859 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnCookieJarChanged, | |
| 860 core_.get(), account_mismatch, empty_jar)); | |
| 861 } | |
| 862 | |
| 863 void SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop( | |
| 864 const syncer::SyncManager::ClearServerDataCallback& frontend_callback) { | |
| 865 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
| 866 frontend_callback.Run(); | |
| 867 } | |
| 868 | |
| 869 } // namespace browser_sync | |
| 870 | |
| 871 #undef SDVLOG | |
| 872 | |
| 873 #undef SLOG | |
| OLD | NEW |