Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_host_impl.cc
blob1455d172658c42aa86961de6b856bb87d571312f
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/logging.h"
9 #include "base/profiler/scoped_tracker.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/signin/chrome_signin_client_factory.h"
14 #include "chrome/browser/sync/glue/invalidation_helper.h"
15 #include "chrome/browser/sync/glue/sync_backend_host_core.h"
16 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "components/invalidation/invalidation_service.h"
19 #include "components/invalidation/object_id_invalidation_map.h"
20 #include "components/network_time/network_time_tracker.h"
21 #include "components/signin/core/browser/signin_client.h"
22 #include "components/sync_driver/sync_frontend.h"
23 #include "components/sync_driver/sync_prefs.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_source.h"
27 #include "sync/internal_api/public/base_transaction.h"
28 #include "sync/internal_api/public/events/protocol_event.h"
29 #include "sync/internal_api/public/http_bridge.h"
30 #include "sync/internal_api/public/internal_components_factory.h"
31 #include "sync/internal_api/public/internal_components_factory_impl.h"
32 #include "sync/internal_api/public/network_resources.h"
33 #include "sync/internal_api/public/sync_manager.h"
34 #include "sync/internal_api/public/sync_manager_factory.h"
35 #include "sync/internal_api/public/util/experiments.h"
36 #include "sync/internal_api/public/util/sync_string_conversions.h"
38 // Helper macros to log with the syncer thread name; useful when there
39 // are multiple syncers involved.
41 #define SLOG(severity) LOG(severity) << name_ << ": "
43 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
45 using syncer::InternalComponentsFactory;
47 namespace browser_sync {
49 namespace {
51 void UpdateNetworkTimeOnUIThread(base::Time network_time,
52 base::TimeDelta resolution,
53 base::TimeDelta latency,
54 base::TimeTicks post_time) {
55 g_browser_process->network_time_tracker()->UpdateNetworkTime(
56 network_time, resolution, latency, post_time);
59 void UpdateNetworkTime(const base::Time& network_time,
60 const base::TimeDelta& resolution,
61 const base::TimeDelta& latency) {
62 content::BrowserThread::PostTask(
63 content::BrowserThread::UI,
64 FROM_HERE,
65 base::Bind(&UpdateNetworkTimeOnUIThread,
66 network_time, resolution, latency, base::TimeTicks::Now()));
69 } // namespace
71 SyncBackendHostImpl::SyncBackendHostImpl(
72 const std::string& name,
73 Profile* profile,
74 invalidation::InvalidationService* invalidator,
75 const base::WeakPtr<sync_driver::SyncPrefs>& sync_prefs,
76 const base::FilePath& sync_folder)
77 : frontend_loop_(base::MessageLoop::current()),
78 profile_(profile),
79 name_(name),
80 initialized_(false),
81 sync_prefs_(sync_prefs),
82 frontend_(NULL),
83 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
84 invalidator_(invalidator),
85 invalidation_handler_registered_(false),
86 weak_ptr_factory_(this) {
87 core_ = new SyncBackendHostCore(
88 name_,
89 profile_->GetPath().Append(sync_folder),
90 sync_prefs_->HasSyncSetupCompleted(),
91 weak_ptr_factory_.GetWeakPtr());
94 SyncBackendHostImpl::~SyncBackendHostImpl() {
95 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor.";
96 DCHECK(!registrar_.get());
99 void SyncBackendHostImpl::Initialize(
100 sync_driver::SyncFrontend* frontend,
101 scoped_ptr<base::Thread> sync_thread,
102 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
103 const GURL& sync_service_url,
104 const syncer::SyncCredentials& credentials,
105 bool delete_sync_data_folder,
106 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
107 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
108 syncer::ReportUnrecoverableErrorFunction
109 report_unrecoverable_error_function,
110 syncer::NetworkResources* network_resources) {
111 // TODO(pavely): Remove ScopedTracker below once crbug.com/426272 is fixed.
112 tracked_objects::ScopedTracker tracker1(FROM_HERE_WITH_EXPLICIT_FUNCTION(
113 "426272 SyncBackendHostImpl::Initialize registrar"));
114 registrar_.reset(new browser_sync::SyncBackendRegistrar(name_,
115 profile_,
116 sync_thread.Pass()));
117 CHECK(registrar_->sync_thread());
119 frontend_ = frontend;
120 DCHECK(frontend);
122 // TODO(pavely): Remove ScopedTracker below once crbug.com/426272 is fixed.
123 tracked_objects::ScopedTracker tracker2(FROM_HERE_WITH_EXPLICIT_FUNCTION(
124 "426272 SyncBackendHostImpl::Initialize locks"));
125 syncer::ModelSafeRoutingInfo routing_info;
126 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
127 registrar_->GetModelSafeRoutingInfo(&routing_info);
128 registrar_->GetWorkers(&workers);
129 // TODO(pavely): Remove ScopedTracker below once crbug.com/426272 is fixed.
130 tracked_objects::ScopedTracker tracker3(FROM_HERE_WITH_EXPLICIT_FUNCTION(
131 "426272 SyncBackendHostImpl::Initialize init"));
133 InternalComponentsFactory::Switches factory_switches = {
134 InternalComponentsFactory::ENCRYPTION_KEYSTORE,
135 InternalComponentsFactory::BACKOFF_NORMAL
138 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
139 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) {
140 factory_switches.backoff_override =
141 InternalComponentsFactory::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE;
143 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) {
144 factory_switches.pre_commit_updates_policy =
145 InternalComponentsFactory::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE;
148 scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions(
149 registrar_->sync_thread()->message_loop(),
150 registrar_.get(),
151 routing_info,
152 workers,
153 extensions_activity_monitor_.GetExtensionsActivity(),
154 event_handler,
155 sync_service_url,
156 network_resources->GetHttpPostProviderFactory(
157 make_scoped_refptr(profile_->GetRequestContext()),
158 base::Bind(&UpdateNetworkTime),
159 core_->GetRequestContextCancelationSignal()),
160 credentials,
161 invalidator_ ? invalidator_->GetInvalidatorClientId() : "",
162 sync_manager_factory.Pass(),
163 delete_sync_data_folder,
164 sync_prefs_->GetEncryptionBootstrapToken(),
165 sync_prefs_->GetKeystoreEncryptionBootstrapToken(),
166 scoped_ptr<InternalComponentsFactory>(
167 new syncer::InternalComponentsFactoryImpl(factory_switches)).Pass(),
168 unrecoverable_error_handler.Pass(),
169 report_unrecoverable_error_function));
170 InitCore(init_opts.Pass());
173 void SyncBackendHostImpl::UpdateCredentials(
174 const syncer::SyncCredentials& credentials) {
175 DCHECK(registrar_->sync_thread()->IsRunning());
176 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
177 base::Bind(&SyncBackendHostCore::DoUpdateCredentials,
178 core_.get(),
179 credentials));
182 void SyncBackendHostImpl::StartSyncingWithServer() {
183 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called.";
185 syncer::ModelSafeRoutingInfo routing_info;
186 registrar_->GetModelSafeRoutingInfo(&routing_info);
188 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
189 base::Bind(&SyncBackendHostCore::DoStartSyncing,
190 core_.get(), routing_info));
193 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase,
194 bool is_explicit) {
195 DCHECK(registrar_->sync_thread()->IsRunning());
196 if (!IsNigoriEnabled()) {
197 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori"
198 " is disabled.";
199 return;
202 // We should never be called with an empty passphrase.
203 DCHECK(!passphrase.empty());
205 // This should only be called by the frontend.
206 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
208 // SetEncryptionPassphrase should never be called if we are currently
209 // encrypted with an explicit passphrase.
210 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE ||
211 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE);
213 // Post an encryption task on the syncer thread.
214 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
215 base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase,
216 core_.get(),
217 passphrase, is_explicit));
220 bool SyncBackendHostImpl::SetDecryptionPassphrase(
221 const std::string& passphrase) {
222 if (!IsNigoriEnabled()) {
223 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori"
224 " is disabled.";
225 return false;
228 // We should never be called with an empty passphrase.
229 DCHECK(!passphrase.empty());
231 // This should only be called by the frontend.
232 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
234 // This should only be called when we have cached pending keys.
235 DCHECK(cached_pending_keys_.has_blob());
237 // Check the passphrase that was provided against our local cache of the
238 // cryptographer's pending keys. If this was unsuccessful, the UI layer can
239 // immediately call OnPassphraseRequired without showing the user a spinner.
240 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase))
241 return false;
243 // Post a decryption task on the syncer thread.
244 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
245 base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase,
246 core_.get(),
247 passphrase));
249 // Since we were able to decrypt the cached pending keys with the passphrase
250 // provided, we immediately alert the UI layer that the passphrase was
251 // accepted. This will avoid the situation where a user enters a passphrase,
252 // clicks OK, immediately reopens the advanced settings dialog, and gets an
253 // unnecessary prompt for a passphrase.
254 // Note: It is not guaranteed that the passphrase will be accepted by the
255 // syncer thread, since we could receive a new nigori node while the task is
256 // pending. This scenario is a valid race, and SetDecryptionPassphrase can
257 // trigger a new OnPassphraseRequired if it needs to.
258 NotifyPassphraseAccepted();
259 return true;
262 void SyncBackendHostImpl::StopSyncingForShutdown() {
263 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
265 // Immediately stop sending messages to the frontend.
266 frontend_ = NULL;
268 // Stop listening for and forwarding locally-triggered sync refresh requests.
269 notification_registrar_.RemoveAll();
271 // Stop non-blocking sync types from sending any more requests to the syncer.
272 sync_context_proxy_.reset();
274 DCHECK(registrar_->sync_thread()->IsRunning());
276 registrar_->RequestWorkerStopOnUIThread();
278 core_->ShutdownOnUIThread();
281 scoped_ptr<base::Thread> SyncBackendHostImpl::Shutdown(
282 syncer::ShutdownReason reason) {
283 // StopSyncingForShutdown() (which nulls out |frontend_|) should be
284 // called first.
285 DCHECK(!frontend_);
286 DCHECK(registrar_->sync_thread()->IsRunning());
288 bool sync_thread_claimed = (reason != syncer::BROWSER_SHUTDOWN);
290 if (invalidation_handler_registered_) {
291 if (reason == syncer::DISABLE_SYNC) {
292 UnregisterInvalidationIds();
294 invalidator_->UnregisterInvalidationHandler(this);
295 invalidator_ = NULL;
297 invalidation_handler_registered_ = false;
299 // Shut down and destroy sync manager.
300 registrar_->sync_thread()->message_loop()->PostTask(
301 FROM_HERE,
302 base::Bind(&SyncBackendHostCore::DoShutdown,
303 core_.get(), reason));
304 core_ = NULL;
306 // Worker cleanup.
307 SyncBackendRegistrar* detached_registrar = registrar_.release();
308 detached_registrar->sync_thread()->message_loop()->PostTask(
309 FROM_HERE,
310 base::Bind(&SyncBackendRegistrar::Shutdown,
311 base::Unretained(detached_registrar)));
313 if (sync_thread_claimed)
314 return detached_registrar->ReleaseSyncThread();
315 else
316 return scoped_ptr<base::Thread>();
319 void SyncBackendHostImpl::UnregisterInvalidationIds() {
320 if (invalidation_handler_registered_) {
321 invalidator_->UpdateRegisteredInvalidationIds(
322 this,
323 syncer::ObjectIdSet());
327 void SyncBackendHostImpl::ConfigureDataTypes(
328 syncer::ConfigureReason reason,
329 const DataTypeConfigStateMap& config_state_map,
330 const base::Callback<void(syncer::ModelTypeSet,
331 syncer::ModelTypeSet)>& ready_task,
332 const base::Callback<void()>& retry_callback) {
333 // Only one configure is allowed at a time. This is guaranteed by our
334 // callers. The SyncBackendHostImpl requests one configure as the backend is
335 // initializing and waits for it to complete. After initialization, all
336 // configurations will pass through the DataTypeManager, which is careful to
337 // never send a new configure request until the current request succeeds.
339 // The SyncBackendRegistrar's routing info will be updated by adding the
340 // types_to_add to the list then removing types_to_remove. Any types which
341 // are not in either of those sets will remain untouched.
343 // Types which were not in the list previously are not fully downloaded, so we
344 // must ask the syncer to download them. Any newly supported datatypes will
345 // not have been in that routing info list, so they will be among the types
346 // downloaded if they are enabled.
348 // The SyncBackendRegistrar's state was initially derived from the types
349 // detected to have been downloaded in the database. Afterwards it is
350 // modified only by this function. We expect it to remain in sync with the
351 // backend because configuration requests are never aborted; they are retried
352 // until they succeed or the backend is shut down.
354 syncer::ModelTypeSet disabled_types =
355 GetDataTypesInState(DISABLED, config_state_map);
356 syncer::ModelTypeSet fatal_types =
357 GetDataTypesInState(FATAL, config_state_map);
358 syncer::ModelTypeSet crypto_types =
359 GetDataTypesInState(CRYPTO, config_state_map);
360 syncer::ModelTypeSet unready_types =
361 GetDataTypesInState(UNREADY, config_state_map);
363 disabled_types.PutAll(fatal_types);
364 disabled_types.PutAll(crypto_types);
365 disabled_types.PutAll(unready_types);
367 syncer::ModelTypeSet active_types =
368 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
369 syncer::ModelTypeSet clean_first_types =
370 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
371 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes(
372 syncer::Union(active_types, clean_first_types),
373 disabled_types);
374 types_to_download.PutAll(clean_first_types);
375 types_to_download.RemoveAll(syncer::ProxyTypes());
376 if (!types_to_download.Empty())
377 types_to_download.Put(syncer::NIGORI);
379 // TODO(sync): crbug.com/137550.
380 // It's dangerous to configure types that have progress markers. Types with
381 // progress markers can trigger a MIGRATION_DONE response. We are not
382 // prepared to handle a migration during a configure, so we must ensure that
383 // all our types_to_download actually contain no data before we sync them.
385 // One common way to end up in this situation used to be types which
386 // downloaded some or all of their data but have not applied it yet. We avoid
387 // problems with those types by purging the data of any such partially synced
388 // types soon after we load the directory.
390 // Another possible scenario is that we have newly supported or newly enabled
391 // data types being downloaded here but the nigori type, which is always
392 // included in any GetUpdates request, requires migration. The server has
393 // code to detect this scenario based on the configure reason, the fact that
394 // the nigori type is the only requested type which requires migration, and
395 // that the requested types list includes at least one non-nigori type. It
396 // will not send a MIGRATION_DONE response in that case. We still need to be
397 // careful to not send progress markers for non-nigori types, though. If a
398 // non-nigori type in the request requires migration, a MIGRATION_DONE
399 // response will be sent.
401 syncer::ModelSafeRoutingInfo routing_info;
402 registrar_->GetModelSafeRoutingInfo(&routing_info);
404 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes();
405 syncer::ModelTypeSet types_to_purge =
406 syncer::Difference(syncer::ModelTypeSet::All(), current_types);
407 syncer::ModelTypeSet inactive_types =
408 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
409 types_to_purge.RemoveAll(inactive_types);
410 types_to_purge.RemoveAll(unready_types);
412 // If a type has already been disabled and unapplied or journaled, it will
413 // not be part of the |types_to_purge| set, and therefore does not need
414 // to be acted on again.
415 fatal_types.RetainAll(types_to_purge);
416 syncer::ModelTypeSet unapply_types =
417 syncer::Union(crypto_types, clean_first_types);
418 unapply_types.RetainAll(types_to_purge);
420 DCHECK(syncer::Intersection(current_types, fatal_types).Empty());
421 DCHECK(syncer::Intersection(current_types, crypto_types).Empty());
422 DCHECK(current_types.HasAll(types_to_download));
424 SDVLOG(1) << "Types "
425 << syncer::ModelTypeSetToString(types_to_download)
426 << " added; calling DoConfigureSyncer";
427 // Divide up the types into their corresponding actions (each is mutually
428 // exclusive):
429 // - Types which have just been added to the routing info (types_to_download):
430 // are downloaded.
431 // - Types which have encountered a fatal error (fatal_types) are deleted
432 // from the directory and journaled in the delete journal.
433 // - Types which have encountered a cryptographer error (crypto_types) are
434 // unapplied (local state is purged but sync state is not).
435 // - All other types not in the routing info (types just disabled) are deleted
436 // from the directory.
437 // - Everything else (enabled types and already disabled types) is not
438 // touched.
439 RequestConfigureSyncer(reason,
440 types_to_download,
441 types_to_purge,
442 fatal_types,
443 unapply_types,
444 inactive_types,
445 routing_info,
446 ready_task,
447 retry_callback);
450 void SyncBackendHostImpl::EnableEncryptEverything() {
451 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
452 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything,
453 core_.get()));
456 void SyncBackendHostImpl::ActivateDataType(
457 syncer::ModelType type, syncer::ModelSafeGroup group,
458 sync_driver::ChangeProcessor* change_processor) {
459 registrar_->ActivateDataType(type, group, change_processor, GetUserShare());
462 void SyncBackendHostImpl::DeactivateDataType(syncer::ModelType type) {
463 registrar_->DeactivateDataType(type);
466 syncer::UserShare* SyncBackendHostImpl::GetUserShare() const {
467 return core_->sync_manager()->GetUserShare();
470 scoped_ptr<syncer::SyncContextProxy>
471 SyncBackendHostImpl::GetSyncContextProxy() {
472 return sync_context_proxy_.get() ? scoped_ptr<syncer::SyncContextProxy>(
473 sync_context_proxy_->Clone())
474 : scoped_ptr<syncer::SyncContextProxy>();
477 SyncBackendHostImpl::Status SyncBackendHostImpl::GetDetailedStatus() {
478 DCHECK(initialized());
479 return core_->sync_manager()->GetDetailedStatus();
482 syncer::sessions::SyncSessionSnapshot
483 SyncBackendHostImpl::GetLastSessionSnapshot() const {
484 return last_snapshot_;
487 bool SyncBackendHostImpl::HasUnsyncedItems() const {
488 DCHECK(initialized());
489 return core_->sync_manager()->HasUnsyncedItems();
492 bool SyncBackendHostImpl::IsNigoriEnabled() const {
493 return registrar_.get() && registrar_->IsNigoriEnabled();
496 syncer::PassphraseType SyncBackendHostImpl::GetPassphraseType() const {
497 return cached_passphrase_type_;
500 base::Time SyncBackendHostImpl::GetExplicitPassphraseTime() const {
501 return cached_explicit_passphrase_time_;
504 bool SyncBackendHostImpl::IsCryptographerReady(
505 const syncer::BaseTransaction* trans) const {
506 return initialized() && trans->GetCryptographer() &&
507 trans->GetCryptographer()->is_ready();
510 void SyncBackendHostImpl::GetModelSafeRoutingInfo(
511 syncer::ModelSafeRoutingInfo* out) const {
512 if (initialized()) {
513 CHECK(registrar_.get());
514 registrar_->GetModelSafeRoutingInfo(out);
515 } else {
516 NOTREACHED();
520 void SyncBackendHostImpl::FlushDirectory() const {
521 DCHECK(initialized());
522 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
523 base::Bind(&SyncBackendHostCore::SaveChanges, core_));
526 void SyncBackendHostImpl::RequestBufferedProtocolEventsAndEnableForwarding() {
527 registrar_->sync_thread()->message_loop()->PostTask(
528 FROM_HERE,
529 base::Bind(
530 &SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding,
531 core_));
534 void SyncBackendHostImpl::DisableProtocolEventForwarding() {
535 registrar_->sync_thread()->message_loop()->PostTask(
536 FROM_HERE,
537 base::Bind(
538 &SyncBackendHostCore::DisableProtocolEventForwarding,
539 core_));
542 void SyncBackendHostImpl::EnableDirectoryTypeDebugInfoForwarding() {
543 DCHECK(initialized());
544 registrar_->sync_thread()->message_loop()->PostTask(
545 FROM_HERE,
546 base::Bind(
547 &SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding,
548 core_));
551 void SyncBackendHostImpl::DisableDirectoryTypeDebugInfoForwarding() {
552 DCHECK(initialized());
553 registrar_->sync_thread()->message_loop()->PostTask(
554 FROM_HERE,
555 base::Bind(
556 &SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding,
557 core_));
560 void SyncBackendHostImpl::GetAllNodesForTypes(
561 syncer::ModelTypeSet types,
562 base::Callback<void(const std::vector<syncer::ModelType>&,
563 ScopedVector<base::ListValue>)> callback) {
564 DCHECK(initialized());
565 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
566 base::Bind(
567 &SyncBackendHostCore::GetAllNodesForTypes,
568 core_,
569 types,
570 frontend_loop_->message_loop_proxy(),
571 callback));
574 void SyncBackendHostImpl::InitCore(scoped_ptr<DoInitializeOptions> options) {
575 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
576 base::Bind(&SyncBackendHostCore::DoInitialize,
577 core_.get(), base::Passed(&options)));
580 void SyncBackendHostImpl::RequestConfigureSyncer(
581 syncer::ConfigureReason reason,
582 syncer::ModelTypeSet to_download,
583 syncer::ModelTypeSet to_purge,
584 syncer::ModelTypeSet to_journal,
585 syncer::ModelTypeSet to_unapply,
586 syncer::ModelTypeSet to_ignore,
587 const syncer::ModelSafeRoutingInfo& routing_info,
588 const base::Callback<void(syncer::ModelTypeSet,
589 syncer::ModelTypeSet)>& ready_task,
590 const base::Closure& retry_callback) {
591 DoConfigureSyncerTypes config_types;
592 config_types.to_download = to_download;
593 config_types.to_purge = to_purge;
594 config_types.to_journal = to_journal;
595 config_types.to_unapply = to_unapply;
596 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
597 base::Bind(&SyncBackendHostCore::DoConfigureSyncer,
598 core_.get(),
599 reason,
600 config_types,
601 routing_info,
602 ready_task,
603 retry_callback));
606 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop(
607 const syncer::ModelTypeSet enabled_types,
608 const syncer::ModelTypeSet succeeded_configuration_types,
609 const syncer::ModelTypeSet failed_configuration_types,
610 const base::Callback<void(syncer::ModelTypeSet,
611 syncer::ModelTypeSet)>& ready_task) {
612 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458406 is
613 // fixed.
614 tracked_objects::ScopedTracker tracking_profile1(
615 FROM_HERE_WITH_EXPLICIT_FUNCTION(
616 "458406 SyncBackendHostImpl::FinishConfigureDataTOFL"));
617 if (!frontend_)
618 return;
620 if (invalidator_) {
621 invalidator_->UpdateRegisteredInvalidationIds(
622 this,
623 ModelTypeSetToObjectIdSet(enabled_types));
626 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458406 is
627 // fixed.
628 tracked_objects::ScopedTracker tracking_profile2(
629 FROM_HERE_WITH_EXPLICIT_FUNCTION(
630 "458406 SyncBackendHostImpl::FinishConfigureDataTOFL::ReadyTask"));
631 if (!ready_task.is_null())
632 ready_task.Run(succeeded_configuration_types, failed_configuration_types);
635 void SyncBackendHostImpl::Observe(
636 int type,
637 const content::NotificationSource& source,
638 const content::NotificationDetails& details) {
639 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
640 DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL);
642 content::Details<const syncer::ModelTypeSet> state_details(details);
643 const syncer::ModelTypeSet& types = *(state_details.ptr());
644 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
645 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
648 void SyncBackendHostImpl::AddExperimentalTypes() {
649 CHECK(initialized());
650 syncer::Experiments experiments;
651 if (core_->sync_manager()->ReceivedExperiment(&experiments))
652 frontend_->OnExperimentsChanged(experiments);
655 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop(
656 const syncer::WeakHandle<syncer::JsBackend> js_backend,
657 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>
658 debug_info_listener,
659 syncer::SyncContextProxy* sync_context_proxy,
660 const std::string& cache_guid) {
661 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
663 if (sync_context_proxy)
664 sync_context_proxy_ = sync_context_proxy->Clone();
666 if (!frontend_)
667 return;
669 initialized_ = true;
671 if (invalidator_) {
672 invalidator_->RegisterInvalidationHandler(this);
673 invalidation_handler_registered_ = true;
675 // Fake a state change to initialize the SyncManager's cached invalidator
676 // state.
677 OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
680 // Start forwarding refresh requests to the SyncManager
681 notification_registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
682 content::Source<Profile>(profile_));
684 // Now that we've downloaded the control types, we can see if there are any
685 // experimental types to enable. This should be done before we inform
686 // the frontend to ensure they're visible in the customize screen.
687 AddExperimentalTypes();
688 frontend_->OnBackendInitialized(js_backend,
689 debug_info_listener,
690 cache_guid,
691 true);
694 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() {
695 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
696 if (!frontend_)
697 return;
699 frontend_->OnBackendInitialized(
700 syncer::WeakHandle<syncer::JsBackend>(),
701 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
703 false);
706 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop(
707 const syncer::sessions::SyncSessionSnapshot& snapshot) {
708 if (!frontend_)
709 return;
710 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
712 last_snapshot_ = snapshot;
714 SDVLOG(1) << "Got snapshot " << snapshot.ToString();
716 // Process any changes to the datatypes we're syncing.
717 // TODO(sync): add support for removing types.
718 if (initialized())
719 AddExperimentalTypes();
721 if (initialized())
722 frontend_->OnSyncCycleCompleted();
725 void SyncBackendHostImpl::RetryConfigurationOnFrontendLoop(
726 const base::Closure& retry_callback) {
727 SDVLOG(1) << "Failed to complete configuration, informing of retry.";
728 retry_callback.Run();
731 void SyncBackendHostImpl::PersistEncryptionBootstrapToken(
732 const std::string& token,
733 syncer::BootstrapTokenType token_type) {
734 CHECK(sync_prefs_.get());
735 DCHECK(!token.empty());
736 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN)
737 sync_prefs_->SetEncryptionBootstrapToken(token);
738 else
739 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token);
742 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop(
743 const syncer::SyncProtocolError& sync_error) {
744 if (!frontend_)
745 return;
746 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
747 frontend_->OnActionableError(sync_error);
750 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop(
751 syncer::ModelTypeSet types) {
752 if (!frontend_)
753 return;
754 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
755 frontend_->OnMigrationNeededForTypes(types);
758 void SyncBackendHostImpl::OnInvalidatorStateChange(
759 syncer::InvalidatorState state) {
760 registrar_->sync_thread()->message_loop()->PostTask(
761 FROM_HERE,
762 base::Bind(&SyncBackendHostCore::DoOnInvalidatorStateChange,
763 core_.get(),
764 state));
767 void SyncBackendHostImpl::OnIncomingInvalidation(
768 const syncer::ObjectIdInvalidationMap& invalidation_map) {
769 registrar_->sync_thread()->message_loop()->PostTask(
770 FROM_HERE,
771 base::Bind(&SyncBackendHostCore::DoOnIncomingInvalidation,
772 core_.get(),
773 invalidation_map));
776 std::string SyncBackendHostImpl::GetOwnerName() const {
777 return "SyncBackendHostImpl";
780 bool SyncBackendHostImpl::CheckPassphraseAgainstCachedPendingKeys(
781 const std::string& passphrase) const {
782 DCHECK(cached_pending_keys_.has_blob());
783 DCHECK(!passphrase.empty());
784 syncer::Nigori nigori;
785 nigori.InitByDerivation("localhost", "dummy", passphrase);
786 std::string plaintext;
787 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext);
788 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys.";
789 return result;
792 void SyncBackendHostImpl::NotifyPassphraseRequired(
793 syncer::PassphraseRequiredReason reason,
794 sync_pb::EncryptedData pending_keys) {
795 if (!frontend_)
796 return;
798 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
800 // Update our cache of the cryptographer's pending keys.
801 cached_pending_keys_ = pending_keys;
803 frontend_->OnPassphraseRequired(reason, pending_keys);
806 void SyncBackendHostImpl::NotifyPassphraseAccepted() {
807 if (!frontend_)
808 return;
810 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
812 // Clear our cache of the cryptographer's pending keys.
813 cached_pending_keys_.clear_blob();
814 frontend_->OnPassphraseAccepted();
817 void SyncBackendHostImpl::NotifyEncryptedTypesChanged(
818 syncer::ModelTypeSet encrypted_types,
819 bool encrypt_everything) {
820 if (!frontend_)
821 return;
823 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
824 frontend_->OnEncryptedTypesChanged(
825 encrypted_types, encrypt_everything);
828 void SyncBackendHostImpl::NotifyEncryptionComplete() {
829 if (!frontend_)
830 return;
832 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
833 frontend_->OnEncryptionComplete();
836 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop(
837 syncer::PassphraseType type,
838 base::Time explicit_passphrase_time) {
839 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
840 DVLOG(1) << "Passphrase type changed to "
841 << syncer::PassphraseTypeToString(type);
842 cached_passphrase_type_ = type;
843 cached_explicit_passphrase_time_ = explicit_passphrase_time;
846 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop(
847 syncer::ConnectionStatus status) {
848 if (!frontend_)
849 return;
851 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
853 DVLOG(1) << "Connection status changed: "
854 << syncer::ConnectionStatusToString(status);
855 frontend_->OnConnectionStatusChange(status);
858 void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop(
859 syncer::ProtocolEvent* event) {
860 scoped_ptr<syncer::ProtocolEvent> scoped_event(event);
861 if (!frontend_)
862 return;
863 frontend_->OnProtocolEvent(*scoped_event);
866 void SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop(
867 syncer::ModelType type,
868 const syncer::CommitCounters& counters) {
869 if (!frontend_)
870 return;
871 frontend_->OnDirectoryTypeCommitCounterUpdated(type, counters);
874 void SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop(
875 syncer::ModelType type,
876 const syncer::UpdateCounters& counters) {
877 if (!frontend_)
878 return;
879 frontend_->OnDirectoryTypeUpdateCounterUpdated(type, counters);
882 void SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop(
883 syncer::ModelType type,
884 const syncer::StatusCounters& counters) {
885 if (!frontend_)
886 return;
887 frontend_->OnDirectoryTypeStatusCounterUpdated(type, counters);
890 base::MessageLoop* SyncBackendHostImpl::GetSyncLoopForTesting() {
891 return registrar_->sync_thread()->message_loop();
894 } // namespace browser_sync
896 #undef SDVLOG
898 #undef SLOG