Make sure the sync directory is deleted on sign-out.
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_host_core.cc
blob372128e4c84485cec74d6f54577f691083c38aea
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_core.h"
7 #include "base/files/file_util.h"
8 #include "base/metrics/histogram.h"
9 #include "chrome/browser/sync/glue/invalidation_adapter.h"
10 #include "chrome/browser/sync/glue/local_device_info_provider_impl.h"
11 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
12 #include "chrome/common/chrome_version_info.h"
13 #include "components/invalidation/invalidation_util.h"
14 #include "components/invalidation/object_id_invalidation_map.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "sync/internal_api/public/events/protocol_event.h"
17 #include "sync/internal_api/public/http_post_provider_factory.h"
18 #include "sync/internal_api/public/internal_components_factory.h"
19 #include "sync/internal_api/public/sessions/commit_counters.h"
20 #include "sync/internal_api/public/sessions/status_counters.h"
21 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
22 #include "sync/internal_api/public/sessions/update_counters.h"
23 #include "sync/internal_api/public/sync_context_proxy.h"
24 #include "sync/internal_api/public/sync_manager.h"
25 #include "sync/internal_api/public/sync_manager_factory.h"
26 #include "url/gurl.h"
28 // Helper macros to log with the syncer thread name; useful when there
29 // are multiple syncers involved.
31 #define SLOG(severity) LOG(severity) << name_ << ": "
33 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
35 static const int kSaveChangesIntervalSeconds = 10;
37 namespace syncer {
38 class InternalComponentsFactory;
39 } // namespace syncer
41 namespace {
43 // Enums for UMAs.
44 enum SyncBackendInitState {
45 SETUP_COMPLETED_FOUND_RESTORED_TYPES = 0,
46 SETUP_COMPLETED_NO_RESTORED_TYPES,
47 FIRST_SETUP_NO_RESTORED_TYPES,
48 FIRST_SETUP_RESTORED_TYPES,
49 SYNC_BACKEND_INIT_STATE_COUNT
52 } // namespace
54 namespace browser_sync {
56 DoInitializeOptions::DoInitializeOptions(
57 base::MessageLoop* sync_loop,
58 SyncBackendRegistrar* registrar,
59 const syncer::ModelSafeRoutingInfo& routing_info,
60 const std::vector<scoped_refptr<syncer::ModelSafeWorker> >& workers,
61 const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity,
62 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
63 const GURL& service_url,
64 scoped_ptr<syncer::HttpPostProviderFactory> http_bridge_factory,
65 const syncer::SyncCredentials& credentials,
66 const std::string& invalidator_client_id,
67 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
68 const std::string& restored_key_for_bootstrapping,
69 const std::string& restored_keystore_key_for_bootstrapping,
70 scoped_ptr<syncer::InternalComponentsFactory> internal_components_factory,
71 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
72 syncer::ReportUnrecoverableErrorFunction
73 report_unrecoverable_error_function)
74 : sync_loop(sync_loop),
75 registrar(registrar),
76 routing_info(routing_info),
77 workers(workers),
78 extensions_activity(extensions_activity),
79 event_handler(event_handler),
80 service_url(service_url),
81 http_bridge_factory(http_bridge_factory.Pass()),
82 credentials(credentials),
83 invalidator_client_id(invalidator_client_id),
84 sync_manager_factory(sync_manager_factory.Pass()),
85 restored_key_for_bootstrapping(restored_key_for_bootstrapping),
86 restored_keystore_key_for_bootstrapping(
87 restored_keystore_key_for_bootstrapping),
88 internal_components_factory(internal_components_factory.Pass()),
89 unrecoverable_error_handler(unrecoverable_error_handler.Pass()),
90 report_unrecoverable_error_function(report_unrecoverable_error_function) {
93 DoInitializeOptions::~DoInitializeOptions() {}
95 DoConfigureSyncerTypes::DoConfigureSyncerTypes() {}
97 DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {}
99 SyncBackendHostCore::SyncBackendHostCore(
100 const std::string& name,
101 const base::FilePath& directory_path,
102 bool has_sync_setup_completed,
103 const base::WeakPtr<SyncBackendHostImpl>& backend)
104 : name_(name),
105 directory_path_(directory_path),
106 host_(backend),
107 sync_loop_(NULL),
108 registrar_(NULL),
109 has_sync_setup_completed_(has_sync_setup_completed),
110 forward_protocol_events_(false),
111 forward_type_info_(false),
112 weak_ptr_factory_(this) {
113 DCHECK(backend.get());
116 SyncBackendHostCore::~SyncBackendHostCore() {
117 DCHECK(!sync_manager_.get());
120 void SyncBackendHostCore::Initialize(scoped_ptr<DoInitializeOptions> options) {
121 content::BrowserThread::PostTask(content::BrowserThread::FILE,
122 FROM_HERE, base::Bind(
123 &SyncBackendHostCore::CreateDirectoryAndDoInitialize, this,
124 base::Passed(&options)));
127 void SyncBackendHostCore::CreateDirectoryAndDoInitialize(
128 scoped_ptr<DoInitializeOptions> options) {
129 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
130 if (!base::CreateDirectory(directory_path_)) {
131 DLOG(FATAL) << "Sync Data directory creation failed.";
133 // We need to extract the loop pointer on a separate line because on
134 // Windows the options pointer gets Passed() first.
135 base::MessageLoop* sync_loop = options->sync_loop;
136 sync_loop->PostTask(FROM_HERE, base::Bind(
137 &SyncBackendHostCore::DoInitialize, this, base::Passed(&options)));
140 void SyncBackendHostCore::OnSyncCycleCompleted(
141 const syncer::sessions::SyncSessionSnapshot& snapshot) {
142 if (!sync_loop_)
143 return;
144 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
146 host_.Call(
147 FROM_HERE,
148 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop,
149 snapshot);
152 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) {
153 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
154 sync_manager_->RefreshTypes(types);
157 void SyncBackendHostCore::OnInitializationComplete(
158 const syncer::WeakHandle<syncer::JsBackend>& js_backend,
159 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
160 debug_info_listener,
161 bool success,
162 const syncer::ModelTypeSet restored_types) {
163 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
165 if (!success) {
166 DoDestroySyncManager(syncer::STOP_SYNC);
167 host_.Call(FROM_HERE,
168 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
169 return;
172 // Register for encryption related changes now. We have to do this before
173 // the initializing downloading control types or initializing the encryption
174 // handler in order to receive notifications triggered during encryption
175 // startup.
176 sync_manager_->GetEncryptionHandler()->AddObserver(this);
178 // Sync manager initialization is complete, so we can schedule recurring
179 // SaveChanges.
180 sync_loop_->PostTask(FROM_HERE,
181 base::Bind(&SyncBackendHostCore::StartSavingChanges,
182 weak_ptr_factory_.GetWeakPtr()));
184 // Hang on to these for a while longer. We're not ready to hand them back to
185 // the UI thread yet.
186 js_backend_ = js_backend;
187 debug_info_listener_ = debug_info_listener;
189 // Track whether or not sync DB and preferences were in sync.
190 SyncBackendInitState backend_init_state;
191 if (has_sync_setup_completed_ && !restored_types.Empty()) {
192 backend_init_state = SETUP_COMPLETED_FOUND_RESTORED_TYPES;
193 } else if (has_sync_setup_completed_ && restored_types.Empty()) {
194 backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES;
195 } else if (!has_sync_setup_completed_ && restored_types.Empty()) {
196 backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES;
197 } else { // (!has_sync_setup_completed_ && !restored_types.Empty())
198 backend_init_state = FIRST_SETUP_RESTORED_TYPES;
201 UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState",
202 backend_init_state,
203 SYNC_BACKEND_INIT_STATE_COUNT);
205 // Before proceeding any further, we need to download the control types and
206 // purge any partial data (ie. data downloaded for a type that was on its way
207 // to being initially synced, but didn't quite make it.). The following
208 // configure cycle will take care of this. It depends on the registrar state
209 // which we initialize below to ensure that we don't perform any downloads if
210 // all control types have already completed their initial sync.
211 registrar_->SetInitialTypes(restored_types);
213 syncer::ConfigureReason reason =
214 restored_types.Empty() ?
215 syncer::CONFIGURE_REASON_NEW_CLIENT :
216 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
218 syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes(
219 syncer::ControlTypes(), syncer::ModelTypeSet());
220 syncer::ModelSafeRoutingInfo routing_info;
221 registrar_->GetModelSafeRoutingInfo(&routing_info);
222 SDVLOG(1) << "Control Types "
223 << syncer::ModelTypeSetToString(new_control_types)
224 << " added; calling ConfigureSyncer";
226 syncer::ModelTypeSet types_to_purge =
227 syncer::Difference(syncer::ModelTypeSet::All(),
228 GetRoutingInfoTypes(routing_info));
230 sync_manager_->ConfigureSyncer(
231 reason,
232 new_control_types,
233 types_to_purge,
234 syncer::ModelTypeSet(),
235 syncer::ModelTypeSet(),
236 routing_info,
237 base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes,
238 weak_ptr_factory_.GetWeakPtr()),
239 base::Closure());
242 void SyncBackendHostCore::OnConnectionStatusChange(
243 syncer::ConnectionStatus status) {
244 if (!sync_loop_)
245 return;
246 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
247 host_.Call(
248 FROM_HERE,
249 &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop, status);
252 void SyncBackendHostCore::OnPassphraseRequired(
253 syncer::PassphraseRequiredReason reason,
254 const sync_pb::EncryptedData& pending_keys) {
255 if (!sync_loop_)
256 return;
257 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
258 host_.Call(
259 FROM_HERE,
260 &SyncBackendHostImpl::NotifyPassphraseRequired, reason, pending_keys);
263 void SyncBackendHostCore::OnPassphraseAccepted() {
264 if (!sync_loop_)
265 return;
266 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
267 host_.Call(
268 FROM_HERE,
269 &SyncBackendHostImpl::NotifyPassphraseAccepted);
272 void SyncBackendHostCore::OnBootstrapTokenUpdated(
273 const std::string& bootstrap_token,
274 syncer::BootstrapTokenType type) {
275 if (!sync_loop_)
276 return;
277 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
278 host_.Call(FROM_HERE,
279 &SyncBackendHostImpl::PersistEncryptionBootstrapToken,
280 bootstrap_token,
281 type);
284 void SyncBackendHostCore::OnEncryptedTypesChanged(
285 syncer::ModelTypeSet encrypted_types,
286 bool encrypt_everything) {
287 if (!sync_loop_)
288 return;
289 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
290 // NOTE: We're in a transaction.
291 host_.Call(
292 FROM_HERE,
293 &SyncBackendHostImpl::NotifyEncryptedTypesChanged,
294 encrypted_types, encrypt_everything);
297 void SyncBackendHostCore::OnEncryptionComplete() {
298 if (!sync_loop_)
299 return;
300 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
301 // NOTE: We're in a transaction.
302 host_.Call(
303 FROM_HERE,
304 &SyncBackendHostImpl::NotifyEncryptionComplete);
307 void SyncBackendHostCore::OnCryptographerStateChanged(
308 syncer::Cryptographer* cryptographer) {
309 // Do nothing.
312 void SyncBackendHostCore::OnPassphraseTypeChanged(
313 syncer::PassphraseType type, base::Time passphrase_time) {
314 host_.Call(
315 FROM_HERE,
316 &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop,
317 type, passphrase_time);
320 void SyncBackendHostCore::OnCommitCountersUpdated(
321 syncer::ModelType type,
322 const syncer::CommitCounters& counters) {
323 host_.Call(
324 FROM_HERE,
325 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop,
326 type, counters);
329 void SyncBackendHostCore::OnUpdateCountersUpdated(
330 syncer::ModelType type,
331 const syncer::UpdateCounters& counters) {
332 host_.Call(
333 FROM_HERE,
334 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop,
335 type, counters);
338 void SyncBackendHostCore::OnStatusCountersUpdated(
339 syncer::ModelType type,
340 const syncer::StatusCounters& counters) {
341 host_.Call(
342 FROM_HERE,
343 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop,
344 type, counters);
347 void SyncBackendHostCore::OnActionableError(
348 const syncer::SyncProtocolError& sync_error) {
349 if (!sync_loop_)
350 return;
351 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
352 host_.Call(
353 FROM_HERE,
354 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop,
355 sync_error);
358 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types) {
359 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
360 host_.Call(
361 FROM_HERE,
362 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop,
363 types);
366 void SyncBackendHostCore::OnProtocolEvent(
367 const syncer::ProtocolEvent& event) {
368 // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr.
369 if (forward_protocol_events_) {
370 scoped_ptr<syncer::ProtocolEvent> event_clone(event.Clone());
371 host_.Call(
372 FROM_HERE,
373 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
374 event_clone.release());
378 void SyncBackendHostCore::DoOnInvalidatorStateChange(
379 syncer::InvalidatorState state) {
380 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
381 sync_manager_->SetInvalidatorEnabled(state == syncer::INVALIDATIONS_ENABLED);
384 void SyncBackendHostCore::DoOnIncomingInvalidation(
385 const syncer::ObjectIdInvalidationMap& invalidation_map) {
386 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
388 syncer::ObjectIdSet ids = invalidation_map.GetObjectIds();
389 for (syncer::ObjectIdSet::const_iterator ids_it = ids.begin();
390 ids_it != ids.end();
391 ++ids_it) {
392 syncer::ModelType type;
393 if (!NotificationTypeToRealModelType(ids_it->name(), &type)) {
394 DLOG(WARNING) << "Notification has invalid id: "
395 << syncer::ObjectIdToString(*ids_it);
396 } else {
397 syncer::SingleObjectInvalidationSet invalidation_set =
398 invalidation_map.ForObject(*ids_it);
399 for (syncer::SingleObjectInvalidationSet::const_iterator inv_it =
400 invalidation_set.begin();
401 inv_it != invalidation_set.end();
402 ++inv_it) {
403 scoped_ptr<syncer::InvalidationInterface> inv_adapter(
404 new InvalidationAdapter(*inv_it));
405 sync_manager_->OnIncomingInvalidation(type, inv_adapter.Pass());
411 void SyncBackendHostCore::DoInitialize(
412 scoped_ptr<DoInitializeOptions> options) {
413 DCHECK(!sync_loop_);
414 sync_loop_ = options->sync_loop;
415 DCHECK(sync_loop_);
417 // Finish initializing the HttpBridgeFactory. We do this here because
418 // building the user agent may block on some platforms.
419 chrome::VersionInfo version_info;
420 options->http_bridge_factory->Init(
421 LocalDeviceInfoProviderImpl::MakeUserAgentForSyncApi(version_info));
423 DCHECK(!registrar_);
424 registrar_ = options->registrar;
425 DCHECK(registrar_);
427 sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_);
428 sync_manager_->AddObserver(this);
430 syncer::SyncManager::InitArgs args;
431 args.database_location = directory_path_;
432 args.event_handler = options->event_handler;
433 args.service_url = options->service_url;
434 args.post_factory = options->http_bridge_factory.Pass();
435 args.workers = options->workers;
436 args.extensions_activity = options->extensions_activity.get();
437 args.change_delegate = options->registrar; // as SyncManager::ChangeDelegate
438 args.credentials = options->credentials;
439 args.invalidator_client_id = options->invalidator_client_id;
440 args.restored_key_for_bootstrapping = options->restored_key_for_bootstrapping;
441 args.restored_keystore_key_for_bootstrapping =
442 options->restored_keystore_key_for_bootstrapping;
443 args.internal_components_factory =
444 options->internal_components_factory.Pass();
445 args.encryptor = &encryptor_;
446 args.unrecoverable_error_handler =
447 options->unrecoverable_error_handler.Pass();
448 args.report_unrecoverable_error_function =
449 options->report_unrecoverable_error_function;
450 args.cancelation_signal = &stop_syncing_signal_;
451 sync_manager_->Init(&args);
454 void SyncBackendHostCore::DoUpdateCredentials(
455 const syncer::SyncCredentials& credentials) {
456 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
457 // UpdateCredentials can be called during backend initialization, possibly
458 // when backend initialization has failed but hasn't notified the UI thread
459 // yet. In that case, the sync manager may have been destroyed on the sync
460 // thread before this task was executed, so we do nothing.
461 if (sync_manager_) {
462 sync_manager_->UpdateCredentials(credentials);
466 void SyncBackendHostCore::DoStartSyncing(
467 const syncer::ModelSafeRoutingInfo& routing_info) {
468 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
469 sync_manager_->StartSyncingNormally(routing_info);
472 void SyncBackendHostCore::DoSetEncryptionPassphrase(
473 const std::string& passphrase,
474 bool is_explicit) {
475 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
476 sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(
477 passphrase, is_explicit);
480 void SyncBackendHostCore::DoInitialProcessControlTypes() {
481 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
483 DVLOG(1) << "Initilalizing Control Types";
485 // Initialize encryption.
486 sync_manager_->GetEncryptionHandler()->Init();
488 // Note: experiments are currently handled via SBH::AddExperimentalTypes,
489 // which is called at the end of every sync cycle.
490 // TODO(zea): eventually add an experiment handler and initialize it here.
492 if (!sync_manager_->GetUserShare()) { // NULL in some tests.
493 DVLOG(1) << "Skipping initialization of DeviceInfo";
494 host_.Call(
495 FROM_HERE,
496 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
497 return;
500 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
501 LOG(ERROR) << "Failed to download control types";
502 host_.Call(
503 FROM_HERE,
504 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
505 return;
508 host_.Call(FROM_HERE,
509 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop,
510 js_backend_,
511 debug_info_listener_,
512 sync_manager_->GetSyncContextProxy(),
513 sync_manager_->cache_guid());
515 js_backend_.Reset();
516 debug_info_listener_.Reset();
519 void SyncBackendHostCore::DoSetDecryptionPassphrase(
520 const std::string& passphrase) {
521 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
522 sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(
523 passphrase);
526 void SyncBackendHostCore::DoEnableEncryptEverything() {
527 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
528 sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
531 void SyncBackendHostCore::ShutdownOnUIThread() {
532 // This will cut short any blocking network tasks, cut short any in-progress
533 // sync cycles, and prevent the creation of new blocking network tasks and new
534 // sync cycles. If there was an in-progress network request, it would have
535 // had a reference to the RequestContextGetter. This reference will be
536 // dropped by the time this function returns.
538 // It is safe to call this even if Sync's backend classes have not been
539 // initialized yet. Those classes will receive the message when the sync
540 // thread finally getes around to constructing them.
541 stop_syncing_signal_.Signal();
543 // This will drop the HttpBridgeFactory's reference to the
544 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can
545 // no longer be used to create new HttpBridge instances. We can get away with
546 // this because the stop_syncing_signal_ has already been signalled, which
547 // guarantees that the ServerConnectionManager will no longer attempt to
548 // create new connections.
549 release_request_context_signal_.Signal();
552 void SyncBackendHostCore::DoShutdown(syncer::ShutdownReason reason) {
553 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
555 DoDestroySyncManager(reason);
557 registrar_ = NULL;
559 host_.Reset();
560 weak_ptr_factory_.InvalidateWeakPtrs();
563 void SyncBackendHostCore::DoDestroySyncManager(syncer::ShutdownReason reason) {
564 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
565 if (sync_manager_) {
566 DisableDirectoryTypeDebugInfoForwarding();
567 save_changes_timer_.reset();
568 sync_manager_->RemoveObserver(this);
569 sync_manager_->ShutdownOnSyncThread(reason);
570 sync_manager_.reset();
574 void SyncBackendHostCore::DoConfigureSyncer(
575 syncer::ConfigureReason reason,
576 const DoConfigureSyncerTypes& config_types,
577 const syncer::ModelSafeRoutingInfo routing_info,
578 const base::Callback<void(syncer::ModelTypeSet,
579 syncer::ModelTypeSet)>& ready_task,
580 const base::Closure& retry_callback) {
581 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
582 DCHECK(!ready_task.is_null());
583 DCHECK(!retry_callback.is_null());
584 base::Closure chained_ready_task(
585 base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes,
586 weak_ptr_factory_.GetWeakPtr(),
587 config_types.to_download,
588 ready_task));
589 base::Closure chained_retry_task(
590 base::Bind(&SyncBackendHostCore::DoRetryConfiguration,
591 weak_ptr_factory_.GetWeakPtr(),
592 retry_callback));
593 sync_manager_->ConfigureSyncer(reason,
594 config_types.to_download,
595 config_types.to_purge,
596 config_types.to_journal,
597 config_types.to_unapply,
598 routing_info,
599 chained_ready_task,
600 chained_retry_task);
603 void SyncBackendHostCore::DoFinishConfigureDataTypes(
604 syncer::ModelTypeSet types_to_config,
605 const base::Callback<void(syncer::ModelTypeSet,
606 syncer::ModelTypeSet)>& ready_task) {
607 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
609 // Update the enabled types for the bridge and sync manager.
610 syncer::ModelSafeRoutingInfo routing_info;
611 registrar_->GetModelSafeRoutingInfo(&routing_info);
612 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
613 enabled_types.RemoveAll(syncer::ProxyTypes());
615 const syncer::ModelTypeSet failed_configuration_types =
616 Difference(types_to_config, sync_manager_->InitialSyncEndedTypes());
617 const syncer::ModelTypeSet succeeded_configuration_types =
618 Difference(types_to_config, failed_configuration_types);
619 host_.Call(FROM_HERE,
620 &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop,
621 enabled_types,
622 succeeded_configuration_types,
623 failed_configuration_types,
624 ready_task);
627 void SyncBackendHostCore::DoRetryConfiguration(
628 const base::Closure& retry_callback) {
629 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
630 host_.Call(FROM_HERE,
631 &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop,
632 retry_callback);
635 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() {
636 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
637 forward_protocol_events_ = true;
639 if (sync_manager_) {
640 // Grab our own copy of the buffered events.
641 // The buffer is not modified by this operation.
642 std::vector<syncer::ProtocolEvent*> buffered_events;
643 sync_manager_->GetBufferedProtocolEvents().release(&buffered_events);
645 // Send them all over the fence to the host.
646 for (std::vector<syncer::ProtocolEvent*>::iterator it =
647 buffered_events.begin(); it != buffered_events.end(); ++it) {
648 // TODO(rlarocque): Make it explicit that host_ takes ownership.
649 host_.Call(
650 FROM_HERE,
651 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
652 *it);
657 void SyncBackendHostCore::DisableProtocolEventForwarding() {
658 forward_protocol_events_ = false;
661 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() {
662 DCHECK(sync_manager_);
664 forward_type_info_ = true;
666 if (!sync_manager_->HasDirectoryTypeDebugInfoObserver(this))
667 sync_manager_->RegisterDirectoryTypeDebugInfoObserver(this);
668 sync_manager_->RequestEmitDebugInfo();
671 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() {
672 DCHECK(sync_manager_);
674 if (!forward_type_info_)
675 return;
677 forward_type_info_ = false;
679 if (sync_manager_->HasDirectoryTypeDebugInfoObserver(this))
680 sync_manager_->UnregisterDirectoryTypeDebugInfoObserver(this);
683 void SyncBackendHostCore::GetAllNodesForTypes(
684 syncer::ModelTypeSet types,
685 scoped_refptr<base::SequencedTaskRunner> task_runner,
686 base::Callback<void(const std::vector<syncer::ModelType>& type,
687 ScopedVector<base::ListValue>)> callback) {
688 std::vector<syncer::ModelType> types_vector;
689 ScopedVector<base::ListValue> node_lists;
691 syncer::ModelSafeRoutingInfo routes;
692 registrar_->GetModelSafeRoutingInfo(&routes);
693 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routes);
695 for (syncer::ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
696 types_vector.push_back(it.Get());
697 if (!enabled_types.Has(it.Get())) {
698 node_lists.push_back(new base::ListValue());
699 } else {
700 node_lists.push_back(
701 sync_manager_->GetAllNodesForType(it.Get()).release());
705 task_runner->PostTask(
706 FROM_HERE,
707 base::Bind(callback, types_vector, base::Passed(&node_lists)));
710 void SyncBackendHostCore::StartSavingChanges() {
711 // We may already be shut down.
712 if (!sync_loop_)
713 return;
714 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
715 DCHECK(!save_changes_timer_.get());
716 save_changes_timer_.reset(new base::RepeatingTimer<SyncBackendHostCore>());
717 save_changes_timer_->Start(FROM_HERE,
718 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
719 this, &SyncBackendHostCore::SaveChanges);
722 void SyncBackendHostCore::SaveChanges() {
723 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
724 sync_manager_->SaveChanges();
727 } // namespace browser_sync