BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_host_impl.cc
blob920a25f21df4c8a41c356e0db0df33249d38ddaa
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/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(
61 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
62 const base::Time& network_time,
63 const base::TimeDelta& resolution,
64 const base::TimeDelta& latency) {
65 ui_thread->PostTask(FROM_HERE,
66 base::Bind(&UpdateNetworkTimeOnUIThread, network_time,
67 resolution, latency, base::TimeTicks::Now()));
70 } // namespace
72 SyncBackendHostImpl::SyncBackendHostImpl(
73 const std::string& name,
74 Profile* profile,
75 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
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 ui_thread_(ui_thread),
82 name_(name),
83 initialized_(false),
84 sync_prefs_(sync_prefs),
85 frontend_(NULL),
86 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
87 invalidator_(invalidator),
88 invalidation_handler_registered_(false),
89 weak_ptr_factory_(this) {
90 core_ = new SyncBackendHostCore(
91 name_,
92 profile_->GetPath().Append(sync_folder),
93 sync_prefs_->HasSyncSetupCompleted(),
94 weak_ptr_factory_.GetWeakPtr());
97 SyncBackendHostImpl::~SyncBackendHostImpl() {
98 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor.";
99 DCHECK(!registrar_.get());
102 void SyncBackendHostImpl::Initialize(
103 sync_driver::SyncFrontend* frontend,
104 scoped_ptr<base::Thread> sync_thread,
105 const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
106 const scoped_refptr<base::SingleThreadTaskRunner>& file_thread,
107 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
108 const GURL& sync_service_url,
109 const std::string& sync_user_agent,
110 const syncer::SyncCredentials& credentials,
111 bool delete_sync_data_folder,
112 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
113 const syncer::WeakHandle<syncer::UnrecoverableErrorHandler>&
114 unrecoverable_error_handler,
115 const base::Closure& report_unrecoverable_error_function,
116 syncer::NetworkResources* network_resources,
117 scoped_ptr<syncer::SyncEncryptionHandler::NigoriState> saved_nigori_state) {
118 registrar_.reset(new browser_sync::SyncBackendRegistrar(
119 name_, profile_, sync_thread.Pass(), ui_thread_, db_thread, file_thread));
120 CHECK(registrar_->sync_thread());
122 frontend_ = frontend;
123 DCHECK(frontend);
125 syncer::ModelSafeRoutingInfo routing_info;
126 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
127 registrar_->GetModelSafeRoutingInfo(&routing_info);
128 registrar_->GetWorkers(&workers);
130 InternalComponentsFactory::Switches factory_switches = {
131 InternalComponentsFactory::ENCRYPTION_KEYSTORE,
132 InternalComponentsFactory::BACKOFF_NORMAL
135 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
136 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) {
137 factory_switches.backoff_override =
138 InternalComponentsFactory::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE;
140 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) {
141 factory_switches.pre_commit_updates_policy =
142 InternalComponentsFactory::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE;
144 syncer::PassphraseTransitionClearDataOption clear_data_option =
145 syncer::PASSPHRASE_TRANSITION_DO_NOT_CLEAR_DATA;
146 if (cl->HasSwitch(switches::kSyncEnableClearDataOnPassphraseEncryption))
147 clear_data_option = syncer::PASSPHRASE_TRANSITION_CLEAR_DATA;
149 std::map<syncer::ModelType, int64> invalidation_versions;
150 sync_prefs_->GetInvalidationVersions(&invalidation_versions);
152 scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions(
153 registrar_->sync_thread()->message_loop(), registrar_.get(), routing_info,
154 workers, extensions_activity_monitor_.GetExtensionsActivity(),
155 event_handler, sync_service_url, sync_user_agent,
156 network_resources->GetHttpPostProviderFactory(
157 make_scoped_refptr(profile_->GetRequestContext()),
158 base::Bind(&UpdateNetworkTime, ui_thread_),
159 core_->GetRequestContextCancelationSignal()),
160 credentials, invalidator_ ? invalidator_->GetInvalidatorClientId() : "",
161 sync_manager_factory.Pass(), delete_sync_data_folder,
162 sync_prefs_->GetEncryptionBootstrapToken(),
163 sync_prefs_->GetKeystoreEncryptionBootstrapToken(),
164 scoped_ptr<InternalComponentsFactory>(
165 new syncer::InternalComponentsFactoryImpl(factory_switches))
166 .Pass(),
167 unrecoverable_error_handler, report_unrecoverable_error_function,
168 saved_nigori_state.Pass(), clear_data_option, invalidation_versions));
169 InitCore(init_opts.Pass());
172 void SyncBackendHostImpl::UpdateCredentials(
173 const syncer::SyncCredentials& credentials) {
174 DCHECK(registrar_->sync_thread()->IsRunning());
175 registrar_->sync_thread()->task_runner()->PostTask(
176 FROM_HERE, base::Bind(&SyncBackendHostCore::DoUpdateCredentials,
177 core_.get(), credentials));
180 void SyncBackendHostImpl::StartSyncingWithServer() {
181 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called.";
183 syncer::ModelSafeRoutingInfo routing_info;
184 registrar_->GetModelSafeRoutingInfo(&routing_info);
186 registrar_->sync_thread()->task_runner()->PostTask(
187 FROM_HERE, base::Bind(&SyncBackendHostCore::DoStartSyncing, core_.get(),
188 routing_info, sync_prefs_->GetLastPollTime()));
191 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase,
192 bool is_explicit) {
193 DCHECK(registrar_->sync_thread()->IsRunning());
194 if (!IsNigoriEnabled()) {
195 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori"
196 " is disabled.";
197 return;
200 // We should never be called with an empty passphrase.
201 DCHECK(!passphrase.empty());
203 // This should only be called by the frontend.
204 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
206 // SetEncryptionPassphrase should never be called if we are currently
207 // encrypted with an explicit passphrase.
208 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE ||
209 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE);
211 // Post an encryption task on the syncer thread.
212 registrar_->sync_thread()->task_runner()->PostTask(
213 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase,
214 core_.get(), passphrase, is_explicit));
217 bool SyncBackendHostImpl::SetDecryptionPassphrase(
218 const std::string& passphrase) {
219 if (!IsNigoriEnabled()) {
220 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori"
221 " is disabled.";
222 return false;
225 // We should never be called with an empty passphrase.
226 DCHECK(!passphrase.empty());
228 // This should only be called by the frontend.
229 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
231 // This should only be called when we have cached pending keys.
232 DCHECK(cached_pending_keys_.has_blob());
234 // Check the passphrase that was provided against our local cache of the
235 // cryptographer's pending keys. If this was unsuccessful, the UI layer can
236 // immediately call OnPassphraseRequired without showing the user a spinner.
237 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase))
238 return false;
240 // Post a decryption task on the syncer thread.
241 registrar_->sync_thread()->task_runner()->PostTask(
242 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase,
243 core_.get(), passphrase));
245 // Since we were able to decrypt the cached pending keys with the passphrase
246 // provided, we immediately alert the UI layer that the passphrase was
247 // accepted. This will avoid the situation where a user enters a passphrase,
248 // clicks OK, immediately reopens the advanced settings dialog, and gets an
249 // unnecessary prompt for a passphrase.
250 // Note: It is not guaranteed that the passphrase will be accepted by the
251 // syncer thread, since we could receive a new nigori node while the task is
252 // pending. This scenario is a valid race, and SetDecryptionPassphrase can
253 // trigger a new OnPassphraseRequired if it needs to.
254 NotifyPassphraseAccepted();
255 return true;
258 void SyncBackendHostImpl::StopSyncingForShutdown() {
259 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
261 // Immediately stop sending messages to the frontend.
262 frontend_ = NULL;
264 // Stop listening for and forwarding locally-triggered sync refresh requests.
265 notification_registrar_.RemoveAll();
267 // Stop non-blocking sync types from sending any more requests to the syncer.
268 sync_context_proxy_.reset();
270 DCHECK(registrar_->sync_thread()->IsRunning());
272 registrar_->RequestWorkerStopOnUIThread();
274 core_->ShutdownOnUIThread();
277 scoped_ptr<base::Thread> SyncBackendHostImpl::Shutdown(
278 syncer::ShutdownReason reason) {
279 // StopSyncingForShutdown() (which nulls out |frontend_|) should be
280 // called first.
281 DCHECK(!frontend_);
282 DCHECK(registrar_->sync_thread()->IsRunning());
284 bool sync_thread_claimed = (reason != syncer::BROWSER_SHUTDOWN);
286 if (invalidation_handler_registered_) {
287 if (reason == syncer::DISABLE_SYNC) {
288 UnregisterInvalidationIds();
290 invalidator_->UnregisterInvalidationHandler(this);
291 invalidator_ = NULL;
293 invalidation_handler_registered_ = false;
295 // Shut down and destroy sync manager.
296 registrar_->sync_thread()->task_runner()->PostTask(
297 FROM_HERE,
298 base::Bind(&SyncBackendHostCore::DoShutdown, core_.get(), reason));
299 core_ = NULL;
301 // Worker cleanup.
302 SyncBackendRegistrar* detached_registrar = registrar_.release();
303 detached_registrar->sync_thread()->task_runner()->PostTask(
304 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
305 base::Unretained(detached_registrar)));
307 if (sync_thread_claimed)
308 return detached_registrar->ReleaseSyncThread();
309 else
310 return scoped_ptr<base::Thread>();
313 void SyncBackendHostImpl::UnregisterInvalidationIds() {
314 if (invalidation_handler_registered_) {
315 CHECK(invalidator_->UpdateRegisteredInvalidationIds(this,
316 syncer::ObjectIdSet()));
320 syncer::ModelTypeSet SyncBackendHostImpl::ConfigureDataTypes(
321 syncer::ConfigureReason reason,
322 const DataTypeConfigStateMap& config_state_map,
323 const base::Callback<void(syncer::ModelTypeSet, syncer::ModelTypeSet)>&
324 ready_task,
325 const base::Callback<void()>& retry_callback) {
326 // Only one configure is allowed at a time. This is guaranteed by our
327 // callers. The SyncBackendHostImpl requests one configure as the backend is
328 // initializing and waits for it to complete. After initialization, all
329 // configurations will pass through the DataTypeManager, which is careful to
330 // never send a new configure request until the current request succeeds.
332 // The SyncBackendRegistrar's routing info will be updated by adding the
333 // types_to_add to the list then removing types_to_remove. Any types which
334 // are not in either of those sets will remain untouched.
336 // Types which were not in the list previously are not fully downloaded, so we
337 // must ask the syncer to download them. Any newly supported datatypes will
338 // not have been in that routing info list, so they will be among the types
339 // downloaded if they are enabled.
341 // The SyncBackendRegistrar's state was initially derived from the types
342 // detected to have been downloaded in the database. Afterwards it is
343 // modified only by this function. We expect it to remain in sync with the
344 // backend because configuration requests are never aborted; they are retried
345 // until they succeed or the backend is shut down.
347 syncer::ModelTypeSet disabled_types =
348 GetDataTypesInState(DISABLED, config_state_map);
349 syncer::ModelTypeSet fatal_types =
350 GetDataTypesInState(FATAL, config_state_map);
351 syncer::ModelTypeSet crypto_types =
352 GetDataTypesInState(CRYPTO, config_state_map);
353 syncer::ModelTypeSet unready_types =
354 GetDataTypesInState(UNREADY, config_state_map);
356 disabled_types.PutAll(fatal_types);
357 disabled_types.PutAll(crypto_types);
358 disabled_types.PutAll(unready_types);
360 syncer::ModelTypeSet active_types =
361 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
362 syncer::ModelTypeSet clean_first_types =
363 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
364 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes(
365 syncer::Union(active_types, clean_first_types),
366 disabled_types);
367 types_to_download.PutAll(clean_first_types);
368 types_to_download.RemoveAll(syncer::ProxyTypes());
369 if (!types_to_download.Empty())
370 types_to_download.Put(syncer::NIGORI);
372 // TODO(sync): crbug.com/137550.
373 // It's dangerous to configure types that have progress markers. Types with
374 // progress markers can trigger a MIGRATION_DONE response. We are not
375 // prepared to handle a migration during a configure, so we must ensure that
376 // all our types_to_download actually contain no data before we sync them.
378 // One common way to end up in this situation used to be types which
379 // downloaded some or all of their data but have not applied it yet. We avoid
380 // problems with those types by purging the data of any such partially synced
381 // types soon after we load the directory.
383 // Another possible scenario is that we have newly supported or newly enabled
384 // data types being downloaded here but the nigori type, which is always
385 // included in any GetUpdates request, requires migration. The server has
386 // code to detect this scenario based on the configure reason, the fact that
387 // the nigori type is the only requested type which requires migration, and
388 // that the requested types list includes at least one non-nigori type. It
389 // will not send a MIGRATION_DONE response in that case. We still need to be
390 // careful to not send progress markers for non-nigori types, though. If a
391 // non-nigori type in the request requires migration, a MIGRATION_DONE
392 // response will be sent.
394 syncer::ModelSafeRoutingInfo routing_info;
395 registrar_->GetModelSafeRoutingInfo(&routing_info);
397 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes();
398 syncer::ModelTypeSet types_to_purge =
399 syncer::Difference(syncer::ModelTypeSet::All(), current_types);
400 syncer::ModelTypeSet inactive_types =
401 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
402 types_to_purge.RemoveAll(inactive_types);
403 types_to_purge.RemoveAll(unready_types);
405 // If a type has already been disabled and unapplied or journaled, it will
406 // not be part of the |types_to_purge| set, and therefore does not need
407 // to be acted on again.
408 fatal_types.RetainAll(types_to_purge);
409 syncer::ModelTypeSet unapply_types =
410 syncer::Union(crypto_types, clean_first_types);
411 unapply_types.RetainAll(types_to_purge);
413 DCHECK(syncer::Intersection(current_types, fatal_types).Empty());
414 DCHECK(syncer::Intersection(current_types, crypto_types).Empty());
415 DCHECK(current_types.HasAll(types_to_download));
417 SDVLOG(1) << "Types "
418 << syncer::ModelTypeSetToString(types_to_download)
419 << " added; calling DoConfigureSyncer";
420 // Divide up the types into their corresponding actions (each is mutually
421 // exclusive):
422 // - Types which have just been added to the routing info (types_to_download):
423 // are downloaded.
424 // - Types which have encountered a fatal error (fatal_types) are deleted
425 // from the directory and journaled in the delete journal.
426 // - Types which have encountered a cryptographer error (crypto_types) are
427 // unapplied (local state is purged but sync state is not).
428 // - All other types not in the routing info (types just disabled) are deleted
429 // from the directory.
430 // - Everything else (enabled types and already disabled types) is not
431 // touched.
432 RequestConfigureSyncer(reason,
433 types_to_download,
434 types_to_purge,
435 fatal_types,
436 unapply_types,
437 inactive_types,
438 routing_info,
439 ready_task,
440 retry_callback);
442 DCHECK(syncer::Intersection(active_types, types_to_purge).Empty());
443 DCHECK(syncer::Intersection(active_types, fatal_types).Empty());
444 DCHECK(syncer::Intersection(active_types, unapply_types).Empty());
445 DCHECK(syncer::Intersection(active_types, inactive_types).Empty());
446 return syncer::Difference(active_types, types_to_download);
449 void SyncBackendHostImpl::EnableEncryptEverything() {
450 registrar_->sync_thread()->task_runner()->PostTask(
451 FROM_HERE,
452 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything, core_.get()));
455 void SyncBackendHostImpl::ActivateDataType(
456 syncer::ModelType type, syncer::ModelSafeGroup group,
457 sync_driver::ChangeProcessor* change_processor) {
458 registrar_->ActivateDataType(type, group, change_processor, GetUserShare());
461 void SyncBackendHostImpl::DeactivateDataType(syncer::ModelType type) {
462 registrar_->DeactivateDataType(type);
465 syncer::UserShare* SyncBackendHostImpl::GetUserShare() const {
466 return core_->sync_manager()->GetUserShare();
469 scoped_ptr<syncer_v2::SyncContextProxy>
470 SyncBackendHostImpl::GetSyncContextProxy() {
471 return sync_context_proxy_.get() ? scoped_ptr<syncer_v2::SyncContextProxy>(
472 sync_context_proxy_->Clone())
473 : scoped_ptr<syncer_v2::SyncContextProxy>();
476 SyncBackendHostImpl::Status SyncBackendHostImpl::GetDetailedStatus() {
477 DCHECK(initialized());
478 return core_->sync_manager()->GetDetailedStatus();
481 syncer::sessions::SyncSessionSnapshot
482 SyncBackendHostImpl::GetLastSessionSnapshot() const {
483 return last_snapshot_;
486 bool SyncBackendHostImpl::HasUnsyncedItems() const {
487 DCHECK(initialized());
488 return core_->sync_manager()->HasUnsyncedItems();
491 bool SyncBackendHostImpl::IsNigoriEnabled() const {
492 return registrar_.get() && registrar_->IsNigoriEnabled();
495 syncer::PassphraseType SyncBackendHostImpl::GetPassphraseType() const {
496 return cached_passphrase_type_;
499 base::Time SyncBackendHostImpl::GetExplicitPassphraseTime() const {
500 return cached_explicit_passphrase_time_;
503 bool SyncBackendHostImpl::IsCryptographerReady(
504 const syncer::BaseTransaction* trans) const {
505 return initialized() && trans->GetCryptographer() &&
506 trans->GetCryptographer()->is_ready();
509 void SyncBackendHostImpl::GetModelSafeRoutingInfo(
510 syncer::ModelSafeRoutingInfo* out) const {
511 if (initialized()) {
512 CHECK(registrar_.get());
513 registrar_->GetModelSafeRoutingInfo(out);
514 } else {
515 NOTREACHED();
519 void SyncBackendHostImpl::FlushDirectory() const {
520 DCHECK(initialized());
521 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
522 base::Bind(&SyncBackendHostCore::SaveChanges, core_));
525 void SyncBackendHostImpl::RequestBufferedProtocolEventsAndEnableForwarding() {
526 registrar_->sync_thread()->task_runner()->PostTask(
527 FROM_HERE,
528 base::Bind(
529 &SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding,
530 core_));
533 void SyncBackendHostImpl::DisableProtocolEventForwarding() {
534 registrar_->sync_thread()->task_runner()->PostTask(
535 FROM_HERE,
536 base::Bind(&SyncBackendHostCore::DisableProtocolEventForwarding, core_));
539 void SyncBackendHostImpl::EnableDirectoryTypeDebugInfoForwarding() {
540 DCHECK(initialized());
541 registrar_->sync_thread()->task_runner()->PostTask(
542 FROM_HERE,
543 base::Bind(&SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding,
544 core_));
547 void SyncBackendHostImpl::DisableDirectoryTypeDebugInfoForwarding() {
548 DCHECK(initialized());
549 registrar_->sync_thread()->task_runner()->PostTask(
550 FROM_HERE,
551 base::Bind(&SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding,
552 core_));
555 void SyncBackendHostImpl::GetAllNodesForTypes(
556 syncer::ModelTypeSet types,
557 base::Callback<void(const std::vector<syncer::ModelType>&,
558 ScopedVector<base::ListValue>)> callback) {
559 DCHECK(initialized());
560 registrar_->sync_thread()->task_runner()->PostTask(
561 FROM_HERE, base::Bind(&SyncBackendHostCore::GetAllNodesForTypes, core_,
562 types, frontend_loop_->task_runner(), callback));
565 void SyncBackendHostImpl::InitCore(scoped_ptr<DoInitializeOptions> options) {
566 registrar_->sync_thread()->task_runner()->PostTask(
567 FROM_HERE, base::Bind(&SyncBackendHostCore::DoInitialize, core_.get(),
568 base::Passed(&options)));
571 void SyncBackendHostImpl::RequestConfigureSyncer(
572 syncer::ConfigureReason reason,
573 syncer::ModelTypeSet to_download,
574 syncer::ModelTypeSet to_purge,
575 syncer::ModelTypeSet to_journal,
576 syncer::ModelTypeSet to_unapply,
577 syncer::ModelTypeSet to_ignore,
578 const syncer::ModelSafeRoutingInfo& routing_info,
579 const base::Callback<void(syncer::ModelTypeSet,
580 syncer::ModelTypeSet)>& ready_task,
581 const base::Closure& retry_callback) {
582 DoConfigureSyncerTypes config_types;
583 config_types.to_download = to_download;
584 config_types.to_purge = to_purge;
585 config_types.to_journal = to_journal;
586 config_types.to_unapply = to_unapply;
587 registrar_->sync_thread()->task_runner()->PostTask(
588 FROM_HERE,
589 base::Bind(&SyncBackendHostCore::DoConfigureSyncer, core_.get(), reason,
590 config_types, routing_info, ready_task, retry_callback));
593 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop(
594 const syncer::ModelTypeSet enabled_types,
595 const syncer::ModelTypeSet succeeded_configuration_types,
596 const syncer::ModelTypeSet failed_configuration_types,
597 const base::Callback<void(syncer::ModelTypeSet,
598 syncer::ModelTypeSet)>& ready_task) {
599 if (!frontend_)
600 return;
602 if (invalidator_) {
603 CHECK(invalidator_->UpdateRegisteredInvalidationIds(
604 this, ModelTypeSetToObjectIdSet(enabled_types)));
607 if (!ready_task.is_null())
608 ready_task.Run(succeeded_configuration_types, failed_configuration_types);
611 void SyncBackendHostImpl::Observe(
612 int type,
613 const content::NotificationSource& source,
614 const content::NotificationDetails& details) {
615 DCHECK(ui_thread_->BelongsToCurrentThread());
616 DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL);
618 content::Details<const syncer::ModelTypeSet> state_details(details);
619 const syncer::ModelTypeSet& types = *(state_details.ptr());
620 registrar_->sync_thread()->task_runner()->PostTask(
621 FROM_HERE,
622 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
625 void SyncBackendHostImpl::AddExperimentalTypes() {
626 CHECK(initialized());
627 syncer::Experiments experiments;
628 if (core_->sync_manager()->ReceivedExperiment(&experiments))
629 frontend_->OnExperimentsChanged(experiments);
632 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop(
633 const syncer::WeakHandle<syncer::JsBackend> js_backend,
634 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>
635 debug_info_listener,
636 syncer_v2::SyncContextProxy* sync_context_proxy,
637 const std::string& cache_guid) {
638 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
640 if (sync_context_proxy)
641 sync_context_proxy_ = sync_context_proxy->Clone();
643 if (!frontend_)
644 return;
646 initialized_ = true;
648 if (invalidator_) {
649 invalidator_->RegisterInvalidationHandler(this);
650 invalidation_handler_registered_ = true;
652 // Fake a state change to initialize the SyncManager's cached invalidator
653 // state.
654 OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
657 // Start forwarding refresh requests to the SyncManager
658 notification_registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
659 content::Source<Profile>(profile_));
661 // Now that we've downloaded the control types, we can see if there are any
662 // experimental types to enable. This should be done before we inform
663 // the frontend to ensure they're visible in the customize screen.
664 AddExperimentalTypes();
665 frontend_->OnBackendInitialized(js_backend,
666 debug_info_listener,
667 cache_guid,
668 true);
671 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() {
672 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
673 if (!frontend_)
674 return;
676 frontend_->OnBackendInitialized(
677 syncer::WeakHandle<syncer::JsBackend>(),
678 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
680 false);
683 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop(
684 const syncer::sessions::SyncSessionSnapshot& snapshot) {
685 if (!frontend_)
686 return;
687 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
689 last_snapshot_ = snapshot;
691 SDVLOG(1) << "Got snapshot " << snapshot.ToString();
693 if (!snapshot.poll_finish_time().is_null())
694 sync_prefs_->SetLastPollTime(snapshot.poll_finish_time());
696 // Process any changes to the datatypes we're syncing.
697 // TODO(sync): add support for removing types.
698 if (initialized())
699 AddExperimentalTypes();
701 if (initialized())
702 frontend_->OnSyncCycleCompleted();
705 void SyncBackendHostImpl::RetryConfigurationOnFrontendLoop(
706 const base::Closure& retry_callback) {
707 SDVLOG(1) << "Failed to complete configuration, informing of retry.";
708 retry_callback.Run();
711 void SyncBackendHostImpl::PersistEncryptionBootstrapToken(
712 const std::string& token,
713 syncer::BootstrapTokenType token_type) {
714 CHECK(sync_prefs_.get());
715 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN)
716 sync_prefs_->SetEncryptionBootstrapToken(token);
717 else
718 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token);
721 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop(
722 const syncer::SyncProtocolError& sync_error) {
723 if (!frontend_)
724 return;
725 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
726 frontend_->OnActionableError(sync_error);
729 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop(
730 syncer::ModelTypeSet types) {
731 if (!frontend_)
732 return;
733 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
734 frontend_->OnMigrationNeededForTypes(types);
737 void SyncBackendHostImpl::OnInvalidatorStateChange(
738 syncer::InvalidatorState state) {
739 registrar_->sync_thread()->task_runner()->PostTask(
740 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnInvalidatorStateChange,
741 core_.get(), state));
744 void SyncBackendHostImpl::OnIncomingInvalidation(
745 const syncer::ObjectIdInvalidationMap& invalidation_map) {
746 registrar_->sync_thread()->task_runner()->PostTask(
747 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnIncomingInvalidation,
748 core_.get(), invalidation_map));
751 std::string SyncBackendHostImpl::GetOwnerName() const {
752 return "SyncBackendHostImpl";
755 bool SyncBackendHostImpl::CheckPassphraseAgainstCachedPendingKeys(
756 const std::string& passphrase) const {
757 DCHECK(cached_pending_keys_.has_blob());
758 DCHECK(!passphrase.empty());
759 syncer::Nigori nigori;
760 nigori.InitByDerivation("localhost", "dummy", passphrase);
761 std::string plaintext;
762 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext);
763 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys.";
764 return result;
767 void SyncBackendHostImpl::NotifyPassphraseRequired(
768 syncer::PassphraseRequiredReason reason,
769 sync_pb::EncryptedData pending_keys) {
770 if (!frontend_)
771 return;
773 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
775 // Update our cache of the cryptographer's pending keys.
776 cached_pending_keys_ = pending_keys;
778 frontend_->OnPassphraseRequired(reason, pending_keys);
781 void SyncBackendHostImpl::NotifyPassphraseAccepted() {
782 if (!frontend_)
783 return;
785 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
787 // Clear our cache of the cryptographer's pending keys.
788 cached_pending_keys_.clear_blob();
789 frontend_->OnPassphraseAccepted();
792 void SyncBackendHostImpl::NotifyEncryptedTypesChanged(
793 syncer::ModelTypeSet encrypted_types,
794 bool encrypt_everything) {
795 if (!frontend_)
796 return;
798 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
799 frontend_->OnEncryptedTypesChanged(
800 encrypted_types, encrypt_everything);
803 void SyncBackendHostImpl::NotifyEncryptionComplete() {
804 if (!frontend_)
805 return;
807 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
808 frontend_->OnEncryptionComplete();
811 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop(
812 syncer::PassphraseType type,
813 base::Time explicit_passphrase_time) {
814 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
815 DVLOG(1) << "Passphrase type changed to "
816 << syncer::PassphraseTypeToString(type);
817 cached_passphrase_type_ = type;
818 cached_explicit_passphrase_time_ = explicit_passphrase_time;
821 void SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop(
822 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) {
823 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
824 frontend_->OnLocalSetPassphraseEncryption(nigori_state);
827 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop(
828 syncer::ConnectionStatus status) {
829 if (!frontend_)
830 return;
832 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
834 DVLOG(1) << "Connection status changed: "
835 << syncer::ConnectionStatusToString(status);
836 frontend_->OnConnectionStatusChange(status);
839 void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop(
840 syncer::ProtocolEvent* event) {
841 scoped_ptr<syncer::ProtocolEvent> scoped_event(event);
842 if (!frontend_)
843 return;
844 frontend_->OnProtocolEvent(*scoped_event);
847 void SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop(
848 syncer::ModelType type,
849 const syncer::CommitCounters& counters) {
850 if (!frontend_)
851 return;
852 frontend_->OnDirectoryTypeCommitCounterUpdated(type, counters);
855 void SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop(
856 syncer::ModelType type,
857 const syncer::UpdateCounters& counters) {
858 if (!frontend_)
859 return;
860 frontend_->OnDirectoryTypeUpdateCounterUpdated(type, counters);
863 void SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop(
864 syncer::ModelType type,
865 const syncer::StatusCounters& counters) {
866 if (!frontend_)
867 return;
868 frontend_->OnDirectoryTypeStatusCounterUpdated(type, counters);
871 void SyncBackendHostImpl::UpdateInvalidationVersions(
872 const std::map<syncer::ModelType, int64>& invalidation_versions) {
873 sync_prefs_->UpdateInvalidationVersions(invalidation_versions);
876 base::MessageLoop* SyncBackendHostImpl::GetSyncLoopForTesting() {
877 return registrar_->sync_thread()->message_loop();
880 void SyncBackendHostImpl::RefreshTypesForTest(syncer::ModelTypeSet types) {
881 DCHECK(ui_thread_->BelongsToCurrentThread());
883 registrar_->sync_thread()->task_runner()->PostTask(
884 FROM_HERE,
885 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
888 void SyncBackendHostImpl::ClearServerData(
889 const syncer::SyncManager::ClearServerDataCallback& callback) {
890 DCHECK(ui_thread_->BelongsToCurrentThread());
891 registrar_->sync_thread()->task_runner()->PostTask(
892 FROM_HERE, base::Bind(&SyncBackendHostCore::DoClearServerData,
893 core_.get(), callback));
896 void SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop(
897 const syncer::SyncManager::ClearServerDataCallback& frontend_callback) {
898 DCHECK(ui_thread_->BelongsToCurrentThread());
899 frontend_callback.Run();
902 } // namespace browser_sync
904 #undef SDVLOG
906 #undef SLOG