[sql] Remove _HAS_EXCEPTIONS=0 from build info.
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_host_impl.cc
blobb5db3d09c35294195b0826f73bcc8c73fe100c92
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 std::map<syncer::ModelType, int64> invalidation_versions;
145 sync_prefs_->GetInvalidationVersions(&invalidation_versions);
147 scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions(
148 registrar_->sync_thread()->message_loop(), registrar_.get(), routing_info,
149 workers, extensions_activity_monitor_.GetExtensionsActivity(),
150 event_handler, sync_service_url,
151 network_resources->GetHttpPostProviderFactory(
152 make_scoped_refptr(profile_->GetRequestContext()),
153 base::Bind(&UpdateNetworkTime),
154 core_->GetRequestContextCancelationSignal()),
155 credentials, invalidator_ ? invalidator_->GetInvalidatorClientId() : "",
156 sync_manager_factory.Pass(), delete_sync_data_folder,
157 sync_prefs_->GetEncryptionBootstrapToken(),
158 sync_prefs_->GetKeystoreEncryptionBootstrapToken(),
159 scoped_ptr<InternalComponentsFactory>(
160 new syncer::InternalComponentsFactoryImpl(factory_switches))
161 .Pass(),
162 unrecoverable_error_handler.Pass(), report_unrecoverable_error_function,
163 saved_nigori_state.Pass(), clear_data_option, invalidation_versions));
164 InitCore(init_opts.Pass());
167 void SyncBackendHostImpl::UpdateCredentials(
168 const syncer::SyncCredentials& credentials) {
169 DCHECK(registrar_->sync_thread()->IsRunning());
170 registrar_->sync_thread()->task_runner()->PostTask(
171 FROM_HERE, base::Bind(&SyncBackendHostCore::DoUpdateCredentials,
172 core_.get(), credentials));
175 void SyncBackendHostImpl::StartSyncingWithServer() {
176 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called.";
178 syncer::ModelSafeRoutingInfo routing_info;
179 registrar_->GetModelSafeRoutingInfo(&routing_info);
181 registrar_->sync_thread()->task_runner()->PostTask(
182 FROM_HERE, base::Bind(&SyncBackendHostCore::DoStartSyncing, core_.get(),
183 routing_info, sync_prefs_->GetLastPollTime()));
186 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase,
187 bool is_explicit) {
188 DCHECK(registrar_->sync_thread()->IsRunning());
189 if (!IsNigoriEnabled()) {
190 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori"
191 " is disabled.";
192 return;
195 // We should never be called with an empty passphrase.
196 DCHECK(!passphrase.empty());
198 // This should only be called by the frontend.
199 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
201 // SetEncryptionPassphrase should never be called if we are currently
202 // encrypted with an explicit passphrase.
203 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE ||
204 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE);
206 // Post an encryption task on the syncer thread.
207 registrar_->sync_thread()->task_runner()->PostTask(
208 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase,
209 core_.get(), passphrase, is_explicit));
212 bool SyncBackendHostImpl::SetDecryptionPassphrase(
213 const std::string& passphrase) {
214 if (!IsNigoriEnabled()) {
215 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori"
216 " is disabled.";
217 return false;
220 // We should never be called with an empty passphrase.
221 DCHECK(!passphrase.empty());
223 // This should only be called by the frontend.
224 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
226 // This should only be called when we have cached pending keys.
227 DCHECK(cached_pending_keys_.has_blob());
229 // Check the passphrase that was provided against our local cache of the
230 // cryptographer's pending keys. If this was unsuccessful, the UI layer can
231 // immediately call OnPassphraseRequired without showing the user a spinner.
232 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase))
233 return false;
235 // Post a decryption task on the syncer thread.
236 registrar_->sync_thread()->task_runner()->PostTask(
237 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase,
238 core_.get(), passphrase));
240 // Since we were able to decrypt the cached pending keys with the passphrase
241 // provided, we immediately alert the UI layer that the passphrase was
242 // accepted. This will avoid the situation where a user enters a passphrase,
243 // clicks OK, immediately reopens the advanced settings dialog, and gets an
244 // unnecessary prompt for a passphrase.
245 // Note: It is not guaranteed that the passphrase will be accepted by the
246 // syncer thread, since we could receive a new nigori node while the task is
247 // pending. This scenario is a valid race, and SetDecryptionPassphrase can
248 // trigger a new OnPassphraseRequired if it needs to.
249 NotifyPassphraseAccepted();
250 return true;
253 void SyncBackendHostImpl::StopSyncingForShutdown() {
254 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
256 // Immediately stop sending messages to the frontend.
257 frontend_ = NULL;
259 // Stop listening for and forwarding locally-triggered sync refresh requests.
260 notification_registrar_.RemoveAll();
262 // Stop non-blocking sync types from sending any more requests to the syncer.
263 sync_context_proxy_.reset();
265 DCHECK(registrar_->sync_thread()->IsRunning());
267 registrar_->RequestWorkerStopOnUIThread();
269 core_->ShutdownOnUIThread();
272 scoped_ptr<base::Thread> SyncBackendHostImpl::Shutdown(
273 syncer::ShutdownReason reason) {
274 // StopSyncingForShutdown() (which nulls out |frontend_|) should be
275 // called first.
276 DCHECK(!frontend_);
277 DCHECK(registrar_->sync_thread()->IsRunning());
279 bool sync_thread_claimed = (reason != syncer::BROWSER_SHUTDOWN);
281 if (invalidation_handler_registered_) {
282 if (reason == syncer::DISABLE_SYNC) {
283 UnregisterInvalidationIds();
285 invalidator_->UnregisterInvalidationHandler(this);
286 invalidator_ = NULL;
288 invalidation_handler_registered_ = false;
290 // Shut down and destroy sync manager.
291 registrar_->sync_thread()->task_runner()->PostTask(
292 FROM_HERE,
293 base::Bind(&SyncBackendHostCore::DoShutdown, core_.get(), reason));
294 core_ = NULL;
296 // Worker cleanup.
297 SyncBackendRegistrar* detached_registrar = registrar_.release();
298 detached_registrar->sync_thread()->task_runner()->PostTask(
299 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
300 base::Unretained(detached_registrar)));
302 if (sync_thread_claimed)
303 return detached_registrar->ReleaseSyncThread();
304 else
305 return scoped_ptr<base::Thread>();
308 void SyncBackendHostImpl::UnregisterInvalidationIds() {
309 if (invalidation_handler_registered_) {
310 CHECK(invalidator_->UpdateRegisteredInvalidationIds(this,
311 syncer::ObjectIdSet()));
315 syncer::ModelTypeSet SyncBackendHostImpl::ConfigureDataTypes(
316 syncer::ConfigureReason reason,
317 const DataTypeConfigStateMap& config_state_map,
318 const base::Callback<void(syncer::ModelTypeSet, syncer::ModelTypeSet)>&
319 ready_task,
320 const base::Callback<void()>& retry_callback) {
321 // Only one configure is allowed at a time. This is guaranteed by our
322 // callers. The SyncBackendHostImpl requests one configure as the backend is
323 // initializing and waits for it to complete. After initialization, all
324 // configurations will pass through the DataTypeManager, which is careful to
325 // never send a new configure request until the current request succeeds.
327 // The SyncBackendRegistrar's routing info will be updated by adding the
328 // types_to_add to the list then removing types_to_remove. Any types which
329 // are not in either of those sets will remain untouched.
331 // Types which were not in the list previously are not fully downloaded, so we
332 // must ask the syncer to download them. Any newly supported datatypes will
333 // not have been in that routing info list, so they will be among the types
334 // downloaded if they are enabled.
336 // The SyncBackendRegistrar's state was initially derived from the types
337 // detected to have been downloaded in the database. Afterwards it is
338 // modified only by this function. We expect it to remain in sync with the
339 // backend because configuration requests are never aborted; they are retried
340 // until they succeed or the backend is shut down.
342 syncer::ModelTypeSet disabled_types =
343 GetDataTypesInState(DISABLED, config_state_map);
344 syncer::ModelTypeSet fatal_types =
345 GetDataTypesInState(FATAL, config_state_map);
346 syncer::ModelTypeSet crypto_types =
347 GetDataTypesInState(CRYPTO, config_state_map);
348 syncer::ModelTypeSet unready_types =
349 GetDataTypesInState(UNREADY, config_state_map);
351 disabled_types.PutAll(fatal_types);
352 disabled_types.PutAll(crypto_types);
353 disabled_types.PutAll(unready_types);
355 syncer::ModelTypeSet active_types =
356 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
357 syncer::ModelTypeSet clean_first_types =
358 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
359 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes(
360 syncer::Union(active_types, clean_first_types),
361 disabled_types);
362 types_to_download.PutAll(clean_first_types);
363 types_to_download.RemoveAll(syncer::ProxyTypes());
364 if (!types_to_download.Empty())
365 types_to_download.Put(syncer::NIGORI);
367 // TODO(sync): crbug.com/137550.
368 // It's dangerous to configure types that have progress markers. Types with
369 // progress markers can trigger a MIGRATION_DONE response. We are not
370 // prepared to handle a migration during a configure, so we must ensure that
371 // all our types_to_download actually contain no data before we sync them.
373 // One common way to end up in this situation used to be types which
374 // downloaded some or all of their data but have not applied it yet. We avoid
375 // problems with those types by purging the data of any such partially synced
376 // types soon after we load the directory.
378 // Another possible scenario is that we have newly supported or newly enabled
379 // data types being downloaded here but the nigori type, which is always
380 // included in any GetUpdates request, requires migration. The server has
381 // code to detect this scenario based on the configure reason, the fact that
382 // the nigori type is the only requested type which requires migration, and
383 // that the requested types list includes at least one non-nigori type. It
384 // will not send a MIGRATION_DONE response in that case. We still need to be
385 // careful to not send progress markers for non-nigori types, though. If a
386 // non-nigori type in the request requires migration, a MIGRATION_DONE
387 // response will be sent.
389 syncer::ModelSafeRoutingInfo routing_info;
390 registrar_->GetModelSafeRoutingInfo(&routing_info);
392 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes();
393 syncer::ModelTypeSet types_to_purge =
394 syncer::Difference(syncer::ModelTypeSet::All(), current_types);
395 syncer::ModelTypeSet inactive_types =
396 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
397 types_to_purge.RemoveAll(inactive_types);
398 types_to_purge.RemoveAll(unready_types);
400 // If a type has already been disabled and unapplied or journaled, it will
401 // not be part of the |types_to_purge| set, and therefore does not need
402 // to be acted on again.
403 fatal_types.RetainAll(types_to_purge);
404 syncer::ModelTypeSet unapply_types =
405 syncer::Union(crypto_types, clean_first_types);
406 unapply_types.RetainAll(types_to_purge);
408 DCHECK(syncer::Intersection(current_types, fatal_types).Empty());
409 DCHECK(syncer::Intersection(current_types, crypto_types).Empty());
410 DCHECK(current_types.HasAll(types_to_download));
412 SDVLOG(1) << "Types "
413 << syncer::ModelTypeSetToString(types_to_download)
414 << " added; calling DoConfigureSyncer";
415 // Divide up the types into their corresponding actions (each is mutually
416 // exclusive):
417 // - Types which have just been added to the routing info (types_to_download):
418 // are downloaded.
419 // - Types which have encountered a fatal error (fatal_types) are deleted
420 // from the directory and journaled in the delete journal.
421 // - Types which have encountered a cryptographer error (crypto_types) are
422 // unapplied (local state is purged but sync state is not).
423 // - All other types not in the routing info (types just disabled) are deleted
424 // from the directory.
425 // - Everything else (enabled types and already disabled types) is not
426 // touched.
427 RequestConfigureSyncer(reason,
428 types_to_download,
429 types_to_purge,
430 fatal_types,
431 unapply_types,
432 inactive_types,
433 routing_info,
434 ready_task,
435 retry_callback);
437 DCHECK(syncer::Intersection(active_types, types_to_purge).Empty());
438 DCHECK(syncer::Intersection(active_types, fatal_types).Empty());
439 DCHECK(syncer::Intersection(active_types, unapply_types).Empty());
440 DCHECK(syncer::Intersection(active_types, inactive_types).Empty());
441 return syncer::Difference(active_types, types_to_download);
444 void SyncBackendHostImpl::EnableEncryptEverything() {
445 registrar_->sync_thread()->task_runner()->PostTask(
446 FROM_HERE,
447 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything, core_.get()));
450 void SyncBackendHostImpl::ActivateDataType(
451 syncer::ModelType type, syncer::ModelSafeGroup group,
452 sync_driver::ChangeProcessor* change_processor) {
453 registrar_->ActivateDataType(type, group, change_processor, GetUserShare());
456 void SyncBackendHostImpl::DeactivateDataType(syncer::ModelType type) {
457 registrar_->DeactivateDataType(type);
460 syncer::UserShare* SyncBackendHostImpl::GetUserShare() const {
461 return core_->sync_manager()->GetUserShare();
464 scoped_ptr<syncer_v2::SyncContextProxy>
465 SyncBackendHostImpl::GetSyncContextProxy() {
466 return sync_context_proxy_.get() ? scoped_ptr<syncer_v2::SyncContextProxy>(
467 sync_context_proxy_->Clone())
468 : scoped_ptr<syncer_v2::SyncContextProxy>();
471 SyncBackendHostImpl::Status SyncBackendHostImpl::GetDetailedStatus() {
472 DCHECK(initialized());
473 return core_->sync_manager()->GetDetailedStatus();
476 syncer::sessions::SyncSessionSnapshot
477 SyncBackendHostImpl::GetLastSessionSnapshot() const {
478 return last_snapshot_;
481 bool SyncBackendHostImpl::HasUnsyncedItems() const {
482 DCHECK(initialized());
483 return core_->sync_manager()->HasUnsyncedItems();
486 bool SyncBackendHostImpl::IsNigoriEnabled() const {
487 return registrar_.get() && registrar_->IsNigoriEnabled();
490 syncer::PassphraseType SyncBackendHostImpl::GetPassphraseType() const {
491 return cached_passphrase_type_;
494 base::Time SyncBackendHostImpl::GetExplicitPassphraseTime() const {
495 return cached_explicit_passphrase_time_;
498 bool SyncBackendHostImpl::IsCryptographerReady(
499 const syncer::BaseTransaction* trans) const {
500 return initialized() && trans->GetCryptographer() &&
501 trans->GetCryptographer()->is_ready();
504 void SyncBackendHostImpl::GetModelSafeRoutingInfo(
505 syncer::ModelSafeRoutingInfo* out) const {
506 if (initialized()) {
507 CHECK(registrar_.get());
508 registrar_->GetModelSafeRoutingInfo(out);
509 } else {
510 NOTREACHED();
514 void SyncBackendHostImpl::FlushDirectory() const {
515 DCHECK(initialized());
516 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
517 base::Bind(&SyncBackendHostCore::SaveChanges, core_));
520 void SyncBackendHostImpl::RequestBufferedProtocolEventsAndEnableForwarding() {
521 registrar_->sync_thread()->task_runner()->PostTask(
522 FROM_HERE,
523 base::Bind(
524 &SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding,
525 core_));
528 void SyncBackendHostImpl::DisableProtocolEventForwarding() {
529 registrar_->sync_thread()->task_runner()->PostTask(
530 FROM_HERE,
531 base::Bind(&SyncBackendHostCore::DisableProtocolEventForwarding, core_));
534 void SyncBackendHostImpl::EnableDirectoryTypeDebugInfoForwarding() {
535 DCHECK(initialized());
536 registrar_->sync_thread()->task_runner()->PostTask(
537 FROM_HERE,
538 base::Bind(&SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding,
539 core_));
542 void SyncBackendHostImpl::DisableDirectoryTypeDebugInfoForwarding() {
543 DCHECK(initialized());
544 registrar_->sync_thread()->task_runner()->PostTask(
545 FROM_HERE,
546 base::Bind(&SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding,
547 core_));
550 void SyncBackendHostImpl::GetAllNodesForTypes(
551 syncer::ModelTypeSet types,
552 base::Callback<void(const std::vector<syncer::ModelType>&,
553 ScopedVector<base::ListValue>)> callback) {
554 DCHECK(initialized());
555 registrar_->sync_thread()->task_runner()->PostTask(
556 FROM_HERE, base::Bind(&SyncBackendHostCore::GetAllNodesForTypes, core_,
557 types, frontend_loop_->task_runner(), callback));
560 void SyncBackendHostImpl::InitCore(scoped_ptr<DoInitializeOptions> options) {
561 registrar_->sync_thread()->task_runner()->PostTask(
562 FROM_HERE, base::Bind(&SyncBackendHostCore::DoInitialize, core_.get(),
563 base::Passed(&options)));
566 void SyncBackendHostImpl::RequestConfigureSyncer(
567 syncer::ConfigureReason reason,
568 syncer::ModelTypeSet to_download,
569 syncer::ModelTypeSet to_purge,
570 syncer::ModelTypeSet to_journal,
571 syncer::ModelTypeSet to_unapply,
572 syncer::ModelTypeSet to_ignore,
573 const syncer::ModelSafeRoutingInfo& routing_info,
574 const base::Callback<void(syncer::ModelTypeSet,
575 syncer::ModelTypeSet)>& ready_task,
576 const base::Closure& retry_callback) {
577 DoConfigureSyncerTypes config_types;
578 config_types.to_download = to_download;
579 config_types.to_purge = to_purge;
580 config_types.to_journal = to_journal;
581 config_types.to_unapply = to_unapply;
582 registrar_->sync_thread()->task_runner()->PostTask(
583 FROM_HERE,
584 base::Bind(&SyncBackendHostCore::DoConfigureSyncer, core_.get(), reason,
585 config_types, routing_info, ready_task, retry_callback));
588 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop(
589 const syncer::ModelTypeSet enabled_types,
590 const syncer::ModelTypeSet succeeded_configuration_types,
591 const syncer::ModelTypeSet failed_configuration_types,
592 const base::Callback<void(syncer::ModelTypeSet,
593 syncer::ModelTypeSet)>& ready_task) {
594 if (!frontend_)
595 return;
597 if (invalidator_) {
598 CHECK(invalidator_->UpdateRegisteredInvalidationIds(
599 this, ModelTypeSetToObjectIdSet(enabled_types)));
602 if (!ready_task.is_null())
603 ready_task.Run(succeeded_configuration_types, failed_configuration_types);
606 void SyncBackendHostImpl::Observe(
607 int type,
608 const content::NotificationSource& source,
609 const content::NotificationDetails& details) {
610 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
611 DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL);
613 content::Details<const syncer::ModelTypeSet> state_details(details);
614 const syncer::ModelTypeSet& types = *(state_details.ptr());
615 registrar_->sync_thread()->task_runner()->PostTask(
616 FROM_HERE,
617 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
620 void SyncBackendHostImpl::AddExperimentalTypes() {
621 CHECK(initialized());
622 syncer::Experiments experiments;
623 if (core_->sync_manager()->ReceivedExperiment(&experiments))
624 frontend_->OnExperimentsChanged(experiments);
627 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop(
628 const syncer::WeakHandle<syncer::JsBackend> js_backend,
629 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>
630 debug_info_listener,
631 syncer_v2::SyncContextProxy* sync_context_proxy,
632 const std::string& cache_guid) {
633 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
635 if (sync_context_proxy)
636 sync_context_proxy_ = sync_context_proxy->Clone();
638 if (!frontend_)
639 return;
641 initialized_ = true;
643 if (invalidator_) {
644 invalidator_->RegisterInvalidationHandler(this);
645 invalidation_handler_registered_ = true;
647 // Fake a state change to initialize the SyncManager's cached invalidator
648 // state.
649 OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
652 // Start forwarding refresh requests to the SyncManager
653 notification_registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
654 content::Source<Profile>(profile_));
656 // Now that we've downloaded the control types, we can see if there are any
657 // experimental types to enable. This should be done before we inform
658 // the frontend to ensure they're visible in the customize screen.
659 AddExperimentalTypes();
660 frontend_->OnBackendInitialized(js_backend,
661 debug_info_listener,
662 cache_guid,
663 true);
666 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() {
667 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
668 if (!frontend_)
669 return;
671 frontend_->OnBackendInitialized(
672 syncer::WeakHandle<syncer::JsBackend>(),
673 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
675 false);
678 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop(
679 const syncer::sessions::SyncSessionSnapshot& snapshot) {
680 if (!frontend_)
681 return;
682 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
684 last_snapshot_ = snapshot;
686 SDVLOG(1) << "Got snapshot " << snapshot.ToString();
688 if (!snapshot.poll_finish_time().is_null())
689 sync_prefs_->SetLastPollTime(snapshot.poll_finish_time());
691 // Process any changes to the datatypes we're syncing.
692 // TODO(sync): add support for removing types.
693 if (initialized())
694 AddExperimentalTypes();
696 if (initialized())
697 frontend_->OnSyncCycleCompleted();
700 void SyncBackendHostImpl::RetryConfigurationOnFrontendLoop(
701 const base::Closure& retry_callback) {
702 SDVLOG(1) << "Failed to complete configuration, informing of retry.";
703 retry_callback.Run();
706 void SyncBackendHostImpl::PersistEncryptionBootstrapToken(
707 const std::string& token,
708 syncer::BootstrapTokenType token_type) {
709 CHECK(sync_prefs_.get());
710 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN)
711 sync_prefs_->SetEncryptionBootstrapToken(token);
712 else
713 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token);
716 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop(
717 const syncer::SyncProtocolError& sync_error) {
718 if (!frontend_)
719 return;
720 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
721 frontend_->OnActionableError(sync_error);
724 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop(
725 syncer::ModelTypeSet types) {
726 if (!frontend_)
727 return;
728 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
729 frontend_->OnMigrationNeededForTypes(types);
732 void SyncBackendHostImpl::OnInvalidatorStateChange(
733 syncer::InvalidatorState state) {
734 registrar_->sync_thread()->task_runner()->PostTask(
735 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnInvalidatorStateChange,
736 core_.get(), state));
739 void SyncBackendHostImpl::OnIncomingInvalidation(
740 const syncer::ObjectIdInvalidationMap& invalidation_map) {
741 registrar_->sync_thread()->task_runner()->PostTask(
742 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnIncomingInvalidation,
743 core_.get(), invalidation_map));
746 std::string SyncBackendHostImpl::GetOwnerName() const {
747 return "SyncBackendHostImpl";
750 bool SyncBackendHostImpl::CheckPassphraseAgainstCachedPendingKeys(
751 const std::string& passphrase) const {
752 DCHECK(cached_pending_keys_.has_blob());
753 DCHECK(!passphrase.empty());
754 syncer::Nigori nigori;
755 nigori.InitByDerivation("localhost", "dummy", passphrase);
756 std::string plaintext;
757 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext);
758 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys.";
759 return result;
762 void SyncBackendHostImpl::NotifyPassphraseRequired(
763 syncer::PassphraseRequiredReason reason,
764 sync_pb::EncryptedData pending_keys) {
765 if (!frontend_)
766 return;
768 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
770 // Update our cache of the cryptographer's pending keys.
771 cached_pending_keys_ = pending_keys;
773 frontend_->OnPassphraseRequired(reason, pending_keys);
776 void SyncBackendHostImpl::NotifyPassphraseAccepted() {
777 if (!frontend_)
778 return;
780 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
782 // Clear our cache of the cryptographer's pending keys.
783 cached_pending_keys_.clear_blob();
784 frontend_->OnPassphraseAccepted();
787 void SyncBackendHostImpl::NotifyEncryptedTypesChanged(
788 syncer::ModelTypeSet encrypted_types,
789 bool encrypt_everything) {
790 if (!frontend_)
791 return;
793 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
794 frontend_->OnEncryptedTypesChanged(
795 encrypted_types, encrypt_everything);
798 void SyncBackendHostImpl::NotifyEncryptionComplete() {
799 if (!frontend_)
800 return;
802 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
803 frontend_->OnEncryptionComplete();
806 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop(
807 syncer::PassphraseType type,
808 base::Time explicit_passphrase_time) {
809 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
810 DVLOG(1) << "Passphrase type changed to "
811 << syncer::PassphraseTypeToString(type);
812 cached_passphrase_type_ = type;
813 cached_explicit_passphrase_time_ = explicit_passphrase_time;
816 void SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop(
817 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) {
818 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
819 frontend_->OnLocalSetPassphraseEncryption(nigori_state);
822 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop(
823 syncer::ConnectionStatus status) {
824 if (!frontend_)
825 return;
827 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
829 DVLOG(1) << "Connection status changed: "
830 << syncer::ConnectionStatusToString(status);
831 frontend_->OnConnectionStatusChange(status);
834 void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop(
835 syncer::ProtocolEvent* event) {
836 scoped_ptr<syncer::ProtocolEvent> scoped_event(event);
837 if (!frontend_)
838 return;
839 frontend_->OnProtocolEvent(*scoped_event);
842 void SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop(
843 syncer::ModelType type,
844 const syncer::CommitCounters& counters) {
845 if (!frontend_)
846 return;
847 frontend_->OnDirectoryTypeCommitCounterUpdated(type, counters);
850 void SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop(
851 syncer::ModelType type,
852 const syncer::UpdateCounters& counters) {
853 if (!frontend_)
854 return;
855 frontend_->OnDirectoryTypeUpdateCounterUpdated(type, counters);
858 void SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop(
859 syncer::ModelType type,
860 const syncer::StatusCounters& counters) {
861 if (!frontend_)
862 return;
863 frontend_->OnDirectoryTypeStatusCounterUpdated(type, counters);
866 void SyncBackendHostImpl::UpdateInvalidationVersions(
867 const std::map<syncer::ModelType, int64>& invalidation_versions) {
868 sync_prefs_->UpdateInvalidationVersions(invalidation_versions);
871 base::MessageLoop* SyncBackendHostImpl::GetSyncLoopForTesting() {
872 return registrar_->sync_thread()->message_loop();
875 void SyncBackendHostImpl::RefreshTypesForTest(syncer::ModelTypeSet types) {
876 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
878 registrar_->sync_thread()->task_runner()->PostTask(
879 FROM_HERE,
880 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
883 void SyncBackendHostImpl::ClearServerData(
884 const syncer::SyncManager::ClearServerDataCallback& callback) {
885 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
886 registrar_->sync_thread()->task_runner()->PostTask(
887 FROM_HERE, base::Bind(&SyncBackendHostCore::DoClearServerData,
888 core_.get(), callback));
891 void SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop(
892 const syncer::SyncManager::ClearServerDataCallback& frontend_callback) {
893 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
894 frontend_callback.Run();
897 } // namespace browser_sync
899 #undef SDVLOG
901 #undef SLOG