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 "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/invalidation/invalidation_service.h"
11 #include "chrome/browser/invalidation/invalidation_service_factory.h"
12 #include "chrome/browser/network_time/network_time_tracker.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/sync/glue/sync_backend_host_core.h"
15 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "components/sync_driver/sync_frontend.h"
18 #include "components/sync_driver/sync_prefs.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/notification_details.h"
21 #include "content/public/browser/notification_source.h"
22 #include "sync/internal_api/public/base_transaction.h"
23 #include "sync/internal_api/public/events/protocol_event.h"
24 #include "sync/internal_api/public/http_bridge.h"
25 #include "sync/internal_api/public/internal_components_factory.h"
26 #include "sync/internal_api/public/internal_components_factory_impl.h"
27 #include "sync/internal_api/public/network_resources.h"
28 #include "sync/internal_api/public/sync_manager.h"
29 #include "sync/internal_api/public/sync_manager_factory.h"
30 #include "sync/internal_api/public/util/experiments.h"
31 #include "sync/internal_api/public/util/sync_string_conversions.h"
32 #include "sync/notifier/object_id_invalidation_map.h"
34 // Helper macros to log with the syncer thread name; useful when there
35 // are multiple syncers involved.
37 #define SLOG(severity) LOG(severity) << name_ << ": "
39 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
41 using syncer::InternalComponentsFactory
;
43 static const base::FilePath::CharType kSyncDataFolderName
[] =
44 FILE_PATH_LITERAL("Sync Data");
46 namespace browser_sync
{
48 SyncBackendHostImpl::SyncBackendHostImpl(
49 const std::string
& name
,
51 const base::WeakPtr
<sync_driver::SyncPrefs
>& sync_prefs
)
52 : frontend_loop_(base::MessageLoop::current()),
56 sync_prefs_(sync_prefs
),
58 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE
),
60 invalidation::InvalidationServiceFactory::GetForProfile(profile
)),
61 invalidation_handler_registered_(false),
62 weak_ptr_factory_(this) {
64 core_
= new SyncBackendHostCore(
66 profile_
->GetPath().Append(kSyncDataFolderName
),
67 sync_prefs_
->HasSyncSetupCompleted(),
68 weak_ptr_factory_
.GetWeakPtr());
71 SyncBackendHostImpl::~SyncBackendHostImpl() {
72 DCHECK(!core_
.get() && !frontend_
) << "Must call Shutdown before destructor.";
73 DCHECK(!registrar_
.get());
76 void SyncBackendHostImpl::Initialize(
77 SyncFrontend
* frontend
,
78 scoped_ptr
<base::Thread
> sync_thread
,
79 const syncer::WeakHandle
<syncer::JsEventHandler
>& event_handler
,
80 const GURL
& sync_service_url
,
81 const syncer::SyncCredentials
& credentials
,
82 bool delete_sync_data_folder
,
83 scoped_ptr
<syncer::SyncManagerFactory
> sync_manager_factory
,
84 scoped_ptr
<syncer::UnrecoverableErrorHandler
> unrecoverable_error_handler
,
85 syncer::ReportUnrecoverableErrorFunction
86 report_unrecoverable_error_function
,
87 syncer::NetworkResources
* network_resources
) {
88 registrar_
.reset(new browser_sync::SyncBackendRegistrar(name_
,
91 CHECK(registrar_
->sync_thread());
96 syncer::ModelSafeRoutingInfo routing_info
;
97 std::vector
<scoped_refptr
<syncer::ModelSafeWorker
> > workers
;
98 registrar_
->GetModelSafeRoutingInfo(&routing_info
);
99 registrar_
->GetWorkers(&workers
);
101 InternalComponentsFactory::Switches factory_switches
= {
102 InternalComponentsFactory::ENCRYPTION_KEYSTORE
,
103 InternalComponentsFactory::BACKOFF_NORMAL
106 CommandLine
* cl
= CommandLine::ForCurrentProcess();
107 if (cl
->HasSwitch(switches::kSyncShortInitialRetryOverride
)) {
108 factory_switches
.backoff_override
=
109 InternalComponentsFactory::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE
;
111 if (cl
->HasSwitch(switches::kSyncEnableGetUpdateAvoidance
)) {
112 factory_switches
.pre_commit_updates_policy
=
113 InternalComponentsFactory::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE
;
116 scoped_ptr
<DoInitializeOptions
> init_opts(new DoInitializeOptions(
117 registrar_
->sync_thread()->message_loop(),
121 extensions_activity_monitor_
.GetExtensionsActivity(),
124 network_resources
->GetHttpPostProviderFactory(
125 make_scoped_refptr(profile_
->GetRequestContext()),
126 NetworkTimeTracker::BuildNotifierUpdateCallback(),
127 core_
->GetRequestContextCancelationSignal()),
129 invalidator_
->GetInvalidatorClientId(),
130 sync_manager_factory
.Pass(),
131 delete_sync_data_folder
,
132 sync_prefs_
->GetEncryptionBootstrapToken(),
133 sync_prefs_
->GetKeystoreEncryptionBootstrapToken(),
134 scoped_ptr
<InternalComponentsFactory
>(
135 new syncer::InternalComponentsFactoryImpl(factory_switches
)).Pass(),
136 unrecoverable_error_handler
.Pass(),
137 report_unrecoverable_error_function
));
138 InitCore(init_opts
.Pass());
141 void SyncBackendHostImpl::UpdateCredentials(
142 const syncer::SyncCredentials
& credentials
) {
143 DCHECK(registrar_
->sync_thread()->IsRunning());
144 registrar_
->sync_thread()->message_loop()->PostTask(FROM_HERE
,
145 base::Bind(&SyncBackendHostCore::DoUpdateCredentials
,
150 void SyncBackendHostImpl::StartSyncingWithServer() {
151 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called.";
153 syncer::ModelSafeRoutingInfo routing_info
;
154 registrar_
->GetModelSafeRoutingInfo(&routing_info
);
156 registrar_
->sync_thread()->message_loop()->PostTask(FROM_HERE
,
157 base::Bind(&SyncBackendHostCore::DoStartSyncing
,
158 core_
.get(), routing_info
));
161 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string
& passphrase
,
163 DCHECK(registrar_
->sync_thread()->IsRunning());
164 if (!IsNigoriEnabled()) {
165 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori"
170 // We should never be called with an empty passphrase.
171 DCHECK(!passphrase
.empty());
173 // This should only be called by the frontend.
174 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
176 // SetEncryptionPassphrase should never be called if we are currently
177 // encrypted with an explicit passphrase.
178 DCHECK(cached_passphrase_type_
== syncer::KEYSTORE_PASSPHRASE
||
179 cached_passphrase_type_
== syncer::IMPLICIT_PASSPHRASE
);
181 // Post an encryption task on the syncer thread.
182 registrar_
->sync_thread()->message_loop()->PostTask(FROM_HERE
,
183 base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase
,
185 passphrase
, is_explicit
));
188 bool SyncBackendHostImpl::SetDecryptionPassphrase(
189 const std::string
& passphrase
) {
190 if (!IsNigoriEnabled()) {
191 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori"
196 // We should never be called with an empty passphrase.
197 DCHECK(!passphrase
.empty());
199 // This should only be called by the frontend.
200 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
202 // This should only be called when we have cached pending keys.
203 DCHECK(cached_pending_keys_
.has_blob());
205 // Check the passphrase that was provided against our local cache of the
206 // cryptographer's pending keys. If this was unsuccessful, the UI layer can
207 // immediately call OnPassphraseRequired without showing the user a spinner.
208 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase
))
211 // Post a decryption task on the syncer thread.
212 registrar_
->sync_thread()->message_loop()->PostTask(FROM_HERE
,
213 base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase
,
217 // Since we were able to decrypt the cached pending keys with the passphrase
218 // provided, we immediately alert the UI layer that the passphrase was
219 // accepted. This will avoid the situation where a user enters a passphrase,
220 // clicks OK, immediately reopens the advanced settings dialog, and gets an
221 // unnecessary prompt for a passphrase.
222 // Note: It is not guaranteed that the passphrase will be accepted by the
223 // syncer thread, since we could receive a new nigori node while the task is
224 // pending. This scenario is a valid race, and SetDecryptionPassphrase can
225 // trigger a new OnPassphraseRequired if it needs to.
226 NotifyPassphraseAccepted();
230 void SyncBackendHostImpl::StopSyncingForShutdown() {
231 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
233 // Immediately stop sending messages to the frontend.
236 // Stop listening for and forwarding locally-triggered sync refresh requests.
237 notification_registrar_
.RemoveAll();
239 // Stop non-blocking sync types from sending any more requests to the syncer.
240 sync_core_proxy_
.reset();
242 DCHECK(registrar_
->sync_thread()->IsRunning());
244 registrar_
->RequestWorkerStopOnUIThread();
246 core_
->ShutdownOnUIThread();
249 scoped_ptr
<base::Thread
> SyncBackendHostImpl::Shutdown(ShutdownOption option
) {
250 // StopSyncingForShutdown() (which nulls out |frontend_|) should be
253 DCHECK(registrar_
->sync_thread()->IsRunning());
255 bool sync_disabled
= (option
== DISABLE_AND_CLAIM_THREAD
);
256 bool sync_thread_claimed
=
257 (option
== DISABLE_AND_CLAIM_THREAD
|| option
== STOP_AND_CLAIM_THREAD
);
259 if (invalidation_handler_registered_
) {
261 UnregisterInvalidationIds();
263 invalidator_
->UnregisterInvalidationHandler(this);
266 invalidation_handler_registered_
= false;
268 // Shut down and destroy sync manager.
269 registrar_
->sync_thread()->message_loop()->PostTask(
271 base::Bind(&SyncBackendHostCore::DoShutdown
,
272 core_
.get(), sync_disabled
));
276 SyncBackendRegistrar
* detached_registrar
= registrar_
.release();
277 detached_registrar
->sync_thread()->message_loop()->PostTask(
279 base::Bind(&SyncBackendRegistrar::Shutdown
,
280 base::Unretained(detached_registrar
)));
282 if (sync_thread_claimed
)
283 return detached_registrar
->ReleaseSyncThread();
285 return scoped_ptr
<base::Thread
>();
288 void SyncBackendHostImpl::UnregisterInvalidationIds() {
289 if (invalidation_handler_registered_
) {
290 invalidator_
->UpdateRegisteredInvalidationIds(
292 syncer::ObjectIdSet());
296 void SyncBackendHostImpl::ConfigureDataTypes(
297 syncer::ConfigureReason reason
,
298 const DataTypeConfigStateMap
& config_state_map
,
299 const base::Callback
<void(syncer::ModelTypeSet
,
300 syncer::ModelTypeSet
)>& ready_task
,
301 const base::Callback
<void()>& retry_callback
) {
302 // Only one configure is allowed at a time. This is guaranteed by our
303 // callers. The SyncBackendHostImpl requests one configure as the backend is
304 // initializing and waits for it to complete. After initialization, all
305 // configurations will pass through the DataTypeManager, which is careful to
306 // never send a new configure request until the current request succeeds.
308 // The SyncBackendRegistrar's routing info will be updated by adding the
309 // types_to_add to the list then removing types_to_remove. Any types which
310 // are not in either of those sets will remain untouched.
312 // Types which were not in the list previously are not fully downloaded, so we
313 // must ask the syncer to download them. Any newly supported datatypes will
314 // not have been in that routing info list, so they will be among the types
315 // downloaded if they are enabled.
317 // The SyncBackendRegistrar's state was initially derived from the types
318 // detected to have been downloaded in the database. Afterwards it is
319 // modified only by this function. We expect it to remain in sync with the
320 // backend because configuration requests are never aborted; they are retried
321 // until they succeed or the backend is shut down.
323 syncer::ModelTypeSet previous_types
= registrar_
->GetLastConfiguredTypes();
325 syncer::ModelTypeSet disabled_types
=
326 GetDataTypesInState(DISABLED
, config_state_map
);
327 syncer::ModelTypeSet fatal_types
=
328 GetDataTypesInState(FATAL
, config_state_map
);
329 syncer::ModelTypeSet crypto_types
=
330 GetDataTypesInState(CRYPTO
, config_state_map
);
331 disabled_types
.PutAll(fatal_types
);
332 disabled_types
.PutAll(crypto_types
);
333 syncer::ModelTypeSet active_types
=
334 GetDataTypesInState(CONFIGURE_ACTIVE
, config_state_map
);
335 syncer::ModelTypeSet clean_first_types
=
336 GetDataTypesInState(CONFIGURE_CLEAN
, config_state_map
);
337 syncer::ModelTypeSet types_to_download
= registrar_
->ConfigureDataTypes(
338 syncer::Union(active_types
, clean_first_types
),
340 types_to_download
.PutAll(clean_first_types
);
341 types_to_download
.RemoveAll(syncer::ProxyTypes());
342 if (!types_to_download
.Empty())
343 types_to_download
.Put(syncer::NIGORI
);
345 // TODO(sync): crbug.com/137550.
346 // It's dangerous to configure types that have progress markers. Types with
347 // progress markers can trigger a MIGRATION_DONE response. We are not
348 // prepared to handle a migration during a configure, so we must ensure that
349 // all our types_to_download actually contain no data before we sync them.
351 // One common way to end up in this situation used to be types which
352 // downloaded some or all of their data but have not applied it yet. We avoid
353 // problems with those types by purging the data of any such partially synced
354 // types soon after we load the directory.
356 // Another possible scenario is that we have newly supported or newly enabled
357 // data types being downloaded here but the nigori type, which is always
358 // included in any GetUpdates request, requires migration. The server has
359 // code to detect this scenario based on the configure reason, the fact that
360 // the nigori type is the only requested type which requires migration, and
361 // that the requested types list includes at least one non-nigori type. It
362 // will not send a MIGRATION_DONE response in that case. We still need to be
363 // careful to not send progress markers for non-nigori types, though. If a
364 // non-nigori type in the request requires migration, a MIGRATION_DONE
365 // response will be sent.
367 syncer::ModelSafeRoutingInfo routing_info
;
368 registrar_
->GetModelSafeRoutingInfo(&routing_info
);
370 syncer::ModelTypeSet current_types
= registrar_
->GetLastConfiguredTypes();
371 syncer::ModelTypeSet types_to_purge
=
372 syncer::Difference(previous_types
, current_types
);
373 syncer::ModelTypeSet inactive_types
=
374 GetDataTypesInState(CONFIGURE_INACTIVE
, config_state_map
);
375 types_to_purge
.RemoveAll(inactive_types
);
377 // If a type has already been disabled and unapplied or journaled, it will
378 // not be part of the |types_to_purge| set, and therefore does not need
379 // to be acted on again.
380 fatal_types
.RetainAll(types_to_purge
);
381 syncer::ModelTypeSet unapply_types
=
382 syncer::Union(crypto_types
, clean_first_types
);
383 unapply_types
.RetainAll(types_to_purge
);
385 DCHECK(syncer::Intersection(current_types
, fatal_types
).Empty());
386 DCHECK(syncer::Intersection(current_types
, crypto_types
).Empty());
387 DCHECK(current_types
.HasAll(types_to_download
));
389 SDVLOG(1) << "Types "
390 << syncer::ModelTypeSetToString(types_to_download
)
391 << " added; calling DoConfigureSyncer";
392 // Divide up the types into their corresponding actions (each is mutually
394 // - Types which have just been added to the routing info (types_to_download):
396 // - Types which have encountered a fatal error (fatal_types) are deleted
397 // from the directory and journaled in the delete journal.
398 // - Types which have encountered a cryptographer error (crypto_types) are
399 // unapplied (local state is purged but sync state is not).
400 // - All other types not in the routing info (types just disabled) are deleted
401 // from the directory.
402 // - Everything else (enabled types and already disabled types) is not
404 RequestConfigureSyncer(reason
,
415 void SyncBackendHostImpl::EnableEncryptEverything() {
416 registrar_
->sync_thread()->message_loop()->PostTask(FROM_HERE
,
417 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything
,
421 void SyncBackendHostImpl::ActivateDataType(
422 syncer::ModelType type
, syncer::ModelSafeGroup group
,
423 ChangeProcessor
* change_processor
) {
424 registrar_
->ActivateDataType(type
, group
, change_processor
, GetUserShare());
427 void SyncBackendHostImpl::DeactivateDataType(syncer::ModelType type
) {
428 registrar_
->DeactivateDataType(type
);
431 syncer::UserShare
* SyncBackendHostImpl::GetUserShare() const {
432 return core_
->sync_manager()->GetUserShare();
435 scoped_ptr
<syncer::SyncCoreProxy
> SyncBackendHostImpl::GetSyncCoreProxy() {
436 return scoped_ptr
<syncer::SyncCoreProxy
>(sync_core_proxy_
->Clone());
439 SyncBackendHostImpl::Status
SyncBackendHostImpl::GetDetailedStatus() {
440 DCHECK(initialized());
441 return core_
->sync_manager()->GetDetailedStatus();
444 syncer::sessions::SyncSessionSnapshot
445 SyncBackendHostImpl::GetLastSessionSnapshot() const {
446 return last_snapshot_
;
449 bool SyncBackendHostImpl::HasUnsyncedItems() const {
450 DCHECK(initialized());
451 return core_
->sync_manager()->HasUnsyncedItems();
454 bool SyncBackendHostImpl::IsNigoriEnabled() const {
455 return registrar_
.get() && registrar_
->IsNigoriEnabled();
458 syncer::PassphraseType
SyncBackendHostImpl::GetPassphraseType() const {
459 return cached_passphrase_type_
;
462 base::Time
SyncBackendHostImpl::GetExplicitPassphraseTime() const {
463 return cached_explicit_passphrase_time_
;
466 bool SyncBackendHostImpl::IsCryptographerReady(
467 const syncer::BaseTransaction
* trans
) const {
468 return initialized() && trans
->GetCryptographer()->is_ready();
471 void SyncBackendHostImpl::GetModelSafeRoutingInfo(
472 syncer::ModelSafeRoutingInfo
* out
) const {
474 CHECK(registrar_
.get());
475 registrar_
->GetModelSafeRoutingInfo(out
);
481 SyncedDeviceTracker
* SyncBackendHostImpl::GetSyncedDeviceTracker() const {
484 return core_
->synced_device_tracker();
487 void SyncBackendHostImpl::RequestBufferedProtocolEventsAndEnableForwarding() {
488 registrar_
->sync_thread()->message_loop()->PostTask(
491 &SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding
,
495 void SyncBackendHostImpl::DisableProtocolEventForwarding() {
496 registrar_
->sync_thread()->message_loop()->PostTask(
499 &SyncBackendHostCore::DisableProtocolEventForwarding
,
503 void SyncBackendHostImpl::GetAllNodesForTypes(
504 syncer::ModelTypeSet types
,
505 base::Callback
<void(const std::vector
<syncer::ModelType
>&,
506 ScopedVector
<base::ListValue
>)> callback
) {
507 DCHECK(initialized());
508 registrar_
->sync_thread()->message_loop()->PostTask(FROM_HERE
,
510 &SyncBackendHostCore::GetAllNodesForTypes
,
513 frontend_loop_
->message_loop_proxy(),
517 void SyncBackendHostImpl::InitCore(scoped_ptr
<DoInitializeOptions
> options
) {
518 registrar_
->sync_thread()->message_loop()->PostTask(FROM_HERE
,
519 base::Bind(&SyncBackendHostCore::DoInitialize
,
520 core_
.get(), base::Passed(&options
)));
523 void SyncBackendHostImpl::RequestConfigureSyncer(
524 syncer::ConfigureReason reason
,
525 syncer::ModelTypeSet to_download
,
526 syncer::ModelTypeSet to_purge
,
527 syncer::ModelTypeSet to_journal
,
528 syncer::ModelTypeSet to_unapply
,
529 syncer::ModelTypeSet to_ignore
,
530 const syncer::ModelSafeRoutingInfo
& routing_info
,
531 const base::Callback
<void(syncer::ModelTypeSet
,
532 syncer::ModelTypeSet
)>& ready_task
,
533 const base::Closure
& retry_callback
) {
534 DoConfigureSyncerTypes config_types
;
535 config_types
.to_download
= to_download
;
536 config_types
.to_purge
= to_purge
;
537 config_types
.to_journal
= to_journal
;
538 config_types
.to_unapply
= to_unapply
;
539 registrar_
->sync_thread()->message_loop()->PostTask(FROM_HERE
,
540 base::Bind(&SyncBackendHostCore::DoConfigureSyncer
,
549 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop(
550 const syncer::ModelTypeSet enabled_types
,
551 const syncer::ModelTypeSet succeeded_configuration_types
,
552 const syncer::ModelTypeSet failed_configuration_types
,
553 const base::Callback
<void(syncer::ModelTypeSet
,
554 syncer::ModelTypeSet
)>& ready_task
) {
558 invalidator_
->UpdateRegisteredInvalidationIds(
560 ModelTypeSetToObjectIdSet(enabled_types
));
562 if (!ready_task
.is_null())
563 ready_task
.Run(succeeded_configuration_types
, failed_configuration_types
);
566 void SyncBackendHostImpl::Observe(
568 const content::NotificationSource
& source
,
569 const content::NotificationDetails
& details
) {
570 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
571 DCHECK_EQ(type
, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL
);
573 content::Details
<const syncer::ModelTypeSet
> state_details(details
);
574 const syncer::ModelTypeSet
& types
= *(state_details
.ptr());
575 registrar_
->sync_thread()->message_loop()->PostTask(FROM_HERE
,
576 base::Bind(&SyncBackendHostCore::DoRefreshTypes
, core_
.get(), types
));
579 void SyncBackendHostImpl::AddExperimentalTypes() {
580 CHECK(initialized());
581 syncer::Experiments experiments
;
582 if (core_
->sync_manager()->ReceivedExperiment(&experiments
))
583 frontend_
->OnExperimentsChanged(experiments
);
586 void SyncBackendHostImpl::HandleControlTypesDownloadRetry() {
587 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
591 frontend_
->OnSyncConfigureRetry();
594 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop(
595 const syncer::WeakHandle
<syncer::JsBackend
> js_backend
,
596 const syncer::WeakHandle
<syncer::DataTypeDebugInfoListener
>
598 syncer::SyncCoreProxy
* sync_core_proxy
) {
599 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
601 sync_core_proxy_
= sync_core_proxy
->Clone();
608 invalidator_
->RegisterInvalidationHandler(this);
609 invalidation_handler_registered_
= true;
611 // Fake a state change to initialize the SyncManager's cached invalidator
613 OnInvalidatorStateChange(invalidator_
->GetInvalidatorState());
615 // Start forwarding refresh requests to the SyncManager
616 notification_registrar_
.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL
,
617 content::Source
<Profile
>(profile_
));
619 // Now that we've downloaded the control types, we can see if there are any
620 // experimental types to enable. This should be done before we inform
621 // the frontend to ensure they're visible in the customize screen.
622 AddExperimentalTypes();
623 frontend_
->OnBackendInitialized(js_backend
,
628 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() {
629 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
633 frontend_
->OnBackendInitialized(
634 syncer::WeakHandle
<syncer::JsBackend
>(),
635 syncer::WeakHandle
<syncer::DataTypeDebugInfoListener
>(),
639 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop(
640 const syncer::sessions::SyncSessionSnapshot
& snapshot
) {
643 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
645 last_snapshot_
= snapshot
;
647 SDVLOG(1) << "Got snapshot " << snapshot
.ToString();
649 // Process any changes to the datatypes we're syncing.
650 // TODO(sync): add support for removing types.
652 AddExperimentalTypes();
655 frontend_
->OnSyncCycleCompleted();
658 void SyncBackendHostImpl::RetryConfigurationOnFrontendLoop(
659 const base::Closure
& retry_callback
) {
660 SDVLOG(1) << "Failed to complete configuration, informing of retry.";
661 retry_callback
.Run();
664 void SyncBackendHostImpl::PersistEncryptionBootstrapToken(
665 const std::string
& token
,
666 syncer::BootstrapTokenType token_type
) {
667 CHECK(sync_prefs_
.get());
668 DCHECK(!token
.empty());
669 if (token_type
== syncer::PASSPHRASE_BOOTSTRAP_TOKEN
)
670 sync_prefs_
->SetEncryptionBootstrapToken(token
);
672 sync_prefs_
->SetKeystoreEncryptionBootstrapToken(token
);
675 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop(
676 const syncer::SyncProtocolError
& sync_error
) {
679 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
680 frontend_
->OnActionableError(sync_error
);
683 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop(
684 syncer::ModelTypeSet types
) {
687 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
688 frontend_
->OnMigrationNeededForTypes(types
);
691 void SyncBackendHostImpl::OnInvalidatorStateChange(
692 syncer::InvalidatorState state
) {
693 registrar_
->sync_thread()->message_loop()->PostTask(
695 base::Bind(&SyncBackendHostCore::DoOnInvalidatorStateChange
,
700 void SyncBackendHostImpl::OnIncomingInvalidation(
701 const syncer::ObjectIdInvalidationMap
& invalidation_map
) {
702 registrar_
->sync_thread()->message_loop()->PostTask(
704 base::Bind(&SyncBackendHostCore::DoOnIncomingInvalidation
,
709 std::string
SyncBackendHostImpl::GetOwnerName() const {
710 return "SyncBackendHostImpl";
713 bool SyncBackendHostImpl::CheckPassphraseAgainstCachedPendingKeys(
714 const std::string
& passphrase
) const {
715 DCHECK(cached_pending_keys_
.has_blob());
716 DCHECK(!passphrase
.empty());
717 syncer::Nigori nigori
;
718 nigori
.InitByDerivation("localhost", "dummy", passphrase
);
719 std::string plaintext
;
720 bool result
= nigori
.Decrypt(cached_pending_keys_
.blob(), &plaintext
);
721 DVLOG_IF(1, result
) << "Passphrase failed to decrypt pending keys.";
725 void SyncBackendHostImpl::NotifyPassphraseRequired(
726 syncer::PassphraseRequiredReason reason
,
727 sync_pb::EncryptedData pending_keys
) {
731 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
733 // Update our cache of the cryptographer's pending keys.
734 cached_pending_keys_
= pending_keys
;
736 frontend_
->OnPassphraseRequired(reason
, pending_keys
);
739 void SyncBackendHostImpl::NotifyPassphraseAccepted() {
743 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
745 // Clear our cache of the cryptographer's pending keys.
746 cached_pending_keys_
.clear_blob();
747 frontend_
->OnPassphraseAccepted();
750 void SyncBackendHostImpl::NotifyEncryptedTypesChanged(
751 syncer::ModelTypeSet encrypted_types
,
752 bool encrypt_everything
) {
756 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
757 frontend_
->OnEncryptedTypesChanged(
758 encrypted_types
, encrypt_everything
);
761 void SyncBackendHostImpl::NotifyEncryptionComplete() {
765 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
766 frontend_
->OnEncryptionComplete();
769 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop(
770 syncer::PassphraseType type
,
771 base::Time explicit_passphrase_time
) {
772 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
773 DVLOG(1) << "Passphrase type changed to "
774 << syncer::PassphraseTypeToString(type
);
775 cached_passphrase_type_
= type
;
776 cached_explicit_passphrase_time_
= explicit_passphrase_time
;
779 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop(
780 syncer::ConnectionStatus status
) {
784 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_
);
786 DVLOG(1) << "Connection status changed: "
787 << syncer::ConnectionStatusToString(status
);
788 frontend_
->OnConnectionStatusChange(status
);
791 void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop(
792 syncer::ProtocolEvent
* event
) {
793 scoped_ptr
<syncer::ProtocolEvent
> scoped_event(event
);
796 frontend_
->OnProtocolEvent(*scoped_event
);
799 base::MessageLoop
* SyncBackendHostImpl::GetSyncLoopForTesting() {
800 return registrar_
->sync_thread()->message_loop();
803 } // namespace browser_sync