Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: chrome/browser/sync/glue/sync_backend_host_impl.cc

Issue 61183003: Refactor SyncBackendHost (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix patch upload + fix some other issues Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/sync/glue/sync_backend_host_impl.h"
6
7 #include "base/command_line.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/invalidation/invalidation_service.h"
10 #include "chrome/browser/invalidation/invalidation_service_factory.h"
11 #include "chrome/browser/network_time/network_time_tracker.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/sync/glue/sync_backend_host_core.h"
14 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
15 #include "chrome/browser/sync/glue/sync_frontend.h"
16 #include "chrome/browser/sync/sync_prefs.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/notification_details.h"
20 #include "content/public/browser/notification_source.h"
21 #include "sync/internal_api/public/base_transaction.h"
22 #include "sync/internal_api/public/http_bridge.h"
23 #include "sync/internal_api/public/internal_components_factory.h"
24 #include "sync/internal_api/public/internal_components_factory_impl.h"
25 #include "sync/internal_api/public/sync_manager.h"
26 #include "sync/internal_api/public/sync_manager_factory.h"
27 #include "sync/internal_api/public/util/experiments.h"
28 #include "sync/internal_api/public/util/sync_string_conversions.h"
29
30 // Helper macros to log with the syncer thread name; useful when there
31 // are multiple syncers involved.
32
33 #define SLOG(severity) LOG(severity) << name_ << ": "
34
35 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
36
37 using syncer::InternalComponentsFactory;
38
39 static const base::FilePath::CharType kSyncDataFolderName[] =
40 FILE_PATH_LITERAL("Sync Data");
41
42 namespace browser_sync {
43
44 SyncBackendHostImpl::SyncBackendHostImpl(
45 const std::string& name,
46 Profile* profile,
47 const base::WeakPtr<SyncPrefs>& sync_prefs)
48 : frontend_loop_(base::MessageLoop::current()),
49 profile_(profile),
50 name_(name),
51 initialized_(false),
52 sync_prefs_(sync_prefs),
53 frontend_(NULL),
54 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
55 invalidator_(
56 invalidation::InvalidationServiceFactory::GetForProfile(profile)),
57 invalidation_handler_registered_(false),
58 weak_ptr_factory_(this) {
59 core_ = new SyncBackendHostCore(
60 name_,
61 profile_->GetPath().Append(kSyncDataFolderName),
62 sync_prefs_->HasSyncSetupCompleted(),
63 weak_ptr_factory_.GetWeakPtr());
64 }
65
66 SyncBackendHostImpl::~SyncBackendHostImpl() {
67 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor.";
68 DCHECK(!registrar_.get());
69 }
70
71 void SyncBackendHostImpl::Initialize(
72 SyncFrontend* frontend,
73 scoped_ptr<base::Thread> sync_thread,
74 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
75 const GURL& sync_service_url,
76 const syncer::SyncCredentials& credentials,
77 bool delete_sync_data_folder,
78 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
79 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
80 syncer::ReportUnrecoverableErrorFunction
81 report_unrecoverable_error_function) {
82 registrar_.reset(new browser_sync::SyncBackendRegistrar(name_,
83 profile_,
84 sync_thread.Pass()));
85 CHECK(registrar_->sync_thread());
86
87 frontend_ = frontend;
88 DCHECK(frontend);
89
90 syncer::ModelSafeRoutingInfo routing_info;
91 std::vector<syncer::ModelSafeWorker*> workers;
92 registrar_->GetModelSafeRoutingInfo(&routing_info);
93 registrar_->GetWorkers(&workers);
94
95 InternalComponentsFactory::Switches factory_switches = {
96 InternalComponentsFactory::ENCRYPTION_KEYSTORE,
97 InternalComponentsFactory::BACKOFF_NORMAL
98 };
99
100 CommandLine* cl = CommandLine::ForCurrentProcess();
101 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) {
102 factory_switches.backoff_override =
103 InternalComponentsFactory::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE;
104 }
105 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) {
106 factory_switches.pre_commit_updates_policy =
107 InternalComponentsFactory::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE;
108 }
109
110 scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions(
111 registrar_->sync_thread()->message_loop(),
112 registrar_.get(),
113 routing_info,
114 workers,
115 extensions_activity_monitor_.GetExtensionsActivity(),
116 event_handler,
117 sync_service_url,
118 scoped_ptr<syncer::HttpPostProviderFactory>(
119 new syncer::HttpBridgeFactory(
120 make_scoped_refptr(profile_->GetRequestContext()),
121 NetworkTimeTracker::BuildNotifierUpdateCallback(),
122 core_->GetRequestContextCancelationSignal())),
123 credentials,
124 invalidator_->GetInvalidatorClientId(),
125 sync_manager_factory.Pass(),
126 delete_sync_data_folder,
127 sync_prefs_->GetEncryptionBootstrapToken(),
128 sync_prefs_->GetKeystoreEncryptionBootstrapToken(),
129 scoped_ptr<InternalComponentsFactory>(
130 new syncer::InternalComponentsFactoryImpl(factory_switches)).Pass(),
131 unrecoverable_error_handler.Pass(),
132 report_unrecoverable_error_function));
133 InitCore(init_opts.Pass());
134 }
135
136 void SyncBackendHostImpl::UpdateCredentials(
137 const syncer::SyncCredentials& credentials) {
138 DCHECK(registrar_->sync_thread()->IsRunning());
139 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
140 base::Bind(&SyncBackendHostCore::DoUpdateCredentials,
141 core_.get(),
142 credentials));
143 }
144
145 void SyncBackendHostImpl::StartSyncingWithServer() {
146 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called.";
147
148 syncer::ModelSafeRoutingInfo routing_info;
149 registrar_->GetModelSafeRoutingInfo(&routing_info);
150
151 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
152 base::Bind(&SyncBackendHostCore::DoStartSyncing,
153 core_.get(), routing_info));
154 }
155
156 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase,
157 bool is_explicit) {
158 DCHECK(registrar_->sync_thread()->IsRunning());
159 if (!IsNigoriEnabled()) {
160 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori"
161 " is disabled.";
162 return;
163 }
164
165 // We should never be called with an empty passphrase.
166 DCHECK(!passphrase.empty());
167
168 // This should only be called by the frontend.
169 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
170
171 // SetEncryptionPassphrase should never be called if we are currently
172 // encrypted with an explicit passphrase.
173 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE ||
174 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE);
175
176 // Post an encryption task on the syncer thread.
177 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
178 base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase,
179 core_.get(),
180 passphrase, is_explicit));
181 }
182
183 bool SyncBackendHostImpl::SetDecryptionPassphrase(
184 const std::string& passphrase) {
185 if (!IsNigoriEnabled()) {
186 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori"
187 " is disabled.";
188 return false;
189 }
190
191 // We should never be called with an empty passphrase.
192 DCHECK(!passphrase.empty());
193
194 // This should only be called by the frontend.
195 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
196
197 // This should only be called when we have cached pending keys.
198 DCHECK(cached_pending_keys_.has_blob());
199
200 // Check the passphrase that was provided against our local cache of the
201 // cryptographer's pending keys. If this was unsuccessful, the UI layer can
202 // immediately call OnPassphraseRequired without showing the user a spinner.
203 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase))
204 return false;
205
206 // Post a decryption task on the syncer thread.
207 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
208 base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase,
209 core_.get(),
210 passphrase));
211
212 // Since we were able to decrypt the cached pending keys with the passphrase
213 // provided, we immediately alert the UI layer that the passphrase was
214 // accepted. This will avoid the situation where a user enters a passphrase,
215 // clicks OK, immediately reopens the advanced settings dialog, and gets an
216 // unnecessary prompt for a passphrase.
217 // Note: It is not guaranteed that the passphrase will be accepted by the
218 // syncer thread, since we could receive a new nigori node while the task is
219 // pending. This scenario is a valid race, and SetDecryptionPassphrase can
220 // trigger a new OnPassphraseRequired if it needs to.
221 NotifyPassphraseAccepted();
222 return true;
223 }
224
225 void SyncBackendHostImpl::StopSyncingForShutdown() {
226 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
227
228 // Immediately stop sending messages to the frontend.
229 frontend_ = NULL;
230
231 // Stop listening for and forwarding locally-triggered sync refresh requests.
232 notification_registrar_.RemoveAll();
233
234 DCHECK(registrar_->sync_thread()->IsRunning());
235
236 registrar_->RequestWorkerStopOnUIThread();
237
238 core_->ShutdownOnUIThread();
239 }
240
241 scoped_ptr<base::Thread> SyncBackendHostImpl::Shutdown(ShutdownOption option) {
242 // StopSyncingForShutdown() (which nulls out |frontend_|) should be
243 // called first.
244 DCHECK(!frontend_);
245 DCHECK(registrar_->sync_thread()->IsRunning());
246
247 bool sync_disabled = (option == DISABLE_AND_CLAIM_THREAD);
248 bool sync_thread_claimed =
249 (option == DISABLE_AND_CLAIM_THREAD || option == STOP_AND_CLAIM_THREAD);
250
251 if (invalidation_handler_registered_) {
252 if (sync_disabled) {
253 UnregisterInvalidationIds();
254 }
255 invalidator_->UnregisterInvalidationHandler(this);
256 invalidator_ = NULL;
257 }
258 invalidation_handler_registered_ = false;
259
260 // Shut down and destroy sync manager.
261 registrar_->sync_thread()->message_loop()->PostTask(
262 FROM_HERE,
263 base::Bind(&SyncBackendHostCore::DoShutdown,
264 core_.get(), sync_disabled));
265 core_ = NULL;
266
267 // Worker cleanup.
268 SyncBackendRegistrar* detached_registrar = registrar_.release();
269 detached_registrar->sync_thread()->message_loop()->PostTask(
270 FROM_HERE,
271 base::Bind(&SyncBackendRegistrar::Shutdown,
272 base::Unretained(detached_registrar)));
273
274 if (sync_thread_claimed)
275 return detached_registrar->ReleaseSyncThread();
276 else
277 return scoped_ptr<base::Thread>();
278 }
279
280 void SyncBackendHostImpl::UnregisterInvalidationIds() {
281 if (invalidation_handler_registered_) {
282 invalidator_->UpdateRegisteredInvalidationIds(
283 this,
284 syncer::ObjectIdSet());
285 }
286 }
287
288 void SyncBackendHostImpl::ConfigureDataTypes(
289 syncer::ConfigureReason reason,
290 const DataTypeConfigStateMap& config_state_map,
291 const base::Callback<void(syncer::ModelTypeSet,
292 syncer::ModelTypeSet)>& ready_task,
293 const base::Callback<void()>& retry_callback) {
294 // Only one configure is allowed at a time. This is guaranteed by our
295 // callers. The SyncBackendHostImpl requests one configure as the backend is
296 // initializing and waits for it to complete. After initialization, all
297 // configurations will pass through the DataTypeManager, which is careful to
298 // never send a new configure request until the current request succeeds.
299
300 // The SyncBackendRegistrar's routing info will be updated by adding the
301 // types_to_add to the list then removing types_to_remove. Any types which
302 // are not in either of those sets will remain untouched.
303 //
304 // Types which were not in the list previously are not fully downloaded, so we
305 // must ask the syncer to download them. Any newly supported datatypes will
306 // not have been in that routing info list, so they will be among the types
307 // downloaded if they are enabled.
308 //
309 // The SyncBackendRegistrar's state was initially derived from the types
310 // detected to have been downloaded in the database. Afterwards it is
311 // modified only by this function. We expect it to remain in sync with the
312 // backend because configuration requests are never aborted; they are retried
313 // until they succeed or the backend is shut down.
314
315 syncer::ModelTypeSet previous_types = registrar_->GetLastConfiguredTypes();
316
317 syncer::ModelTypeSet disabled_types =
318 GetDataTypesInState(DISABLED, config_state_map);
319 syncer::ModelTypeSet fatal_types =
320 GetDataTypesInState(FATAL, config_state_map);
321 syncer::ModelTypeSet crypto_types =
322 GetDataTypesInState(CRYPTO, config_state_map);
323 disabled_types.PutAll(fatal_types);
324 disabled_types.PutAll(crypto_types);
325 syncer::ModelTypeSet active_types =
326 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
327 syncer::ModelTypeSet clean_first_types =
328 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
329 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes(
330 syncer::Union(active_types, clean_first_types),
331 disabled_types);
332 types_to_download.PutAll(clean_first_types);
333 types_to_download.RemoveAll(syncer::ProxyTypes());
334 if (!types_to_download.Empty())
335 types_to_download.Put(syncer::NIGORI);
336
337 // TODO(sync): crbug.com/137550.
338 // It's dangerous to configure types that have progress markers. Types with
339 // progress markers can trigger a MIGRATION_DONE response. We are not
340 // prepared to handle a migration during a configure, so we must ensure that
341 // all our types_to_download actually contain no data before we sync them.
342 //
343 // One common way to end up in this situation used to be types which
344 // downloaded some or all of their data but have not applied it yet. We avoid
345 // problems with those types by purging the data of any such partially synced
346 // types soon after we load the directory.
347 //
348 // Another possible scenario is that we have newly supported or newly enabled
349 // data types being downloaded here but the nigori type, which is always
350 // included in any GetUpdates request, requires migration. The server has
351 // code to detect this scenario based on the configure reason, the fact that
352 // the nigori type is the only requested type which requires migration, and
353 // that the requested types list includes at least one non-nigori type. It
354 // will not send a MIGRATION_DONE response in that case. We still need to be
355 // careful to not send progress markers for non-nigori types, though. If a
356 // non-nigori type in the request requires migration, a MIGRATION_DONE
357 // response will be sent.
358
359 syncer::ModelSafeRoutingInfo routing_info;
360 registrar_->GetModelSafeRoutingInfo(&routing_info);
361
362 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes();
363 syncer::ModelTypeSet types_to_purge =
364 syncer::Difference(previous_types, current_types);
365 syncer::ModelTypeSet inactive_types =
366 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
367 types_to_purge.RemoveAll(inactive_types);
368
369 // If a type has already been disabled and unapplied or journaled, it will
370 // not be part of the |types_to_purge| set, and therefore does not need
371 // to be acted on again.
372 fatal_types.RetainAll(types_to_purge);
373 syncer::ModelTypeSet unapply_types =
374 syncer::Union(crypto_types, clean_first_types);
375 unapply_types.RetainAll(types_to_purge);
376
377 DCHECK(syncer::Intersection(current_types, fatal_types).Empty());
378 DCHECK(syncer::Intersection(current_types, crypto_types).Empty());
379 DCHECK(current_types.HasAll(types_to_download));
380
381 SDVLOG(1) << "Types "
382 << syncer::ModelTypeSetToString(types_to_download)
383 << " added; calling DoConfigureSyncer";
384 // Divide up the types into their corresponding actions (each is mutually
385 // exclusive):
386 // - Types which have just been added to the routing info (types_to_download):
387 // are downloaded.
388 // - Types which have encountered a fatal error (fatal_types) are deleted
389 // from the directory and journaled in the delete journal.
390 // - Types which have encountered a cryptographer error (crypto_types) are
391 // unapplied (local state is purged but sync state is not).
392 // - All other types not in the routing info (types just disabled) are deleted
393 // from the directory.
394 // - Everything else (enabled types and already disabled types) is not
395 // touched.
396 RequestConfigureSyncer(reason,
397 types_to_download,
398 types_to_purge,
399 fatal_types,
400 unapply_types,
401 inactive_types,
402 routing_info,
403 ready_task,
404 retry_callback);
405 }
406
407 void SyncBackendHostImpl::EnableEncryptEverything() {
408 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
409 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything,
410 core_.get()));
411 }
412
413 void SyncBackendHostImpl::ActivateDataType(
414 syncer::ModelType type, syncer::ModelSafeGroup group,
415 ChangeProcessor* change_processor) {
416 registrar_->ActivateDataType(type, group, change_processor, GetUserShare());
417 }
418
419 void SyncBackendHostImpl::DeactivateDataType(syncer::ModelType type) {
420 registrar_->DeactivateDataType(type);
421 }
422
423 syncer::UserShare* SyncBackendHostImpl::GetUserShare() const {
424 return core_->sync_manager()->GetUserShare();
425 }
426
427 SyncBackendHostImpl::Status SyncBackendHostImpl::GetDetailedStatus() {
428 DCHECK(initialized());
429 return core_->sync_manager()->GetDetailedStatus();
430 }
431
432 syncer::sessions::SyncSessionSnapshot
433 SyncBackendHostImpl::GetLastSessionSnapshot() const {
434 return last_snapshot_;
435 }
436
437 bool SyncBackendHostImpl::HasUnsyncedItems() const {
438 DCHECK(initialized());
439 return core_->sync_manager()->HasUnsyncedItems();
440 }
441
442 bool SyncBackendHostImpl::IsNigoriEnabled() const {
443 return registrar_.get() && registrar_->IsNigoriEnabled();
444 }
445
446 syncer::PassphraseType SyncBackendHostImpl::GetPassphraseType() const {
447 return cached_passphrase_type_;
448 }
449
450 base::Time SyncBackendHostImpl::GetExplicitPassphraseTime() const {
451 return cached_explicit_passphrase_time_;
452 }
453
454 bool SyncBackendHostImpl::IsCryptographerReady(
455 const syncer::BaseTransaction* trans) const {
456 return initialized() && trans->GetCryptographer()->is_ready();
457 }
458
459 void SyncBackendHostImpl::GetModelSafeRoutingInfo(
460 syncer::ModelSafeRoutingInfo* out) const {
461 if (initialized()) {
462 CHECK(registrar_.get());
463 registrar_->GetModelSafeRoutingInfo(out);
464 } else {
465 NOTREACHED();
466 }
467 }
468
469 SyncedDeviceTracker* SyncBackendHostImpl::GetSyncedDeviceTracker() const {
470 if (!initialized())
471 return NULL;
472 return core_->synced_device_tracker();
473 }
474
475 void SyncBackendHostImpl::InitCore(scoped_ptr<DoInitializeOptions> options) {
476 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
477 base::Bind(&SyncBackendHostCore::DoInitialize,
478 core_.get(), base::Passed(&options)));
479 }
480
481 void SyncBackendHostImpl::RequestConfigureSyncer(
482 syncer::ConfigureReason reason,
483 syncer::ModelTypeSet to_download,
484 syncer::ModelTypeSet to_purge,
485 syncer::ModelTypeSet to_journal,
486 syncer::ModelTypeSet to_unapply,
487 syncer::ModelTypeSet to_ignore,
488 const syncer::ModelSafeRoutingInfo& routing_info,
489 const base::Callback<void(syncer::ModelTypeSet,
490 syncer::ModelTypeSet)>& ready_task,
491 const base::Closure& retry_callback) {
492 DoConfigureSyncerTypes config_types;
493 config_types.to_download = to_download;
494 config_types.to_purge = to_purge;
495 config_types.to_journal = to_journal;
496 config_types.to_unapply = to_unapply;
497 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
498 base::Bind(&SyncBackendHostCore::DoConfigureSyncer,
499 core_.get(),
500 reason,
501 config_types,
502 routing_info,
503 ready_task,
504 retry_callback));
505 }
506
507 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop(
508 const syncer::ModelTypeSet enabled_types,
509 const syncer::ModelTypeSet succeeded_configuration_types,
510 const syncer::ModelTypeSet failed_configuration_types,
511 const base::Callback<void(syncer::ModelTypeSet,
512 syncer::ModelTypeSet)>& ready_task) {
513 if (!frontend_)
514 return;
515
516 invalidator_->UpdateRegisteredInvalidationIds(
517 this,
518 ModelTypeSetToObjectIdSet(enabled_types));
519
520 if (!ready_task.is_null())
521 ready_task.Run(succeeded_configuration_types, failed_configuration_types);
522 }
523
524 void SyncBackendHostImpl::Observe(
525 int type,
526 const content::NotificationSource& source,
527 const content::NotificationDetails& details) {
528 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
529 DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL);
530
531 content::Details<const syncer::ModelTypeSet> state_details(details);
532 const syncer::ModelTypeSet& types = *(state_details.ptr());
533 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
534 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types));
535 }
536
537 void SyncBackendHostImpl::AddExperimentalTypes() {
538 CHECK(initialized());
539 syncer::Experiments experiments;
540 if (core_->sync_manager()->ReceivedExperiment(&experiments))
541 frontend_->OnExperimentsChanged(experiments);
542 }
543
544 void SyncBackendHostImpl::HandleControlTypesDownloadRetry() {
545 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
546 if (!frontend_)
547 return;
548
549 frontend_->OnSyncConfigureRetry();
550 }
551
552 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop(
553 const syncer::WeakHandle<syncer::JsBackend> js_backend,
554 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>
555 debug_info_listener) {
556 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
557 if (!frontend_)
558 return;
559
560 initialized_ = true;
561
562 invalidator_->RegisterInvalidationHandler(this);
563 invalidation_handler_registered_ = true;
564
565 // Fake a state change to initialize the SyncManager's cached invalidator
566 // state.
567 OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
568
569 // Start forwarding refresh requests to the SyncManager
570 notification_registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
571 content::Source<Profile>(profile_));
572
573 // Now that we've downloaded the control types, we can see if there are any
574 // experimental types to enable. This should be done before we inform
575 // the frontend to ensure they're visible in the customize screen.
576 AddExperimentalTypes();
577 frontend_->OnBackendInitialized(js_backend,
578 debug_info_listener,
579 true);
580 }
581
582 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() {
583 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
584 if (!frontend_)
585 return;
586
587 frontend_->OnBackendInitialized(
588 syncer::WeakHandle<syncer::JsBackend>(),
589 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
590 false);
591 }
592
593 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop(
594 const syncer::sessions::SyncSessionSnapshot& snapshot) {
595 if (!frontend_)
596 return;
597 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
598
599 last_snapshot_ = snapshot;
600
601 SDVLOG(1) << "Got snapshot " << snapshot.ToString();
602
603 const syncer::ModelTypeSet to_migrate =
604 snapshot.model_neutral_state().types_needing_local_migration;
605 if (!to_migrate.Empty())
606 frontend_->OnMigrationNeededForTypes(to_migrate);
607
608 // Process any changes to the datatypes we're syncing.
609 // TODO(sync): add support for removing types.
610 if (initialized())
611 AddExperimentalTypes();
612
613 if (initialized())
614 frontend_->OnSyncCycleCompleted();
615 }
616
617 void SyncBackendHostImpl::RetryConfigurationOnFrontendLoop(
618 const base::Closure& retry_callback) {
619 SDVLOG(1) << "Failed to complete configuration, informing of retry.";
620 retry_callback.Run();
621 }
622
623 void SyncBackendHostImpl::PersistEncryptionBootstrapToken(
624 const std::string& token,
625 syncer::BootstrapTokenType token_type) {
626 CHECK(sync_prefs_.get());
627 DCHECK(!token.empty());
628 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN)
629 sync_prefs_->SetEncryptionBootstrapToken(token);
630 else
631 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token);
632 }
633
634 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop(
635 const syncer::SyncProtocolError& sync_error) {
636 if (!frontend_)
637 return;
638 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
639 frontend_->OnActionableError(sync_error);
640 }
641
642 void SyncBackendHostImpl::OnInvalidatorStateChange(
643 syncer::InvalidatorState state) {
644 registrar_->sync_thread()->message_loop()->PostTask(
645 FROM_HERE,
646 base::Bind(&SyncBackendHostCore::DoOnInvalidatorStateChange,
647 core_.get(),
648 state));
649 }
650
651 void SyncBackendHostImpl::OnIncomingInvalidation(
652 const syncer::ObjectIdInvalidationMap& invalidation_map) {
653 // TODO(rlarocque): Acknowledge these invalidations only after the syncer has
654 // acted on them and saved the results to disk.
655 syncer::ObjectIdSet ids = invalidation_map.GetObjectIds();
656 for (syncer::ObjectIdSet::const_iterator it = ids.begin();
657 it != ids.end(); ++it) {
658 const syncer::AckHandle& handle =
659 invalidation_map.ForObject(*it).back().ack_handle();
660 invalidator_->AcknowledgeInvalidation(*it, handle);
661 }
662
663 registrar_->sync_thread()->message_loop()->PostTask(
664 FROM_HERE,
665 base::Bind(&SyncBackendHostCore::DoOnIncomingInvalidation,
666 core_.get(),
667 invalidation_map));
668 }
669
670 bool SyncBackendHostImpl::CheckPassphraseAgainstCachedPendingKeys(
671 const std::string& passphrase) const {
672 DCHECK(cached_pending_keys_.has_blob());
673 DCHECK(!passphrase.empty());
674 syncer::Nigori nigori;
675 nigori.InitByDerivation("localhost", "dummy", passphrase);
676 std::string plaintext;
677 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext);
678 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys.";
679 return result;
680 }
681
682 void SyncBackendHostImpl::NotifyPassphraseRequired(
683 syncer::PassphraseRequiredReason reason,
684 sync_pb::EncryptedData pending_keys) {
685 if (!frontend_)
686 return;
687
688 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
689
690 // Update our cache of the cryptographer's pending keys.
691 cached_pending_keys_ = pending_keys;
692
693 frontend_->OnPassphraseRequired(reason, pending_keys);
694 }
695
696 void SyncBackendHostImpl::NotifyPassphraseAccepted() {
697 if (!frontend_)
698 return;
699
700 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
701
702 // Clear our cache of the cryptographer's pending keys.
703 cached_pending_keys_.clear_blob();
704 frontend_->OnPassphraseAccepted();
705 }
706
707 void SyncBackendHostImpl::NotifyEncryptedTypesChanged(
708 syncer::ModelTypeSet encrypted_types,
709 bool encrypt_everything) {
710 if (!frontend_)
711 return;
712
713 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
714 frontend_->OnEncryptedTypesChanged(
715 encrypted_types, encrypt_everything);
716 }
717
718 void SyncBackendHostImpl::NotifyEncryptionComplete() {
719 if (!frontend_)
720 return;
721
722 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
723 frontend_->OnEncryptionComplete();
724 }
725
726 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop(
727 syncer::PassphraseType type,
728 base::Time explicit_passphrase_time) {
729 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
730 DVLOG(1) << "Passphrase type changed to "
731 << syncer::PassphraseTypeToString(type);
732 cached_passphrase_type_ = type;
733 cached_explicit_passphrase_time_ = explicit_passphrase_time;
734 }
735
736 void SyncBackendHostImpl::HandleStopSyncingPermanentlyOnFrontendLoop() {
737 if (!frontend_)
738 return;
739 frontend_->OnStopSyncingPermanently();
740 }
741
742 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop(
743 syncer::ConnectionStatus status) {
744 if (!frontend_)
745 return;
746
747 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
748
749 DVLOG(1) << "Connection status changed: "
750 << syncer::ConnectionStatusToString(status);
751 frontend_->OnConnectionStatusChange(status);
752 }
753
754 base::MessageLoop* SyncBackendHostImpl::GetSyncLoopForTesting() {
755 return registrar_->sync_thread()->message_loop();
756 }
757
758 } // namespace browser_sync
759
760 #undef SDVLOG
761
762 #undef SLOG
763
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/sync_backend_host_impl.h ('k') | chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698