Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_host_impl.cc
blob7e63d18314f9fc24cdf84c33e8c75fb1cc9128ff
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/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/public/invalidation_service.h"
19 #include "components/invalidation/public/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/invalidation_helper.h"
23 #include "components/sync_driver/sync_driver_switches.h"
24 #include "components/sync_driver/sync_frontend.h"
25 #include "components/sync_driver/sync_prefs.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/notification_details.h"
28 #include "content/public/browser/notification_source.h"
29 #include "sync/internal_api/public/base_transaction.h"
30 #include "sync/internal_api/public/events/protocol_event.h"
31 #include "sync/internal_api/public/http_bridge.h"
32 #include "sync/internal_api/public/internal_components_factory.h"
33 #include "sync/internal_api/public/internal_components_factory_impl.h"
34 #include "sync/internal_api/public/network_resources.h"
35 #include "sync/internal_api/public/sync_manager.h"
36 #include "sync/internal_api/public/sync_manager_factory.h"
37 #include "sync/internal_api/public/util/experiments.h"
38 #include "sync/internal_api/public/util/sync_string_conversions.h"
40 // Helper macros to log with the syncer thread name; useful when there
41 // are multiple syncers involved.
43 #define SLOG(severity) LOG(severity) << name_ << ": "
45 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
47 using syncer::InternalComponentsFactory;
49 namespace browser_sync {
51 namespace {
53 void UpdateNetworkTimeOnUIThread(base::Time network_time,
54 base::TimeDelta resolution,
55 base::TimeDelta latency,
56 base::TimeTicks post_time) {
57 g_browser_process->network_time_tracker()->UpdateNetworkTime(
58 network_time, resolution, latency, post_time);
61 void UpdateNetworkTime(const base::Time& network_time,
62 const base::TimeDelta& resolution,
63 const base::TimeDelta& latency) {
64 content::BrowserThread::PostTask(
65 content::BrowserThread::UI,
66 FROM_HERE,
67 base::Bind(&UpdateNetworkTimeOnUIThread,
68 network_time, resolution, latency, base::TimeTicks::Now()));
71 } // namespace
73 SyncBackendHostImpl::SyncBackendHostImpl(
74 const std::string& name,
75 Profile* profile,
76 invalidation::InvalidationService* invalidator,
77 const base::WeakPtr<sync_driver::SyncPrefs>& sync_prefs,
78 const base::FilePath& sync_folder)
79 : frontend_loop_(base::MessageLoop::current()),
80 profile_(profile),
81 name_(name),
82 initialized_(false),
83 sync_prefs_(sync_prefs),
84 frontend_(NULL),
85 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
86 invalidator_(invalidator),
87 invalidation_handler_registered_(false),
88 weak_ptr_factory_(this) {
89 core_ = new SyncBackendHostCore(
90 name_,
91 profile_->GetPath().Append(sync_folder),
92 sync_prefs_->HasSyncSetupCompleted(),
93 weak_ptr_factory_.GetWeakPtr());
96 SyncBackendHostImpl::~SyncBackendHostImpl() {
97 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor.";
98 DCHECK(!registrar_.get());
101 void SyncBackendHostImpl::Initialize(
102 sync_driver::SyncFrontend* frontend,
103 scoped_ptr<base::Thread> sync_thread,
104 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
105 const GURL& sync_service_url,
106 const std::string& sync_user_agent,
107 const syncer::SyncCredentials& credentials,
108 bool delete_sync_data_folder,
109 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
110 const syncer::WeakHandle<syncer::UnrecoverableErrorHandler>&
111 unrecoverable_error_handler,
112 const base::Closure& report_unrecoverable_error_function,
113 syncer::NetworkResources* network_resources,
114 scoped_ptr<syncer::SyncEncryptionHandler::NigoriState> saved_nigori_state) {
115 registrar_.reset(new browser_sync::SyncBackendRegistrar(name_,
116 profile_,
117 sync_thread.Pass()));
118 CHECK(registrar_->sync_thread());
120 frontend_ = frontend;
121 DCHECK(frontend);
123 syncer::ModelSafeRoutingInfo routing_info;
124 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
125 registrar_->GetModelSafeRoutingInfo(&routing_info);
126 registrar_->GetWorkers(&workers);
128 InternalComponentsFactory::Switches factory_switches = {
129 InternalComponentsFactory::ENCRYPTION_KEYSTORE,
130 InternalComponentsFactory::BACKOFF_NORMAL
133 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
134 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) {
135 factory_switches.backoff_override =
136 InternalComponentsFactory::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE;
138 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) {
139 factory_switches.pre_commit_updates_policy =
140 InternalComponentsFactory::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE;
142 syncer::PassphraseTransitionClearDataOption clear_data_option =
143 syncer::PASSPHRASE_TRANSITION_DO_NOT_CLEAR_DATA;
144 if (cl->HasSwitch(switches::kSyncEnableClearDataOnPassphraseEncryption))
145 clear_data_option = syncer::PASSPHRASE_TRANSITION_CLEAR_DATA;
147 std::map<syncer::ModelType, int64> invalidation_versions;
148 sync_prefs_->GetInvalidationVersions(&invalidation_versions);
150 scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions(
151 registrar_->sync_thread()->message_loop(), registrar_.get(), routing_info,
152 workers, extensions_activity_monitor_.GetExtensionsActivity(),
153 event_handler, sync_service_url, sync_user_agent,
154 network_resources->GetHttpPostProviderFactory(
155 make_scoped_refptr(profile_->GetRequestContext()),
156 base::Bind(&UpdateNetworkTime),
157 core_->GetRequestContextCancelationSignal()),
158 credentials, invalidator_ ? invalidator_->GetInvalidatorClientId() : "",
159 sync_manager_factory.Pass(), delete_sync_data_folder,
160 sync_prefs_->GetEncryptionBootstrapToken(),
161 sync_prefs_->GetKeystoreEncryptionBootstrapToken(),
162 scoped_ptr<InternalComponentsFactory>(
163 new syncer::InternalComponentsFactoryImpl(factory_switches))
164 .Pass(),
165 unrecoverable_error_handler, report_unrecoverable_error_function,
166 saved_nigori_state.Pass(), clear_data_option, invalidation_versions));
167 InitCore(init_opts.Pass());
170 void SyncBackendHostImpl::UpdateCredentials(
171 const syncer::SyncCredentials& credentials) {
172 DCHECK(registrar_->sync_thread()->IsRunning());
173 registrar_->sync_thread()->task_runner()->PostTask(
174 FROM_HERE, base::Bind(&SyncBackendHostCore::DoUpdateCredentials,
175 core_.get(), credentials));
178 void SyncBackendHostImpl::StartSyncingWithServer() {
179 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called.";
181 syncer::ModelSafeRoutingInfo routing_info;
182 registrar_->GetModelSafeRoutingInfo(&routing_info);
184 registrar_->sync_thread()->task_runner()->PostTask(
185 FROM_HERE, base::Bind(&SyncBackendHostCore::DoStartSyncing, core_.get(),
186 routing_info, sync_prefs_->GetLastPollTime()));
189 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase,
190 bool is_explicit) {
191 DCHECK(registrar_->sync_thread()->IsRunning());
192 if (!IsNigoriEnabled()) {
193 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori"
194 " is disabled.";
195 return;
198 // We should never be called with an empty passphrase.
199 DCHECK(!passphrase.empty());
201 // This should only be called by the frontend.
202 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
204 // SetEncryptionPassphrase should never be called if we are currently
205 // encrypted with an explicit passphrase.
206 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE ||
207 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE);
209 // Post an encryption task on the syncer thread.
210 registrar_->sync_thread()->task_runner()->PostTask(
211 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase,
212 core_.get(), passphrase, is_explicit));
215 bool SyncBackendHostImpl::SetDecryptionPassphrase(
216 const std::string& passphrase) {
217 if (!IsNigoriEnabled()) {
218 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori"
219 " is disabled.";
220 return false;
223 // We should never be called with an empty passphrase.
224 DCHECK(!passphrase.empty());
226 // This should only be called by the frontend.
227 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
229 // This should only be called when we have cached pending keys.
230 DCHECK(cached_pending_keys_.has_blob());
232 // Check the passphrase that was provided against our local cache of the
233 // cryptographer's pending keys. If this was unsuccessful, the UI layer can
234 // immediately call OnPassphraseRequired without showing the user a spinner.
235 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase))
236 return false;
238 // Post a decryption task on the syncer thread.
239 registrar_->sync_thread()->task_runner()->PostTask(
240 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase,
241 core_.get(), passphrase));
243 // Since we were able to decrypt the cached pending keys with the passphrase
244 // provided, we immediately alert the UI layer that the passphrase was
245 // accepted. This will avoid the situation where a user enters a passphrase,
246 // clicks OK, immediately reopens the advanced settings dialog, and gets an
247 // unnecessary prompt for a passphrase.
248 // Note: It is not guaranteed that the passphrase will be accepted by the
249 // syncer thread, since we could receive a new nigori node while the task is
250 // pending. This scenario is a valid race, and SetDecryptionPassphrase can
251 // trigger a new OnPassphraseRequired if it needs to.
252 NotifyPassphraseAccepted();
253 return true;
256 void SyncBackendHostImpl::StopSyncingForShutdown() {
257 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
259 // Immediately stop sending messages to the frontend.
260 frontend_ = NULL;
262 // Stop listening for and forwarding locally-triggered sync refresh requests.
263 notification_registrar_.RemoveAll();
265 // Stop non-blocking sync types from sending any more requests to the syncer.
266 sync_context_proxy_.reset();
268 DCHECK(registrar_->sync_thread()->IsRunning());
270 registrar_->RequestWorkerStopOnUIThread();
272 core_->ShutdownOnUIThread();
275 scoped_ptr<base::Thread> SyncBackendHostImpl::Shutdown(
276 syncer::ShutdownReason reason) {
277 // StopSyncingForShutdown() (which nulls out |frontend_|) should be
278 // called first.
279 DCHECK(!frontend_);
280 DCHECK(registrar_->sync_thread()->IsRunning());
282 bool sync_thread_claimed = (reason != syncer::BROWSER_SHUTDOWN);
284 if (invalidation_handler_registered_) {
285 if (reason == syncer::DISABLE_SYNC) {
286 UnregisterInvalidationIds();
288 invalidator_->UnregisterInvalidationHandler(this);
289 invalidator_ = NULL;
291 invalidation_handler_registered_ = false;
293 // Shut down and destroy sync manager.
294 registrar_->sync_thread()->task_runner()->PostTask(
295 FROM_HERE,
296 base::Bind(&SyncBackendHostCore::DoShutdown, core_.get(), reason));
297 core_ = NULL;
299 // Worker cleanup.
300 SyncBackendRegistrar* detached_registrar = registrar_.release();
301 detached_registrar->sync_thread()->task_runner()->PostTask(
302 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
303 base::Unretained(detached_registrar)));
305 if (sync_thread_claimed)
306 return detached_registrar->ReleaseSyncThread();
307 else
308 return scoped_ptr<base::Thread>();
311 void SyncBackendHostImpl::UnregisterInvalidationIds() {
312 if (invalidation_handler_registered_) {
313 CHECK(invalidator_->UpdateRegisteredInvalidationIds(this,
314 syncer::ObjectIdSet()));
318 syncer::ModelTypeSet SyncBackendHostImpl::ConfigureDataTypes(
319 syncer::ConfigureReason reason,
320 const DataTypeConfigStateMap& config_state_map,
321 const base::Callback<void(syncer::ModelTypeSet, syncer::ModelTypeSet)>&
322 ready_task,
323 const base::Callback<void()>& retry_callback) {
324 // Only one configure is allowed at a time. This is guaranteed by our
325 // callers. The SyncBackendHostImpl requests one configure as the backend is
326 // initializing and waits for it to complete. After initialization, all
327 // configurations will pass through the DataTypeManager, which is careful to
328 // never send a new configure request until the current request succeeds.
330 // The SyncBackendRegistrar's routing info will be updated by adding the
331 // types_to_add to the list then removing types_to_remove. Any types which
332 // are not in either of those sets will remain untouched.
334 // Types which were not in the list previously are not fully downloaded, so we
335 // must ask the syncer to download them. Any newly supported datatypes will
336 // not have been in that routing info list, so they will be among the types
337 // downloaded if they are enabled.
339 // The SyncBackendRegistrar's state was initially derived from the types
340 // detected to have been downloaded in the database. Afterwards it is
341 // modified only by this function. We expect it to remain in sync with the
342 // backend because configuration requests are never aborted; they are retried
343 // until they succeed or the backend is shut down.
345 syncer::ModelTypeSet disabled_types =
346 GetDataTypesInState(DISABLED, config_state_map);
347 syncer::ModelTypeSet fatal_types =
348 GetDataTypesInState(FATAL, config_state_map);
349 syncer::ModelTypeSet crypto_types =
350 GetDataTypesInState(CRYPTO, config_state_map);
351 syncer::ModelTypeSet unready_types =
352 GetDataTypesInState(UNREADY, config_state_map);
354 disabled_types.PutAll(fatal_types);
355 disabled_types.PutAll(crypto_types);
356 disabled_types.PutAll(unready_types);
358 syncer::ModelTypeSet active_types =
359 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
360 syncer::ModelTypeSet clean_first_types =
361 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
362 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes(
363 syncer::Union(active_types, clean_first_types),
364 disabled_types);
365 types_to_download.PutAll(clean_first_types);
366 types_to_download.RemoveAll(syncer::ProxyTypes());
367 if (!types_to_download.Empty())
368 types_to_download.Put(syncer::NIGORI);
370 // TODO(sync): crbug.com/137550.
371 // It's dangerous to configure types that have progress markers. Types with
372 // progress markers can trigger a MIGRATION_DONE response. We are not
373 // prepared to handle a migration during a configure, so we must ensure that
374 // all our types_to_download actually contain no data before we sync them.
376 // One common way to end up in this situation used to be types which
377 // downloaded some or all of their data but have not applied it yet. We avoid
378 // problems with those types by purging the data of any such partially synced
379 // types soon after we load the directory.
381 // Another possible scenario is that we have newly supported or newly enabled
382 // data types being downloaded here but the nigori type, which is always
383 // included in any GetUpdates request, requires migration. The server has
384 // code to detect this scenario based on the configure reason, the fact that
385 // the nigori type is the only requested type which requires migration, and
386 // that the requested types list includes at least one non-nigori type. It
387 // will not send a MIGRATION_DONE response in that case. We still need to be
388 // careful to not send progress markers for non-nigori types, though. If a
389 // non-nigori type in the request requires migration, a MIGRATION_DONE
390 // response will be sent.
392 syncer::ModelSafeRoutingInfo routing_info;
393 registrar_->GetModelSafeRoutingInfo(&routing_info);
395 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes();
396 syncer::ModelTypeSet types_to_purge =
397 syncer::Difference(syncer::ModelTypeSet::All(), current_types);
398 syncer::ModelTypeSet inactive_types =
399 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
400 types_to_purge.RemoveAll(inactive_types);
401 types_to_purge.RemoveAll(unready_types);
403 // If a type has already been disabled and unapplied or journaled, it will
404 // not be part of the |types_to_purge| set, and therefore does not need
405 // to be acted on again.
406 fatal_types.RetainAll(types_to_purge);
407 syncer::ModelTypeSet unapply_types =
408 syncer::Union(crypto_types, clean_first_types);
409 unapply_types.RetainAll(types_to_purge);
411 DCHECK(syncer::Intersection(current_types, fatal_types).Empty());
412 DCHECK(syncer::Intersection(current_types, crypto_types).Empty());
413 DCHECK(current_types.HasAll(types_to_download));
415 SDVLOG(1) << "Types "
416 << syncer::ModelTypeSetToString(types_to_download)
417 << " added; calling DoConfigureSyncer";
418 // Divide up the types into their corresponding actions (each is mutually
419 // exclusive):
420 // - Types which have just been added to the routing info (types_to_download):
421 // are downloaded.
422 // - Types which have encountered a fatal error (fatal_types) are deleted
423 // from the directory and journaled in the delete journal.
424 // - Types which have encountered a cryptographer error (crypto_types) are
425 // unapplied (local state is purged but sync state is not).
426 // - All other types not in the routing info (types just disabled) are deleted
427 // from the directory.
428 // - Everything else (enabled types and already disabled types) is not
429 // touched.
430 RequestConfigureSyncer(reason,
431 types_to_download,
432 types_to_purge,
433 fatal_types,
434 unapply_types,
435 inactive_types,
436 routing_info,
437 ready_task,
438 retry_callback);
440 DCHECK(syncer::Intersection(active_types, types_to_purge).Empty());
441 DCHECK(syncer::Intersection(active_types, fatal_types).Empty());
442 DCHECK(syncer::Intersection(active_types, unapply_types).Empty());
443 DCHECK(syncer::Intersection(active_types, inactive_types).Empty());
444 return syncer::Difference(active_types, types_to_download);
447 void SyncBackendHostImpl::EnableEncryptEverything() {
448 registrar_->sync_thread()->task_runner()->PostTask(
449 FROM_HERE,
450 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything, core_.get()));
453 void SyncBackendHostImpl::ActivateDataType(
454 syncer::ModelType type, syncer::ModelSafeGroup group,
455 sync_driver::ChangeProcessor* change_processor) {
456 registrar_->ActivateDataType(type, group, change_processor, GetUserShare());
459 void SyncBackendHostImpl::DeactivateDataType(syncer::ModelType type) {
460 registrar_->DeactivateDataType(type);
463 syncer::UserShare* SyncBackendHostImpl::GetUserShare() const {
464 return core_->sync_manager()->GetUserShare();
467 scoped_ptr<syncer_v2::SyncContextProxy>
468 SyncBackendHostImpl::GetSyncContextProxy() {
469 return sync_context_proxy_.get() ? scoped_ptr<syncer_v2::SyncContextProxy>(
470 sync_context_proxy_->Clone())
471 : scoped_ptr<syncer_v2::SyncContextProxy>();
474 SyncBackendHostImpl::Status SyncBackendHostImpl::GetDetailedStatus() {
475 DCHECK(initialized());
476 return core_->sync_manager()->GetDetailedStatus();
479 syncer::sessions::SyncSessionSnapshot
480 SyncBackendHostImpl::GetLastSessionSnapshot() const {
481 return last_snapshot_;
484 bool SyncBackendHostImpl::HasUnsyncedItems() const {
485 DCHECK(initialized());
486 return core_->sync_manager()->HasUnsyncedItems();
489 bool SyncBackendHostImpl::IsNigoriEnabled() const {
490 return registrar_.get() && registrar_->IsNigoriEnabled();
493 syncer::PassphraseType SyncBackendHostImpl::GetPassphraseType() const {
494 return cached_passphrase_type_;
497 base::Time SyncBackendHostImpl::GetExplicitPassphraseTime() const {
498 return cached_explicit_passphrase_time_;
501 bool SyncBackendHostImpl::IsCryptographerReady(
502 const syncer::BaseTransaction* trans) const {
503 return initialized() && trans->GetCryptographer() &&
504 trans->GetCryptographer()->is_ready();
507 void SyncBackendHostImpl::GetModelSafeRoutingInfo(
508 syncer::ModelSafeRoutingInfo* out) const {
509 if (initialized()) {
510 CHECK(registrar_.get());
511 registrar_->GetModelSafeRoutingInfo(out);
512 } else {
513 NOTREACHED();
517 void SyncBackendHostImpl::FlushDirectory() const {
518 DCHECK(initialized());
519 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
520 base::Bind(&SyncBackendHostCore::SaveChanges, core_));
523 void SyncBackendHostImpl::RequestBufferedProtocolEventsAndEnableForwarding() {
524 registrar_->sync_thread()->task_runner()->PostTask(
525 FROM_HERE,
526 base::Bind(
527 &SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding,
528 core_));
531 void SyncBackendHostImpl::DisableProtocolEventForwarding() {
532 registrar_->sync_thread()->task_runner()->PostTask(
533 FROM_HERE,
534 base::Bind(&SyncBackendHostCore::DisableProtocolEventForwarding, core_));
537 void SyncBackendHostImpl::EnableDirectoryTypeDebugInfoForwarding() {
538 DCHECK(initialized());
539 registrar_->sync_thread()->task_runner()->PostTask(
540 FROM_HERE,
541 base::Bind(&SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding,
542 core_));
545 void SyncBackendHostImpl::DisableDirectoryTypeDebugInfoForwarding() {
546 DCHECK(initialized());
547 registrar_->sync_thread()->task_runner()->PostTask(
548 FROM_HERE,
549 base::Bind(&SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding,
550 core_));
553 void SyncBackendHostImpl::GetAllNodesForTypes(
554 syncer::ModelTypeSet types,
555 base::Callback<void(const std::vector<syncer::ModelType>&,
556 ScopedVector<base::ListValue>)> callback) {
557 DCHECK(initialized());
558 registrar_->sync_thread()->task_runner()->PostTask(
559 FROM_HERE, base::Bind(&SyncBackendHostCore::GetAllNodesForTypes, core_,
560 types, frontend_loop_->task_runner(), callback));
563 void SyncBackendHostImpl::InitCore(scoped_ptr<DoInitializeOptions> options) {
564 registrar_->sync_thread()->task_runner()->PostTask(
565 FROM_HERE, base::Bind(&SyncBackendHostCore::DoInitialize, core_.get(),
566 base::Passed(&options)));
569 void SyncBackendHostImpl::RequestConfigureSyncer(
570 syncer::ConfigureReason reason,
571 syncer::ModelTypeSet to_download,
572 syncer::ModelTypeSet to_purge,
573 syncer::ModelTypeSet to_journal,
574 syncer::ModelTypeSet to_unapply,
575 syncer::ModelTypeSet to_ignore,
576 const syncer::ModelSafeRoutingInfo& routing_info,
577 const base::Callback<void(syncer::ModelTypeSet,
578 syncer::ModelTypeSet)>& ready_task,
579 const base::Closure& retry_callback) {
580 DoConfigureSyncerTypes config_types;
581 config_types.to_download = to_download;
582 config_types.to_purge = to_purge;
583 config_types.to_journal = to_journal;
584 config_types.to_unapply = to_unapply;
585 registrar_->sync_thread()->task_runner()->PostTask(
586 FROM_HERE,
587 base::Bind(&SyncBackendHostCore::DoConfigureSyncer, core_.get(), reason,
588 config_types, routing_info, ready_task, retry_callback));
591 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop(
592 const syncer::ModelTypeSet enabled_types,
593 const syncer::ModelTypeSet succeeded_configuration_types,
594 const syncer::ModelTypeSet failed_configuration_types,
595 const base::Callback<void(syncer::ModelTypeSet,
596 syncer::ModelTypeSet)>& ready_task) {
597 if (!frontend_)
598 return;
600 if (invalidator_) {
601 CHECK(invalidator_->UpdateRegisteredInvalidationIds(
602 this, ModelTypeSetToObjectIdSet(enabled_types)));
605 if (!ready_task.is_null())
606 ready_task.Run(succeeded_configuration_types, failed_configuration_types);
609 void SyncBackendHostImpl::Observe(
610 int type,
611 const content::NotificationSource& source,
612 const content::NotificationDetails& details) {
613 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
614 DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL);
616 content::Details<const syncer::ModelTypeSet> state_details(details);
617 const syncer::ModelTypeSet& types = *(state_details.ptr());
618 registrar_->sync_thread()->task_runner()->PostTask(
619 FROM_HERE,
620 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
623 void SyncBackendHostImpl::AddExperimentalTypes() {
624 CHECK(initialized());
625 syncer::Experiments experiments;
626 if (core_->sync_manager()->ReceivedExperiment(&experiments))
627 frontend_->OnExperimentsChanged(experiments);
630 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop(
631 const syncer::WeakHandle<syncer::JsBackend> js_backend,
632 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>
633 debug_info_listener,
634 syncer_v2::SyncContextProxy* sync_context_proxy,
635 const std::string& cache_guid) {
636 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
638 if (sync_context_proxy)
639 sync_context_proxy_ = sync_context_proxy->Clone();
641 if (!frontend_)
642 return;
644 initialized_ = true;
646 if (invalidator_) {
647 invalidator_->RegisterInvalidationHandler(this);
648 invalidation_handler_registered_ = true;
650 // Fake a state change to initialize the SyncManager's cached invalidator
651 // state.
652 OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
655 // Start forwarding refresh requests to the SyncManager
656 notification_registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
657 content::Source<Profile>(profile_));
659 // Now that we've downloaded the control types, we can see if there are any
660 // experimental types to enable. This should be done before we inform
661 // the frontend to ensure they're visible in the customize screen.
662 AddExperimentalTypes();
663 frontend_->OnBackendInitialized(js_backend,
664 debug_info_listener,
665 cache_guid,
666 true);
669 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() {
670 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
671 if (!frontend_)
672 return;
674 frontend_->OnBackendInitialized(
675 syncer::WeakHandle<syncer::JsBackend>(),
676 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
678 false);
681 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop(
682 const syncer::sessions::SyncSessionSnapshot& snapshot) {
683 if (!frontend_)
684 return;
685 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
687 last_snapshot_ = snapshot;
689 SDVLOG(1) << "Got snapshot " << snapshot.ToString();
691 if (!snapshot.poll_finish_time().is_null())
692 sync_prefs_->SetLastPollTime(snapshot.poll_finish_time());
694 // Process any changes to the datatypes we're syncing.
695 // TODO(sync): add support for removing types.
696 if (initialized())
697 AddExperimentalTypes();
699 if (initialized())
700 frontend_->OnSyncCycleCompleted();
703 void SyncBackendHostImpl::RetryConfigurationOnFrontendLoop(
704 const base::Closure& retry_callback) {
705 SDVLOG(1) << "Failed to complete configuration, informing of retry.";
706 retry_callback.Run();
709 void SyncBackendHostImpl::PersistEncryptionBootstrapToken(
710 const std::string& token,
711 syncer::BootstrapTokenType token_type) {
712 CHECK(sync_prefs_.get());
713 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN)
714 sync_prefs_->SetEncryptionBootstrapToken(token);
715 else
716 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token);
719 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop(
720 const syncer::SyncProtocolError& sync_error) {
721 if (!frontend_)
722 return;
723 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
724 frontend_->OnActionableError(sync_error);
727 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop(
728 syncer::ModelTypeSet types) {
729 if (!frontend_)
730 return;
731 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
732 frontend_->OnMigrationNeededForTypes(types);
735 void SyncBackendHostImpl::OnInvalidatorStateChange(
736 syncer::InvalidatorState state) {
737 registrar_->sync_thread()->task_runner()->PostTask(
738 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnInvalidatorStateChange,
739 core_.get(), state));
742 void SyncBackendHostImpl::OnIncomingInvalidation(
743 const syncer::ObjectIdInvalidationMap& invalidation_map) {
744 registrar_->sync_thread()->task_runner()->PostTask(
745 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnIncomingInvalidation,
746 core_.get(), invalidation_map));
749 std::string SyncBackendHostImpl::GetOwnerName() const {
750 return "SyncBackendHostImpl";
753 bool SyncBackendHostImpl::CheckPassphraseAgainstCachedPendingKeys(
754 const std::string& passphrase) const {
755 DCHECK(cached_pending_keys_.has_blob());
756 DCHECK(!passphrase.empty());
757 syncer::Nigori nigori;
758 nigori.InitByDerivation("localhost", "dummy", passphrase);
759 std::string plaintext;
760 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext);
761 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys.";
762 return result;
765 void SyncBackendHostImpl::NotifyPassphraseRequired(
766 syncer::PassphraseRequiredReason reason,
767 sync_pb::EncryptedData pending_keys) {
768 if (!frontend_)
769 return;
771 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
773 // Update our cache of the cryptographer's pending keys.
774 cached_pending_keys_ = pending_keys;
776 frontend_->OnPassphraseRequired(reason, pending_keys);
779 void SyncBackendHostImpl::NotifyPassphraseAccepted() {
780 if (!frontend_)
781 return;
783 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
785 // Clear our cache of the cryptographer's pending keys.
786 cached_pending_keys_.clear_blob();
787 frontend_->OnPassphraseAccepted();
790 void SyncBackendHostImpl::NotifyEncryptedTypesChanged(
791 syncer::ModelTypeSet encrypted_types,
792 bool encrypt_everything) {
793 if (!frontend_)
794 return;
796 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
797 frontend_->OnEncryptedTypesChanged(
798 encrypted_types, encrypt_everything);
801 void SyncBackendHostImpl::NotifyEncryptionComplete() {
802 if (!frontend_)
803 return;
805 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
806 frontend_->OnEncryptionComplete();
809 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop(
810 syncer::PassphraseType type,
811 base::Time explicit_passphrase_time) {
812 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
813 DVLOG(1) << "Passphrase type changed to "
814 << syncer::PassphraseTypeToString(type);
815 cached_passphrase_type_ = type;
816 cached_explicit_passphrase_time_ = explicit_passphrase_time;
819 void SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop(
820 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) {
821 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
822 frontend_->OnLocalSetPassphraseEncryption(nigori_state);
825 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop(
826 syncer::ConnectionStatus status) {
827 if (!frontend_)
828 return;
830 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
832 DVLOG(1) << "Connection status changed: "
833 << syncer::ConnectionStatusToString(status);
834 frontend_->OnConnectionStatusChange(status);
837 void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop(
838 syncer::ProtocolEvent* event) {
839 scoped_ptr<syncer::ProtocolEvent> scoped_event(event);
840 if (!frontend_)
841 return;
842 frontend_->OnProtocolEvent(*scoped_event);
845 void SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop(
846 syncer::ModelType type,
847 const syncer::CommitCounters& counters) {
848 if (!frontend_)
849 return;
850 frontend_->OnDirectoryTypeCommitCounterUpdated(type, counters);
853 void SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop(
854 syncer::ModelType type,
855 const syncer::UpdateCounters& counters) {
856 if (!frontend_)
857 return;
858 frontend_->OnDirectoryTypeUpdateCounterUpdated(type, counters);
861 void SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop(
862 syncer::ModelType type,
863 const syncer::StatusCounters& counters) {
864 if (!frontend_)
865 return;
866 frontend_->OnDirectoryTypeStatusCounterUpdated(type, counters);
869 void SyncBackendHostImpl::UpdateInvalidationVersions(
870 const std::map<syncer::ModelType, int64>& invalidation_versions) {
871 sync_prefs_->UpdateInvalidationVersions(invalidation_versions);
874 base::MessageLoop* SyncBackendHostImpl::GetSyncLoopForTesting() {
875 return registrar_->sync_thread()->message_loop();
878 void SyncBackendHostImpl::RefreshTypesForTest(syncer::ModelTypeSet types) {
879 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
881 registrar_->sync_thread()->task_runner()->PostTask(
882 FROM_HERE,
883 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
886 void SyncBackendHostImpl::ClearServerData(
887 const syncer::SyncManager::ClearServerDataCallback& callback) {
888 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
889 registrar_->sync_thread()->task_runner()->PostTask(
890 FROM_HERE, base::Bind(&SyncBackendHostCore::DoClearServerData,
891 core_.get(), callback));
894 void SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop(
895 const syncer::SyncManager::ClearServerDataCallback& frontend_callback) {
896 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
897 frontend_callback.Run();
900 } // namespace browser_sync
902 #undef SDVLOG
904 #undef SLOG