ExtensionSyncService cleanup: process uninstalls in one step
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_host_impl.cc
blob833a9d978897c31c7896f3cd212e32a75d3c608c
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.
5 #include "chrome/browser/sync/glue/sync_backend_host_impl.h"
7 #include "base/command_line.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/single_thread_task_runner.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/signin/chrome_signin_client_factory.h"
15 #include "chrome/browser/sync/glue/invalidation_helper.h"
16 #include "chrome/browser/sync/glue/sync_backend_host_core.h"
17 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "components/invalidation/public/invalidation_service.h"
20 #include "components/invalidation/public/object_id_invalidation_map.h"
21 #include "components/network_time/network_time_tracker.h"
22 #include "components/signin/core/browser/signin_client.h"
23 #include "components/sync_driver/sync_frontend.h"
24 #include "components/sync_driver/sync_prefs.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_source.h"
28 #include "sync/internal_api/public/base_transaction.h"
29 #include "sync/internal_api/public/events/protocol_event.h"
30 #include "sync/internal_api/public/http_bridge.h"
31 #include "sync/internal_api/public/internal_components_factory.h"
32 #include "sync/internal_api/public/internal_components_factory_impl.h"
33 #include "sync/internal_api/public/network_resources.h"
34 #include "sync/internal_api/public/sync_manager.h"
35 #include "sync/internal_api/public/sync_manager_factory.h"
36 #include "sync/internal_api/public/util/experiments.h"
37 #include "sync/internal_api/public/util/sync_string_conversions.h"
39 // Helper macros to log with the syncer thread name; useful when there
40 // are multiple syncers involved.
42 #define SLOG(severity) LOG(severity) << name_ << ": "
44 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
46 using syncer::InternalComponentsFactory;
48 namespace browser_sync {
50 namespace {
52 void UpdateNetworkTimeOnUIThread(base::Time network_time,
53 base::TimeDelta resolution,
54 base::TimeDelta latency,
55 base::TimeTicks post_time) {
56 g_browser_process->network_time_tracker()->UpdateNetworkTime(
57 network_time, resolution, latency, post_time);
60 void UpdateNetworkTime(const base::Time& network_time,
61 const base::TimeDelta& resolution,
62 const base::TimeDelta& latency) {
63 content::BrowserThread::PostTask(
64 content::BrowserThread::UI,
65 FROM_HERE,
66 base::Bind(&UpdateNetworkTimeOnUIThread,
67 network_time, resolution, latency, base::TimeTicks::Now()));
70 } // namespace
72 SyncBackendHostImpl::SyncBackendHostImpl(
73 const std::string& name,
74 Profile* profile,
75 invalidation::InvalidationService* invalidator,
76 const base::WeakPtr<sync_driver::SyncPrefs>& sync_prefs,
77 const base::FilePath& sync_folder)
78 : frontend_loop_(base::MessageLoop::current()),
79 profile_(profile),
80 name_(name),
81 initialized_(false),
82 sync_prefs_(sync_prefs),
83 frontend_(NULL),
84 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
85 invalidator_(invalidator),
86 invalidation_handler_registered_(false),
87 weak_ptr_factory_(this) {
88 core_ = new SyncBackendHostCore(
89 name_,
90 profile_->GetPath().Append(sync_folder),
91 sync_prefs_->HasSyncSetupCompleted(),
92 weak_ptr_factory_.GetWeakPtr());
95 SyncBackendHostImpl::~SyncBackendHostImpl() {
96 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor.";
97 DCHECK(!registrar_.get());
100 void SyncBackendHostImpl::Initialize(
101 sync_driver::SyncFrontend* frontend,
102 scoped_ptr<base::Thread> sync_thread,
103 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
104 const GURL& sync_service_url,
105 const syncer::SyncCredentials& credentials,
106 bool delete_sync_data_folder,
107 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
108 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
109 const base::Closure& report_unrecoverable_error_function,
110 syncer::NetworkResources* network_resources,
111 scoped_ptr<syncer::SyncEncryptionHandler::NigoriState> saved_nigori_state) {
112 registrar_.reset(new browser_sync::SyncBackendRegistrar(name_,
113 profile_,
114 sync_thread.Pass()));
115 CHECK(registrar_->sync_thread());
117 frontend_ = frontend;
118 DCHECK(frontend);
120 syncer::ModelSafeRoutingInfo routing_info;
121 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
122 registrar_->GetModelSafeRoutingInfo(&routing_info);
123 registrar_->GetWorkers(&workers);
125 InternalComponentsFactory::Switches factory_switches = {
126 InternalComponentsFactory::ENCRYPTION_KEYSTORE,
127 InternalComponentsFactory::BACKOFF_NORMAL
130 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
131 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) {
132 factory_switches.backoff_override =
133 InternalComponentsFactory::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE;
135 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) {
136 factory_switches.pre_commit_updates_policy =
137 InternalComponentsFactory::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE;
139 syncer::PassphraseTransitionClearDataOption clear_data_option =
140 syncer::PASSPHRASE_TRANSITION_DO_NOT_CLEAR_DATA;
141 if (cl->HasSwitch(switches::kSyncEnableClearDataOnPassphraseEncryption))
142 clear_data_option = syncer::PASSPHRASE_TRANSITION_CLEAR_DATA;
144 scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions(
145 registrar_->sync_thread()->message_loop(), registrar_.get(), routing_info,
146 workers, extensions_activity_monitor_.GetExtensionsActivity(),
147 event_handler, sync_service_url,
148 network_resources->GetHttpPostProviderFactory(
149 make_scoped_refptr(profile_->GetRequestContext()),
150 base::Bind(&UpdateNetworkTime),
151 core_->GetRequestContextCancelationSignal()),
152 credentials, invalidator_ ? invalidator_->GetInvalidatorClientId() : "",
153 sync_manager_factory.Pass(), delete_sync_data_folder,
154 sync_prefs_->GetEncryptionBootstrapToken(),
155 sync_prefs_->GetKeystoreEncryptionBootstrapToken(),
156 scoped_ptr<InternalComponentsFactory>(
157 new syncer::InternalComponentsFactoryImpl(factory_switches))
158 .Pass(),
159 unrecoverable_error_handler.Pass(), report_unrecoverable_error_function,
160 saved_nigori_state.Pass(), clear_data_option));
161 InitCore(init_opts.Pass());
164 void SyncBackendHostImpl::UpdateCredentials(
165 const syncer::SyncCredentials& credentials) {
166 DCHECK(registrar_->sync_thread()->IsRunning());
167 registrar_->sync_thread()->task_runner()->PostTask(
168 FROM_HERE, base::Bind(&SyncBackendHostCore::DoUpdateCredentials,
169 core_.get(), credentials));
172 void SyncBackendHostImpl::StartSyncingWithServer() {
173 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called.";
175 syncer::ModelSafeRoutingInfo routing_info;
176 registrar_->GetModelSafeRoutingInfo(&routing_info);
178 registrar_->sync_thread()->task_runner()->PostTask(
179 FROM_HERE, base::Bind(&SyncBackendHostCore::DoStartSyncing, core_.get(),
180 routing_info, sync_prefs_->GetLastPollTime()));
183 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase,
184 bool is_explicit) {
185 DCHECK(registrar_->sync_thread()->IsRunning());
186 if (!IsNigoriEnabled()) {
187 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori"
188 " is disabled.";
189 return;
192 // We should never be called with an empty passphrase.
193 DCHECK(!passphrase.empty());
195 // This should only be called by the frontend.
196 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
198 // SetEncryptionPassphrase should never be called if we are currently
199 // encrypted with an explicit passphrase.
200 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE ||
201 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE);
203 // Post an encryption task on the syncer thread.
204 registrar_->sync_thread()->task_runner()->PostTask(
205 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase,
206 core_.get(), passphrase, is_explicit));
209 bool SyncBackendHostImpl::SetDecryptionPassphrase(
210 const std::string& passphrase) {
211 if (!IsNigoriEnabled()) {
212 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori"
213 " is disabled.";
214 return false;
217 // We should never be called with an empty passphrase.
218 DCHECK(!passphrase.empty());
220 // This should only be called by the frontend.
221 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
223 // This should only be called when we have cached pending keys.
224 DCHECK(cached_pending_keys_.has_blob());
226 // Check the passphrase that was provided against our local cache of the
227 // cryptographer's pending keys. If this was unsuccessful, the UI layer can
228 // immediately call OnPassphraseRequired without showing the user a spinner.
229 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase))
230 return false;
232 // Post a decryption task on the syncer thread.
233 registrar_->sync_thread()->task_runner()->PostTask(
234 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase,
235 core_.get(), passphrase));
237 // Since we were able to decrypt the cached pending keys with the passphrase
238 // provided, we immediately alert the UI layer that the passphrase was
239 // accepted. This will avoid the situation where a user enters a passphrase,
240 // clicks OK, immediately reopens the advanced settings dialog, and gets an
241 // unnecessary prompt for a passphrase.
242 // Note: It is not guaranteed that the passphrase will be accepted by the
243 // syncer thread, since we could receive a new nigori node while the task is
244 // pending. This scenario is a valid race, and SetDecryptionPassphrase can
245 // trigger a new OnPassphraseRequired if it needs to.
246 NotifyPassphraseAccepted();
247 return true;
250 void SyncBackendHostImpl::StopSyncingForShutdown() {
251 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
253 // Immediately stop sending messages to the frontend.
254 frontend_ = NULL;
256 // Stop listening for and forwarding locally-triggered sync refresh requests.
257 notification_registrar_.RemoveAll();
259 // Stop non-blocking sync types from sending any more requests to the syncer.
260 sync_context_proxy_.reset();
262 DCHECK(registrar_->sync_thread()->IsRunning());
264 registrar_->RequestWorkerStopOnUIThread();
266 core_->ShutdownOnUIThread();
269 scoped_ptr<base::Thread> SyncBackendHostImpl::Shutdown(
270 syncer::ShutdownReason reason) {
271 // StopSyncingForShutdown() (which nulls out |frontend_|) should be
272 // called first.
273 DCHECK(!frontend_);
274 DCHECK(registrar_->sync_thread()->IsRunning());
276 bool sync_thread_claimed = (reason != syncer::BROWSER_SHUTDOWN);
278 if (invalidation_handler_registered_) {
279 if (reason == syncer::DISABLE_SYNC) {
280 UnregisterInvalidationIds();
282 invalidator_->UnregisterInvalidationHandler(this);
283 invalidator_ = NULL;
285 invalidation_handler_registered_ = false;
287 // Shut down and destroy sync manager.
288 registrar_->sync_thread()->task_runner()->PostTask(
289 FROM_HERE,
290 base::Bind(&SyncBackendHostCore::DoShutdown, core_.get(), reason));
291 core_ = NULL;
293 // Worker cleanup.
294 SyncBackendRegistrar* detached_registrar = registrar_.release();
295 detached_registrar->sync_thread()->task_runner()->PostTask(
296 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
297 base::Unretained(detached_registrar)));
299 if (sync_thread_claimed)
300 return detached_registrar->ReleaseSyncThread();
301 else
302 return scoped_ptr<base::Thread>();
305 void SyncBackendHostImpl::UnregisterInvalidationIds() {
306 if (invalidation_handler_registered_) {
307 CHECK(invalidator_->UpdateRegisteredInvalidationIds(this,
308 syncer::ObjectIdSet()));
312 syncer::ModelTypeSet SyncBackendHostImpl::ConfigureDataTypes(
313 syncer::ConfigureReason reason,
314 const DataTypeConfigStateMap& config_state_map,
315 const base::Callback<void(syncer::ModelTypeSet, syncer::ModelTypeSet)>&
316 ready_task,
317 const base::Callback<void()>& retry_callback) {
318 // Only one configure is allowed at a time. This is guaranteed by our
319 // callers. The SyncBackendHostImpl requests one configure as the backend is
320 // initializing and waits for it to complete. After initialization, all
321 // configurations will pass through the DataTypeManager, which is careful to
322 // never send a new configure request until the current request succeeds.
324 // The SyncBackendRegistrar's routing info will be updated by adding the
325 // types_to_add to the list then removing types_to_remove. Any types which
326 // are not in either of those sets will remain untouched.
328 // Types which were not in the list previously are not fully downloaded, so we
329 // must ask the syncer to download them. Any newly supported datatypes will
330 // not have been in that routing info list, so they will be among the types
331 // downloaded if they are enabled.
333 // The SyncBackendRegistrar's state was initially derived from the types
334 // detected to have been downloaded in the database. Afterwards it is
335 // modified only by this function. We expect it to remain in sync with the
336 // backend because configuration requests are never aborted; they are retried
337 // until they succeed or the backend is shut down.
339 syncer::ModelTypeSet disabled_types =
340 GetDataTypesInState(DISABLED, config_state_map);
341 syncer::ModelTypeSet fatal_types =
342 GetDataTypesInState(FATAL, config_state_map);
343 syncer::ModelTypeSet crypto_types =
344 GetDataTypesInState(CRYPTO, config_state_map);
345 syncer::ModelTypeSet unready_types =
346 GetDataTypesInState(UNREADY, config_state_map);
348 disabled_types.PutAll(fatal_types);
349 disabled_types.PutAll(crypto_types);
350 disabled_types.PutAll(unready_types);
352 syncer::ModelTypeSet active_types =
353 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
354 syncer::ModelTypeSet clean_first_types =
355 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
356 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes(
357 syncer::Union(active_types, clean_first_types),
358 disabled_types);
359 types_to_download.PutAll(clean_first_types);
360 types_to_download.RemoveAll(syncer::ProxyTypes());
361 if (!types_to_download.Empty())
362 types_to_download.Put(syncer::NIGORI);
364 // TODO(sync): crbug.com/137550.
365 // It's dangerous to configure types that have progress markers. Types with
366 // progress markers can trigger a MIGRATION_DONE response. We are not
367 // prepared to handle a migration during a configure, so we must ensure that
368 // all our types_to_download actually contain no data before we sync them.
370 // One common way to end up in this situation used to be types which
371 // downloaded some or all of their data but have not applied it yet. We avoid
372 // problems with those types by purging the data of any such partially synced
373 // types soon after we load the directory.
375 // Another possible scenario is that we have newly supported or newly enabled
376 // data types being downloaded here but the nigori type, which is always
377 // included in any GetUpdates request, requires migration. The server has
378 // code to detect this scenario based on the configure reason, the fact that
379 // the nigori type is the only requested type which requires migration, and
380 // that the requested types list includes at least one non-nigori type. It
381 // will not send a MIGRATION_DONE response in that case. We still need to be
382 // careful to not send progress markers for non-nigori types, though. If a
383 // non-nigori type in the request requires migration, a MIGRATION_DONE
384 // response will be sent.
386 syncer::ModelSafeRoutingInfo routing_info;
387 registrar_->GetModelSafeRoutingInfo(&routing_info);
389 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes();
390 syncer::ModelTypeSet types_to_purge =
391 syncer::Difference(syncer::ModelTypeSet::All(), current_types);
392 syncer::ModelTypeSet inactive_types =
393 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
394 types_to_purge.RemoveAll(inactive_types);
395 types_to_purge.RemoveAll(unready_types);
397 // If a type has already been disabled and unapplied or journaled, it will
398 // not be part of the |types_to_purge| set, and therefore does not need
399 // to be acted on again.
400 fatal_types.RetainAll(types_to_purge);
401 syncer::ModelTypeSet unapply_types =
402 syncer::Union(crypto_types, clean_first_types);
403 unapply_types.RetainAll(types_to_purge);
405 DCHECK(syncer::Intersection(current_types, fatal_types).Empty());
406 DCHECK(syncer::Intersection(current_types, crypto_types).Empty());
407 DCHECK(current_types.HasAll(types_to_download));
409 SDVLOG(1) << "Types "
410 << syncer::ModelTypeSetToString(types_to_download)
411 << " added; calling DoConfigureSyncer";
412 // Divide up the types into their corresponding actions (each is mutually
413 // exclusive):
414 // - Types which have just been added to the routing info (types_to_download):
415 // are downloaded.
416 // - Types which have encountered a fatal error (fatal_types) are deleted
417 // from the directory and journaled in the delete journal.
418 // - Types which have encountered a cryptographer error (crypto_types) are
419 // unapplied (local state is purged but sync state is not).
420 // - All other types not in the routing info (types just disabled) are deleted
421 // from the directory.
422 // - Everything else (enabled types and already disabled types) is not
423 // touched.
424 RequestConfigureSyncer(reason,
425 types_to_download,
426 types_to_purge,
427 fatal_types,
428 unapply_types,
429 inactive_types,
430 routing_info,
431 ready_task,
432 retry_callback);
434 DCHECK(syncer::Intersection(active_types, types_to_purge).Empty());
435 DCHECK(syncer::Intersection(active_types, fatal_types).Empty());
436 DCHECK(syncer::Intersection(active_types, unapply_types).Empty());
437 DCHECK(syncer::Intersection(active_types, inactive_types).Empty());
438 return syncer::Difference(active_types, types_to_download);
441 void SyncBackendHostImpl::EnableEncryptEverything() {
442 registrar_->sync_thread()->task_runner()->PostTask(
443 FROM_HERE,
444 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything, core_.get()));
447 void SyncBackendHostImpl::ActivateDataType(
448 syncer::ModelType type, syncer::ModelSafeGroup group,
449 sync_driver::ChangeProcessor* change_processor) {
450 registrar_->ActivateDataType(type, group, change_processor, GetUserShare());
453 void SyncBackendHostImpl::DeactivateDataType(syncer::ModelType type) {
454 registrar_->DeactivateDataType(type);
457 syncer::UserShare* SyncBackendHostImpl::GetUserShare() const {
458 return core_->sync_manager()->GetUserShare();
461 scoped_ptr<syncer::SyncContextProxy>
462 SyncBackendHostImpl::GetSyncContextProxy() {
463 return sync_context_proxy_.get() ? scoped_ptr<syncer::SyncContextProxy>(
464 sync_context_proxy_->Clone())
465 : scoped_ptr<syncer::SyncContextProxy>();
468 SyncBackendHostImpl::Status SyncBackendHostImpl::GetDetailedStatus() {
469 DCHECK(initialized());
470 return core_->sync_manager()->GetDetailedStatus();
473 syncer::sessions::SyncSessionSnapshot
474 SyncBackendHostImpl::GetLastSessionSnapshot() const {
475 return last_snapshot_;
478 bool SyncBackendHostImpl::HasUnsyncedItems() const {
479 DCHECK(initialized());
480 return core_->sync_manager()->HasUnsyncedItems();
483 bool SyncBackendHostImpl::IsNigoriEnabled() const {
484 return registrar_.get() && registrar_->IsNigoriEnabled();
487 syncer::PassphraseType SyncBackendHostImpl::GetPassphraseType() const {
488 return cached_passphrase_type_;
491 base::Time SyncBackendHostImpl::GetExplicitPassphraseTime() const {
492 return cached_explicit_passphrase_time_;
495 bool SyncBackendHostImpl::IsCryptographerReady(
496 const syncer::BaseTransaction* trans) const {
497 return initialized() && trans->GetCryptographer() &&
498 trans->GetCryptographer()->is_ready();
501 void SyncBackendHostImpl::GetModelSafeRoutingInfo(
502 syncer::ModelSafeRoutingInfo* out) const {
503 if (initialized()) {
504 CHECK(registrar_.get());
505 registrar_->GetModelSafeRoutingInfo(out);
506 } else {
507 NOTREACHED();
511 void SyncBackendHostImpl::FlushDirectory() const {
512 DCHECK(initialized());
513 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
514 base::Bind(&SyncBackendHostCore::SaveChanges, core_));
517 void SyncBackendHostImpl::RequestBufferedProtocolEventsAndEnableForwarding() {
518 registrar_->sync_thread()->task_runner()->PostTask(
519 FROM_HERE,
520 base::Bind(
521 &SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding,
522 core_));
525 void SyncBackendHostImpl::DisableProtocolEventForwarding() {
526 registrar_->sync_thread()->task_runner()->PostTask(
527 FROM_HERE,
528 base::Bind(&SyncBackendHostCore::DisableProtocolEventForwarding, core_));
531 void SyncBackendHostImpl::EnableDirectoryTypeDebugInfoForwarding() {
532 DCHECK(initialized());
533 registrar_->sync_thread()->task_runner()->PostTask(
534 FROM_HERE,
535 base::Bind(&SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding,
536 core_));
539 void SyncBackendHostImpl::DisableDirectoryTypeDebugInfoForwarding() {
540 DCHECK(initialized());
541 registrar_->sync_thread()->task_runner()->PostTask(
542 FROM_HERE,
543 base::Bind(&SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding,
544 core_));
547 void SyncBackendHostImpl::GetAllNodesForTypes(
548 syncer::ModelTypeSet types,
549 base::Callback<void(const std::vector<syncer::ModelType>&,
550 ScopedVector<base::ListValue>)> callback) {
551 DCHECK(initialized());
552 registrar_->sync_thread()->task_runner()->PostTask(
553 FROM_HERE, base::Bind(&SyncBackendHostCore::GetAllNodesForTypes, core_,
554 types, frontend_loop_->task_runner(), callback));
557 void SyncBackendHostImpl::InitCore(scoped_ptr<DoInitializeOptions> options) {
558 registrar_->sync_thread()->task_runner()->PostTask(
559 FROM_HERE, base::Bind(&SyncBackendHostCore::DoInitialize, core_.get(),
560 base::Passed(&options)));
563 void SyncBackendHostImpl::RequestConfigureSyncer(
564 syncer::ConfigureReason reason,
565 syncer::ModelTypeSet to_download,
566 syncer::ModelTypeSet to_purge,
567 syncer::ModelTypeSet to_journal,
568 syncer::ModelTypeSet to_unapply,
569 syncer::ModelTypeSet to_ignore,
570 const syncer::ModelSafeRoutingInfo& routing_info,
571 const base::Callback<void(syncer::ModelTypeSet,
572 syncer::ModelTypeSet)>& ready_task,
573 const base::Closure& retry_callback) {
574 DoConfigureSyncerTypes config_types;
575 config_types.to_download = to_download;
576 config_types.to_purge = to_purge;
577 config_types.to_journal = to_journal;
578 config_types.to_unapply = to_unapply;
579 registrar_->sync_thread()->task_runner()->PostTask(
580 FROM_HERE,
581 base::Bind(&SyncBackendHostCore::DoConfigureSyncer, core_.get(), reason,
582 config_types, routing_info, ready_task, retry_callback));
585 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop(
586 const syncer::ModelTypeSet enabled_types,
587 const syncer::ModelTypeSet succeeded_configuration_types,
588 const syncer::ModelTypeSet failed_configuration_types,
589 const base::Callback<void(syncer::ModelTypeSet,
590 syncer::ModelTypeSet)>& ready_task) {
591 if (!frontend_)
592 return;
594 if (invalidator_) {
595 CHECK(invalidator_->UpdateRegisteredInvalidationIds(
596 this, ModelTypeSetToObjectIdSet(enabled_types)));
599 if (!ready_task.is_null())
600 ready_task.Run(succeeded_configuration_types, failed_configuration_types);
603 void SyncBackendHostImpl::Observe(
604 int type,
605 const content::NotificationSource& source,
606 const content::NotificationDetails& details) {
607 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
608 DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL);
610 content::Details<const syncer::ModelTypeSet> state_details(details);
611 const syncer::ModelTypeSet& types = *(state_details.ptr());
612 registrar_->sync_thread()->task_runner()->PostTask(
613 FROM_HERE,
614 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
617 void SyncBackendHostImpl::AddExperimentalTypes() {
618 CHECK(initialized());
619 syncer::Experiments experiments;
620 if (core_->sync_manager()->ReceivedExperiment(&experiments))
621 frontend_->OnExperimentsChanged(experiments);
624 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop(
625 const syncer::WeakHandle<syncer::JsBackend> js_backend,
626 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>
627 debug_info_listener,
628 syncer::SyncContextProxy* sync_context_proxy,
629 const std::string& cache_guid) {
630 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
632 if (sync_context_proxy)
633 sync_context_proxy_ = sync_context_proxy->Clone();
635 if (!frontend_)
636 return;
638 initialized_ = true;
640 if (invalidator_) {
641 invalidator_->RegisterInvalidationHandler(this);
642 invalidation_handler_registered_ = true;
644 // Fake a state change to initialize the SyncManager's cached invalidator
645 // state.
646 OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
649 // Start forwarding refresh requests to the SyncManager
650 notification_registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
651 content::Source<Profile>(profile_));
653 // Now that we've downloaded the control types, we can see if there are any
654 // experimental types to enable. This should be done before we inform
655 // the frontend to ensure they're visible in the customize screen.
656 AddExperimentalTypes();
657 frontend_->OnBackendInitialized(js_backend,
658 debug_info_listener,
659 cache_guid,
660 true);
663 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() {
664 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
665 if (!frontend_)
666 return;
668 frontend_->OnBackendInitialized(
669 syncer::WeakHandle<syncer::JsBackend>(),
670 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
672 false);
675 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop(
676 const syncer::sessions::SyncSessionSnapshot& snapshot) {
677 if (!frontend_)
678 return;
679 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
681 last_snapshot_ = snapshot;
683 SDVLOG(1) << "Got snapshot " << snapshot.ToString();
685 if (!snapshot.poll_finish_time().is_null())
686 sync_prefs_->SetLastPollTime(snapshot.poll_finish_time());
688 // Process any changes to the datatypes we're syncing.
689 // TODO(sync): add support for removing types.
690 if (initialized())
691 AddExperimentalTypes();
693 if (initialized())
694 frontend_->OnSyncCycleCompleted();
697 void SyncBackendHostImpl::RetryConfigurationOnFrontendLoop(
698 const base::Closure& retry_callback) {
699 SDVLOG(1) << "Failed to complete configuration, informing of retry.";
700 retry_callback.Run();
703 void SyncBackendHostImpl::PersistEncryptionBootstrapToken(
704 const std::string& token,
705 syncer::BootstrapTokenType token_type) {
706 CHECK(sync_prefs_.get());
707 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN)
708 sync_prefs_->SetEncryptionBootstrapToken(token);
709 else
710 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token);
713 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop(
714 const syncer::SyncProtocolError& sync_error) {
715 if (!frontend_)
716 return;
717 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
718 frontend_->OnActionableError(sync_error);
721 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop(
722 syncer::ModelTypeSet types) {
723 if (!frontend_)
724 return;
725 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
726 frontend_->OnMigrationNeededForTypes(types);
729 void SyncBackendHostImpl::OnInvalidatorStateChange(
730 syncer::InvalidatorState state) {
731 registrar_->sync_thread()->task_runner()->PostTask(
732 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnInvalidatorStateChange,
733 core_.get(), state));
736 void SyncBackendHostImpl::OnIncomingInvalidation(
737 const syncer::ObjectIdInvalidationMap& invalidation_map) {
738 registrar_->sync_thread()->task_runner()->PostTask(
739 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnIncomingInvalidation,
740 core_.get(), invalidation_map));
743 std::string SyncBackendHostImpl::GetOwnerName() const {
744 return "SyncBackendHostImpl";
747 bool SyncBackendHostImpl::CheckPassphraseAgainstCachedPendingKeys(
748 const std::string& passphrase) const {
749 DCHECK(cached_pending_keys_.has_blob());
750 DCHECK(!passphrase.empty());
751 syncer::Nigori nigori;
752 nigori.InitByDerivation("localhost", "dummy", passphrase);
753 std::string plaintext;
754 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext);
755 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys.";
756 return result;
759 void SyncBackendHostImpl::NotifyPassphraseRequired(
760 syncer::PassphraseRequiredReason reason,
761 sync_pb::EncryptedData pending_keys) {
762 if (!frontend_)
763 return;
765 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
767 // Update our cache of the cryptographer's pending keys.
768 cached_pending_keys_ = pending_keys;
770 frontend_->OnPassphraseRequired(reason, pending_keys);
773 void SyncBackendHostImpl::NotifyPassphraseAccepted() {
774 if (!frontend_)
775 return;
777 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
779 // Clear our cache of the cryptographer's pending keys.
780 cached_pending_keys_.clear_blob();
781 frontend_->OnPassphraseAccepted();
784 void SyncBackendHostImpl::NotifyEncryptedTypesChanged(
785 syncer::ModelTypeSet encrypted_types,
786 bool encrypt_everything) {
787 if (!frontend_)
788 return;
790 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
791 frontend_->OnEncryptedTypesChanged(
792 encrypted_types, encrypt_everything);
795 void SyncBackendHostImpl::NotifyEncryptionComplete() {
796 if (!frontend_)
797 return;
799 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
800 frontend_->OnEncryptionComplete();
803 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop(
804 syncer::PassphraseType type,
805 base::Time explicit_passphrase_time) {
806 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
807 DVLOG(1) << "Passphrase type changed to "
808 << syncer::PassphraseTypeToString(type);
809 cached_passphrase_type_ = type;
810 cached_explicit_passphrase_time_ = explicit_passphrase_time;
813 void SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop(
814 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) {
815 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
816 frontend_->OnLocalSetPassphraseEncryption(nigori_state);
819 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop(
820 syncer::ConnectionStatus status) {
821 if (!frontend_)
822 return;
824 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
826 DVLOG(1) << "Connection status changed: "
827 << syncer::ConnectionStatusToString(status);
828 frontend_->OnConnectionStatusChange(status);
831 void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop(
832 syncer::ProtocolEvent* event) {
833 scoped_ptr<syncer::ProtocolEvent> scoped_event(event);
834 if (!frontend_)
835 return;
836 frontend_->OnProtocolEvent(*scoped_event);
839 void SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop(
840 syncer::ModelType type,
841 const syncer::CommitCounters& counters) {
842 if (!frontend_)
843 return;
844 frontend_->OnDirectoryTypeCommitCounterUpdated(type, counters);
847 void SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop(
848 syncer::ModelType type,
849 const syncer::UpdateCounters& counters) {
850 if (!frontend_)
851 return;
852 frontend_->OnDirectoryTypeUpdateCounterUpdated(type, counters);
855 void SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop(
856 syncer::ModelType type,
857 const syncer::StatusCounters& counters) {
858 if (!frontend_)
859 return;
860 frontend_->OnDirectoryTypeStatusCounterUpdated(type, counters);
863 base::MessageLoop* SyncBackendHostImpl::GetSyncLoopForTesting() {
864 return registrar_->sync_thread()->message_loop();
867 void SyncBackendHostImpl::RefreshTypesForTest(syncer::ModelTypeSet types) {
868 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
870 registrar_->sync_thread()->task_runner()->PostTask(
871 FROM_HERE,
872 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
875 } // namespace browser_sync
877 #undef SDVLOG
879 #undef SLOG