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/command_line.h"
8 #include "base/file_util.h"
9 #include "base/metrics/histogram.h"
10 #include "chrome/browser/sync/glue/device_info.h"
11 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
12 #include "chrome/browser/sync/glue/synced_device_tracker.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "chrome/common/chrome_version_info.h"
15 #include "sync/internal_api/public/events/protocol_event.h"
16 #include "sync/internal_api/public/http_post_provider_factory.h"
17 #include "sync/internal_api/public/internal_components_factory.h"
18 #include "sync/internal_api/public/sessions/commit_counters.h"
19 #include "sync/internal_api/public/sessions/status_counters.h"
20 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
21 #include "sync/internal_api/public/sessions/update_counters.h"
22 #include "sync/internal_api/public/sync_core_proxy.h"
23 #include "sync/internal_api/public/sync_manager.h"
24 #include "sync/internal_api/public/sync_manager_factory.h"
26 // Helper macros to log with the syncer thread name; useful when there
27 // are multiple syncers involved.
29 #define SLOG(severity) LOG(severity) << name_ << ": "
31 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
33 static const int kSaveChangesIntervalSeconds = 10;
36 class InternalComponentsFactory;
42 enum SyncBackendInitState {
43 SETUP_COMPLETED_FOUND_RESTORED_TYPES = 0,
44 SETUP_COMPLETED_NO_RESTORED_TYPES,
45 FIRST_SETUP_NO_RESTORED_TYPES,
46 FIRST_SETUP_RESTORED_TYPES,
47 SYNC_BACKEND_INIT_STATE_COUNT
52 namespace browser_sync {
54 DoInitializeOptions::DoInitializeOptions(
55 base::MessageLoop* sync_loop,
56 SyncBackendRegistrar* registrar,
57 const syncer::ModelSafeRoutingInfo& routing_info,
58 const std::vector<scoped_refptr<syncer::ModelSafeWorker> >& workers,
59 const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity,
60 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
61 const GURL& service_url,
62 scoped_ptr<syncer::HttpPostProviderFactory> http_bridge_factory,
63 const syncer::SyncCredentials& credentials,
64 const std::string& invalidator_client_id,
65 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
66 bool delete_sync_data_folder,
67 const std::string& restored_key_for_bootstrapping,
68 const std::string& restored_keystore_key_for_bootstrapping,
69 scoped_ptr<syncer::InternalComponentsFactory> internal_components_factory,
70 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
71 syncer::ReportUnrecoverableErrorFunction
72 report_unrecoverable_error_function)
73 : sync_loop(sync_loop),
75 routing_info(routing_info),
77 extensions_activity(extensions_activity),
78 event_handler(event_handler),
79 service_url(service_url),
80 http_bridge_factory(http_bridge_factory.Pass()),
81 credentials(credentials),
82 invalidator_client_id(invalidator_client_id),
83 sync_manager_factory(sync_manager_factory.Pass()),
84 delete_sync_data_folder(delete_sync_data_folder),
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(
91 report_unrecoverable_error_function) {
94 DoInitializeOptions::~DoInitializeOptions() {}
96 DoConfigureSyncerTypes::DoConfigureSyncerTypes() {}
98 DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {}
100 SyncBackendHostCore::SyncBackendHostCore(
101 const std::string& name,
102 const base::FilePath& sync_data_folder_path,
103 bool has_sync_setup_completed,
104 const base::WeakPtr<SyncBackendHostImpl>& backend)
106 sync_data_folder_path_(sync_data_folder_path),
110 has_sync_setup_completed_(has_sync_setup_completed),
111 forward_protocol_events_(false),
112 weak_ptr_factory_(this) {
113 DCHECK(backend.get());
116 SyncBackendHostCore::~SyncBackendHostCore() {
117 DCHECK(!sync_manager_.get());
120 void SyncBackendHostCore::OnSyncCycleCompleted(
121 const syncer::sessions::SyncSessionSnapshot& snapshot) {
124 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
128 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop,
132 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) {
133 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
134 sync_manager_->RefreshTypes(types);
137 void SyncBackendHostCore::OnControlTypesDownloadRetry() {
138 host_.Call(FROM_HERE,
139 &SyncBackendHostImpl::HandleControlTypesDownloadRetry);
142 void SyncBackendHostCore::OnInitializationComplete(
143 const syncer::WeakHandle<syncer::JsBackend>& js_backend,
144 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
147 const syncer::ModelTypeSet restored_types) {
148 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
151 DoDestroySyncManager();
152 host_.Call(FROM_HERE,
153 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
157 // Register for encryption related changes now. We have to do this before
158 // the initializing downloading control types or initializing the encryption
159 // handler in order to receive notifications triggered during encryption
161 sync_manager_->GetEncryptionHandler()->AddObserver(this);
163 // Sync manager initialization is complete, so we can schedule recurring
165 sync_loop_->PostTask(FROM_HERE,
166 base::Bind(&SyncBackendHostCore::StartSavingChanges,
167 weak_ptr_factory_.GetWeakPtr()));
169 // Hang on to these for a while longer. We're not ready to hand them back to
170 // the UI thread yet.
171 js_backend_ = js_backend;
172 debug_info_listener_ = debug_info_listener;
174 // Track whether or not sync DB and preferences were in sync.
175 SyncBackendInitState backend_init_state;
176 if (has_sync_setup_completed_ && !restored_types.Empty()) {
177 backend_init_state = SETUP_COMPLETED_FOUND_RESTORED_TYPES;
178 } else if (has_sync_setup_completed_ && restored_types.Empty()) {
179 backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES;
180 } else if (!has_sync_setup_completed_ && restored_types.Empty()) {
181 backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES;
182 } else { // (!has_sync_setup_completed_ && !restored_types.Empty())
183 backend_init_state = FIRST_SETUP_RESTORED_TYPES;
186 UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState",
188 SYNC_BACKEND_INIT_STATE_COUNT);
190 // Before proceeding any further, we need to download the control types and
191 // purge any partial data (ie. data downloaded for a type that was on its way
192 // to being initially synced, but didn't quite make it.). The following
193 // configure cycle will take care of this. It depends on the registrar state
194 // which we initialize below to ensure that we don't perform any downloads if
195 // all control types have already completed their initial sync.
196 registrar_->SetInitialTypes(restored_types);
198 syncer::ConfigureReason reason =
199 restored_types.Empty() ?
200 syncer::CONFIGURE_REASON_NEW_CLIENT :
201 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
203 syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes(
204 syncer::ControlTypes(), syncer::ModelTypeSet());
205 syncer::ModelSafeRoutingInfo routing_info;
206 registrar_->GetModelSafeRoutingInfo(&routing_info);
207 SDVLOG(1) << "Control Types "
208 << syncer::ModelTypeSetToString(new_control_types)
209 << " added; calling ConfigureSyncer";
211 syncer::ModelTypeSet types_to_purge =
212 syncer::Difference(syncer::ModelTypeSet::All(),
213 GetRoutingInfoTypes(routing_info));
215 sync_manager_->ConfigureSyncer(
219 syncer::ModelTypeSet(),
220 syncer::ModelTypeSet(),
222 base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes,
223 weak_ptr_factory_.GetWeakPtr()),
224 base::Bind(&SyncBackendHostCore::OnControlTypesDownloadRetry,
225 weak_ptr_factory_.GetWeakPtr()));
228 void SyncBackendHostCore::OnConnectionStatusChange(
229 syncer::ConnectionStatus status) {
232 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
235 &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop, status);
238 void SyncBackendHostCore::OnPassphraseRequired(
239 syncer::PassphraseRequiredReason reason,
240 const sync_pb::EncryptedData& pending_keys) {
243 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
246 &SyncBackendHostImpl::NotifyPassphraseRequired, reason, pending_keys);
249 void SyncBackendHostCore::OnPassphraseAccepted() {
252 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
255 &SyncBackendHostImpl::NotifyPassphraseAccepted);
258 void SyncBackendHostCore::OnBootstrapTokenUpdated(
259 const std::string& bootstrap_token,
260 syncer::BootstrapTokenType type) {
263 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
264 host_.Call(FROM_HERE,
265 &SyncBackendHostImpl::PersistEncryptionBootstrapToken,
270 void SyncBackendHostCore::OnEncryptedTypesChanged(
271 syncer::ModelTypeSet encrypted_types,
272 bool encrypt_everything) {
275 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
276 // NOTE: We're in a transaction.
279 &SyncBackendHostImpl::NotifyEncryptedTypesChanged,
280 encrypted_types, encrypt_everything);
283 void SyncBackendHostCore::OnEncryptionComplete() {
286 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
287 // NOTE: We're in a transaction.
290 &SyncBackendHostImpl::NotifyEncryptionComplete);
293 void SyncBackendHostCore::OnCryptographerStateChanged(
294 syncer::Cryptographer* cryptographer) {
298 void SyncBackendHostCore::OnPassphraseTypeChanged(
299 syncer::PassphraseType type, base::Time passphrase_time) {
302 &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop,
303 type, passphrase_time);
306 void SyncBackendHostCore::OnCommitCountersUpdated(
307 syncer::ModelType type,
308 const syncer::CommitCounters& counters) {
311 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop,
315 void SyncBackendHostCore::OnUpdateCountersUpdated(
316 syncer::ModelType type,
317 const syncer::UpdateCounters& counters) {
320 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop,
324 void SyncBackendHostCore::OnStatusCountersUpdated(
325 syncer::ModelType type,
326 const syncer::StatusCounters& counters) {
329 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop,
333 void SyncBackendHostCore::OnActionableError(
334 const syncer::SyncProtocolError& sync_error) {
337 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
340 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop,
344 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types) {
345 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
348 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop,
352 void SyncBackendHostCore::OnProtocolEvent(
353 const syncer::ProtocolEvent& event) {
354 // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr.
355 if (forward_protocol_events_) {
356 scoped_ptr<syncer::ProtocolEvent> event_clone(event.Clone());
359 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
360 event_clone.release());
364 void SyncBackendHostCore::DoOnInvalidatorStateChange(
365 syncer::InvalidatorState state) {
366 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
367 sync_manager_->OnInvalidatorStateChange(state);
370 void SyncBackendHostCore::DoOnIncomingInvalidation(
371 const syncer::ObjectIdInvalidationMap& invalidation_map) {
372 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
373 sync_manager_->OnIncomingInvalidation(invalidation_map);
376 void SyncBackendHostCore::DoInitialize(
377 scoped_ptr<DoInitializeOptions> options) {
379 sync_loop_ = options->sync_loop;
382 // Finish initializing the HttpBridgeFactory. We do this here because
383 // building the user agent may block on some platforms.
384 chrome::VersionInfo version_info;
385 options->http_bridge_factory->Init(
386 DeviceInfo::MakeUserAgentForSyncApi(version_info));
388 // Blow away the partial or corrupt sync data folder before doing any more
389 // initialization, if necessary.
390 if (options->delete_sync_data_folder) {
391 DeleteSyncDataFolder();
394 // Make sure that the directory exists before initializing the backend.
395 // If it already exists, this will do no harm.
396 if (!base::CreateDirectory(sync_data_folder_path_)) {
397 DLOG(FATAL) << "Sync Data directory creation failed.";
401 registrar_ = options->registrar;
404 sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_);
405 sync_manager_->AddObserver(this);
406 sync_manager_->Init(sync_data_folder_path_,
407 options->event_handler,
408 options->service_url.host() + options->service_url.path(),
409 options->service_url.EffectiveIntPort(),
410 options->service_url.SchemeIsSecure(),
411 options->http_bridge_factory.Pass(),
413 options->extensions_activity,
414 options->registrar /* as SyncManager::ChangeDelegate */,
415 options->credentials,
416 options->invalidator_client_id,
417 options->restored_key_for_bootstrapping,
418 options->restored_keystore_key_for_bootstrapping,
419 options->internal_components_factory.get(),
421 options->unrecoverable_error_handler.Pass(),
422 options->report_unrecoverable_error_function,
423 &stop_syncing_signal_);
425 // |sync_manager_| may end up being NULL here in tests (in
426 // synchronous initialization mode).
428 // TODO(akalin): Fix this behavior (see http://crbug.com/140354).
430 // Now check the command line to see if we need to simulate an
431 // unrecoverable error for testing purpose. Note the error is thrown
432 // only if the initialization succeeded. Also it makes sense to use this
433 // flag only when restarting the browser with an account already setup. If
434 // you use this before setting up the setup would not succeed as an error
435 // would be encountered.
436 if (CommandLine::ForCurrentProcess()->HasSwitch(
437 switches::kSyncThrowUnrecoverableError)) {
438 sync_manager_->ThrowUnrecoverableError();
443 void SyncBackendHostCore::DoUpdateCredentials(
444 const syncer::SyncCredentials& credentials) {
445 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
446 // UpdateCredentials can be called during backend initialization, possibly
447 // when backend initialization has failed but hasn't notified the UI thread
448 // yet. In that case, the sync manager may have been destroyed on the sync
449 // thread before this task was executed, so we do nothing.
451 sync_manager_->UpdateCredentials(credentials);
455 void SyncBackendHostCore::DoStartSyncing(
456 const syncer::ModelSafeRoutingInfo& routing_info) {
457 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
458 sync_manager_->StartSyncingNormally(routing_info);
461 void SyncBackendHostCore::DoSetEncryptionPassphrase(
462 const std::string& passphrase,
464 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
465 sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(
466 passphrase, is_explicit);
469 void SyncBackendHostCore::DoInitialProcessControlTypes() {
470 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
472 DVLOG(1) << "Initilalizing Control Types";
474 // Initialize encryption.
475 sync_manager_->GetEncryptionHandler()->Init();
477 // Note: experiments are currently handled via SBH::AddExperimentalTypes,
478 // which is called at the end of every sync cycle.
479 // TODO(zea): eventually add an experiment handler and initialize it here.
481 if (!sync_manager_->GetUserShare()) { // NULL in some tests.
482 DVLOG(1) << "Skipping initialization of DeviceInfo";
485 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
489 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
490 LOG(ERROR) << "Failed to download control types";
493 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
497 // Initialize device info. This is asynchronous on some platforms, so we
498 // provide a callback for when it finishes.
499 synced_device_tracker_.reset(
500 new SyncedDeviceTracker(sync_manager_->GetUserShare(),
501 sync_manager_->cache_guid()));
502 synced_device_tracker_->InitLocalDeviceInfo(
503 base::Bind(&SyncBackendHostCore::DoFinishInitialProcessControlTypes,
504 weak_ptr_factory_.GetWeakPtr()));
507 void SyncBackendHostCore::DoFinishInitialProcessControlTypes() {
508 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
510 registrar_->ActivateDataType(syncer::DEVICE_INFO,
511 syncer::GROUP_PASSIVE,
512 synced_device_tracker_.get(),
513 sync_manager_->GetUserShare());
517 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop,
519 debug_info_listener_,
520 sync_manager_->GetSyncCoreProxy());
523 debug_info_listener_.Reset();
526 void SyncBackendHostCore::DoSetDecryptionPassphrase(
527 const std::string& passphrase) {
528 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
529 sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(
533 void SyncBackendHostCore::DoEnableEncryptEverything() {
534 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
535 sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
538 void SyncBackendHostCore::ShutdownOnUIThread() {
539 // This will cut short any blocking network tasks, cut short any in-progress
540 // sync cycles, and prevent the creation of new blocking network tasks and new
541 // sync cycles. If there was an in-progress network request, it would have
542 // had a reference to the RequestContextGetter. This reference will be
543 // dropped by the time this function returns.
545 // It is safe to call this even if Sync's backend classes have not been
546 // initialized yet. Those classes will receive the message when the sync
547 // thread finally getes around to constructing them.
548 stop_syncing_signal_.Signal();
550 // This will drop the HttpBridgeFactory's reference to the
551 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can
552 // no longer be used to create new HttpBridge instances. We can get away with
553 // this because the stop_syncing_signal_ has already been signalled, which
554 // guarantees that the ServerConnectionManager will no longer attempt to
555 // create new connections.
556 release_request_context_signal_.Signal();
559 void SyncBackendHostCore::DoShutdown(bool sync_disabled) {
560 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
562 // It's safe to do this even if the type was never activated.
563 registrar_->DeactivateDataType(syncer::DEVICE_INFO);
564 synced_device_tracker_.reset();
566 DoDestroySyncManager();
571 DeleteSyncDataFolder();
574 weak_ptr_factory_.InvalidateWeakPtrs();
577 void SyncBackendHostCore::DoDestroySyncManager() {
578 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
580 save_changes_timer_.reset();
581 DisableDirectoryTypeDebugInfoForwarding();
582 sync_manager_->RemoveObserver(this);
583 sync_manager_->ShutdownOnSyncThread();
584 sync_manager_.reset();
588 void SyncBackendHostCore::DoConfigureSyncer(
589 syncer::ConfigureReason reason,
590 const DoConfigureSyncerTypes& config_types,
591 const syncer::ModelSafeRoutingInfo routing_info,
592 const base::Callback<void(syncer::ModelTypeSet,
593 syncer::ModelTypeSet)>& ready_task,
594 const base::Closure& retry_callback) {
595 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
596 sync_manager_->ConfigureSyncer(
598 config_types.to_download,
599 config_types.to_purge,
600 config_types.to_journal,
601 config_types.to_unapply,
603 base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes,
604 weak_ptr_factory_.GetWeakPtr(),
605 config_types.to_download,
607 base::Bind(&SyncBackendHostCore::DoRetryConfiguration,
608 weak_ptr_factory_.GetWeakPtr(),
612 void SyncBackendHostCore::DoFinishConfigureDataTypes(
613 syncer::ModelTypeSet types_to_config,
614 const base::Callback<void(syncer::ModelTypeSet,
615 syncer::ModelTypeSet)>& ready_task) {
616 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
618 // Update the enabled types for the bridge and sync manager.
619 syncer::ModelSafeRoutingInfo routing_info;
620 registrar_->GetModelSafeRoutingInfo(&routing_info);
621 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
622 enabled_types.RemoveAll(syncer::ProxyTypes());
624 const syncer::ModelTypeSet failed_configuration_types =
625 Difference(types_to_config, sync_manager_->InitialSyncEndedTypes());
626 const syncer::ModelTypeSet succeeded_configuration_types =
627 Difference(types_to_config, failed_configuration_types);
628 host_.Call(FROM_HERE,
629 &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop,
631 succeeded_configuration_types,
632 failed_configuration_types,
636 void SyncBackendHostCore::DoRetryConfiguration(
637 const base::Closure& retry_callback) {
638 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
639 host_.Call(FROM_HERE,
640 &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop,
644 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() {
645 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
646 forward_protocol_events_ = true;
649 // Grab our own copy of the buffered events.
650 // The buffer is not modified by this operation.
651 std::vector<syncer::ProtocolEvent*> buffered_events;
652 sync_manager_->GetBufferedProtocolEvents().release(&buffered_events);
654 // Send them all over the fence to the host.
655 for (std::vector<syncer::ProtocolEvent*>::iterator it =
656 buffered_events.begin(); it != buffered_events.end(); ++it) {
657 // TODO(rlarocque): Make it explicit that host_ takes ownership.
660 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
666 void SyncBackendHostCore::DisableProtocolEventForwarding() {
667 forward_protocol_events_ = false;
670 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() {
671 DCHECK(sync_manager_);
672 if (!sync_manager_->HasDirectoryTypeDebugInfoObserver(this))
673 sync_manager_->RegisterDirectoryTypeDebugInfoObserver(this);
674 sync_manager_->RequestEmitDebugInfo();
677 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() {
678 DCHECK(sync_manager_);
679 if (sync_manager_->HasDirectoryTypeDebugInfoObserver(this))
680 sync_manager_->UnregisterDirectoryTypeDebugInfoObserver(this);
683 void SyncBackendHostCore::DeleteSyncDataFolder() {
684 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
685 if (base::DirectoryExists(sync_data_folder_path_)) {
686 if (!base::DeleteFile(sync_data_folder_path_, true))
687 SLOG(DFATAL) << "Could not delete the Sync Data folder.";
691 void SyncBackendHostCore::GetAllNodesForTypes(
692 syncer::ModelTypeSet types,
693 scoped_refptr<base::SequencedTaskRunner> task_runner,
694 base::Callback<void(const std::vector<syncer::ModelType>& type,
695 ScopedVector<base::ListValue>)> callback) {
696 std::vector<syncer::ModelType> types_vector;
697 ScopedVector<base::ListValue> node_lists;
699 syncer::ModelSafeRoutingInfo routes;
700 registrar_->GetModelSafeRoutingInfo(&routes);
701 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routes);
703 for (syncer::ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
704 types_vector.push_back(it.Get());
705 if (!enabled_types.Has(it.Get())) {
706 node_lists.push_back(new base::ListValue());
708 node_lists.push_back(
709 sync_manager_->GetAllNodesForType(it.Get()).release());
713 task_runner->PostTask(
715 base::Bind(callback, types_vector, base::Passed(&node_lists)));
718 void SyncBackendHostCore::StartSavingChanges() {
719 // We may already be shut down.
722 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
723 DCHECK(!save_changes_timer_.get());
724 save_changes_timer_.reset(new base::RepeatingTimer<SyncBackendHostCore>());
725 save_changes_timer_->Start(FROM_HERE,
726 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
727 this, &SyncBackendHostCore::SaveChanges);
730 void SyncBackendHostCore::SaveChanges() {
731 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
732 sync_manager_->SaveChanges();
735 } // namespace browser_sync