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/location.h"
9 #include "base/metrics/histogram.h"
10 #include "base/single_thread_task_runner.h"
11 #include "chrome/browser/sync/glue/invalidation_adapter.h"
12 #include "chrome/browser/sync/glue/local_device_info_provider_impl.h"
13 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
14 #include "chrome/common/chrome_version_info.h"
15 #include "components/invalidation/public/invalidation_util.h"
16 #include "components/invalidation/public/object_id_invalidation_map.h"
17 #include "sync/internal_api/public/events/protocol_event.h"
18 #include "sync/internal_api/public/http_post_provider_factory.h"
19 #include "sync/internal_api/public/internal_components_factory.h"
20 #include "sync/internal_api/public/sessions/commit_counters.h"
21 #include "sync/internal_api/public/sessions/status_counters.h"
22 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
23 #include "sync/internal_api/public/sessions/update_counters.h"
24 #include "sync/internal_api/public/sync_context_proxy.h"
25 #include "sync/internal_api/public/sync_manager.h"
26 #include "sync/internal_api/public/sync_manager_factory.h"
29 // Helper macros to log with the syncer thread name; useful when there
30 // are multiple syncers involved.
32 #define SLOG(severity) LOG(severity) << name_ << ": "
34 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
36 static const int kSaveChangesIntervalSeconds
= 10;
39 class InternalComponentsFactory
;
45 enum SyncBackendInitState
{
46 SETUP_COMPLETED_FOUND_RESTORED_TYPES
= 0,
47 SETUP_COMPLETED_NO_RESTORED_TYPES
,
48 FIRST_SETUP_NO_RESTORED_TYPES
,
49 FIRST_SETUP_RESTORED_TYPES
,
50 SYNC_BACKEND_INIT_STATE_COUNT
55 namespace browser_sync
{
57 DoInitializeOptions::DoInitializeOptions(
58 base::MessageLoop
* sync_loop
,
59 SyncBackendRegistrar
* registrar
,
60 const syncer::ModelSafeRoutingInfo
& routing_info
,
61 const std::vector
<scoped_refptr
<syncer::ModelSafeWorker
>>& workers
,
62 const scoped_refptr
<syncer::ExtensionsActivity
>& extensions_activity
,
63 const syncer::WeakHandle
<syncer::JsEventHandler
>& event_handler
,
64 const GURL
& service_url
,
65 scoped_ptr
<syncer::HttpPostProviderFactory
> http_bridge_factory
,
66 const syncer::SyncCredentials
& credentials
,
67 const std::string
& invalidator_client_id
,
68 scoped_ptr
<syncer::SyncManagerFactory
> sync_manager_factory
,
69 bool delete_sync_data_folder
,
70 const std::string
& restored_key_for_bootstrapping
,
71 const std::string
& restored_keystore_key_for_bootstrapping
,
72 scoped_ptr
<syncer::InternalComponentsFactory
> internal_components_factory
,
73 scoped_ptr
<syncer::UnrecoverableErrorHandler
> unrecoverable_error_handler
,
74 const base::Closure
& report_unrecoverable_error_function
,
75 scoped_ptr
<syncer::SyncEncryptionHandler::NigoriState
> saved_nigori_state
,
76 syncer::PassphraseTransitionClearDataOption clear_data_option
)
77 : sync_loop(sync_loop
),
79 routing_info(routing_info
),
81 extensions_activity(extensions_activity
),
82 event_handler(event_handler
),
83 service_url(service_url
),
84 http_bridge_factory(http_bridge_factory
.Pass()),
85 credentials(credentials
),
86 invalidator_client_id(invalidator_client_id
),
87 sync_manager_factory(sync_manager_factory
.Pass()),
88 delete_sync_data_folder(delete_sync_data_folder
),
89 restored_key_for_bootstrapping(restored_key_for_bootstrapping
),
90 restored_keystore_key_for_bootstrapping(
91 restored_keystore_key_for_bootstrapping
),
92 internal_components_factory(internal_components_factory
.Pass()),
93 unrecoverable_error_handler(unrecoverable_error_handler
.Pass()),
94 report_unrecoverable_error_function(report_unrecoverable_error_function
),
95 saved_nigori_state(saved_nigori_state
.Pass()),
96 clear_data_option(clear_data_option
) {}
98 DoInitializeOptions::~DoInitializeOptions() {}
100 DoConfigureSyncerTypes::DoConfigureSyncerTypes() {}
102 DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {}
104 SyncBackendHostCore::SyncBackendHostCore(
105 const std::string
& name
,
106 const base::FilePath
& sync_data_folder_path
,
107 bool has_sync_setup_completed
,
108 const base::WeakPtr
<SyncBackendHostImpl
>& backend
)
110 sync_data_folder_path_(sync_data_folder_path
),
114 has_sync_setup_completed_(has_sync_setup_completed
),
115 forward_protocol_events_(false),
116 forward_type_info_(false),
117 weak_ptr_factory_(this) {
118 DCHECK(backend
.get());
121 SyncBackendHostCore::~SyncBackendHostCore() {
122 DCHECK(!sync_manager_
.get());
125 void SyncBackendHostCore::OnSyncCycleCompleted(
126 const syncer::sessions::SyncSessionSnapshot
& snapshot
) {
129 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
133 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop
,
137 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types
) {
138 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
139 sync_manager_
->RefreshTypes(types
);
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(syncer::STOP_SYNC
);
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_
->task_runner()->PostTask(
166 FROM_HERE
, 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()),
227 void SyncBackendHostCore::OnConnectionStatusChange(
228 syncer::ConnectionStatus status
) {
231 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
234 &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop
, status
);
237 void SyncBackendHostCore::OnPassphraseRequired(
238 syncer::PassphraseRequiredReason reason
,
239 const sync_pb::EncryptedData
& pending_keys
) {
242 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
245 &SyncBackendHostImpl::NotifyPassphraseRequired
, reason
, pending_keys
);
248 void SyncBackendHostCore::OnPassphraseAccepted() {
251 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
254 &SyncBackendHostImpl::NotifyPassphraseAccepted
);
257 void SyncBackendHostCore::OnBootstrapTokenUpdated(
258 const std::string
& bootstrap_token
,
259 syncer::BootstrapTokenType type
) {
262 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
263 host_
.Call(FROM_HERE
,
264 &SyncBackendHostImpl::PersistEncryptionBootstrapToken
,
269 void SyncBackendHostCore::OnEncryptedTypesChanged(
270 syncer::ModelTypeSet encrypted_types
,
271 bool encrypt_everything
) {
274 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
275 // NOTE: We're in a transaction.
278 &SyncBackendHostImpl::NotifyEncryptedTypesChanged
,
279 encrypted_types
, encrypt_everything
);
282 void SyncBackendHostCore::OnEncryptionComplete() {
285 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
286 // NOTE: We're in a transaction.
289 &SyncBackendHostImpl::NotifyEncryptionComplete
);
292 void SyncBackendHostCore::OnCryptographerStateChanged(
293 syncer::Cryptographer
* cryptographer
) {
297 void SyncBackendHostCore::OnPassphraseTypeChanged(
298 syncer::PassphraseType type
, base::Time passphrase_time
) {
301 &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop
,
302 type
, passphrase_time
);
305 void SyncBackendHostCore::OnLocalSetPassphraseEncryption(
306 const syncer::SyncEncryptionHandler::NigoriState
& nigori_state
) {
309 &SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop
,
313 void SyncBackendHostCore::OnCommitCountersUpdated(
314 syncer::ModelType type
,
315 const syncer::CommitCounters
& counters
) {
318 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop
,
322 void SyncBackendHostCore::OnUpdateCountersUpdated(
323 syncer::ModelType type
,
324 const syncer::UpdateCounters
& counters
) {
327 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop
,
331 void SyncBackendHostCore::OnStatusCountersUpdated(
332 syncer::ModelType type
,
333 const syncer::StatusCounters
& counters
) {
336 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop
,
340 void SyncBackendHostCore::OnActionableError(
341 const syncer::SyncProtocolError
& sync_error
) {
344 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
347 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop
,
351 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types
) {
352 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
355 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop
,
359 void SyncBackendHostCore::OnProtocolEvent(
360 const syncer::ProtocolEvent
& event
) {
361 // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr.
362 if (forward_protocol_events_
) {
363 scoped_ptr
<syncer::ProtocolEvent
> event_clone(event
.Clone());
366 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop
,
367 event_clone
.release());
371 void SyncBackendHostCore::DoOnInvalidatorStateChange(
372 syncer::InvalidatorState state
) {
373 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
374 sync_manager_
->SetInvalidatorEnabled(state
== syncer::INVALIDATIONS_ENABLED
);
377 void SyncBackendHostCore::DoOnIncomingInvalidation(
378 const syncer::ObjectIdInvalidationMap
& invalidation_map
) {
379 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
381 syncer::ObjectIdSet ids
= invalidation_map
.GetObjectIds();
382 for (syncer::ObjectIdSet::const_iterator ids_it
= ids
.begin();
385 syncer::ModelType type
;
386 if (!NotificationTypeToRealModelType(ids_it
->name(), &type
)) {
387 DLOG(WARNING
) << "Notification has invalid id: "
388 << syncer::ObjectIdToString(*ids_it
);
390 syncer::SingleObjectInvalidationSet invalidation_set
=
391 invalidation_map
.ForObject(*ids_it
);
392 for (syncer::SingleObjectInvalidationSet::const_iterator inv_it
=
393 invalidation_set
.begin();
394 inv_it
!= invalidation_set
.end();
396 scoped_ptr
<syncer::InvalidationInterface
> inv_adapter(
397 new InvalidationAdapter(*inv_it
));
398 sync_manager_
->OnIncomingInvalidation(type
, inv_adapter
.Pass());
404 void SyncBackendHostCore::DoInitialize(
405 scoped_ptr
<DoInitializeOptions
> options
) {
407 sync_loop_
= options
->sync_loop
;
410 // Finish initializing the HttpBridgeFactory. We do this here because
411 // building the user agent may block on some platforms.
412 chrome::VersionInfo version_info
;
413 options
->http_bridge_factory
->Init(
414 LocalDeviceInfoProviderImpl::MakeUserAgentForSyncApi(version_info
));
416 // Blow away the partial or corrupt sync data folder before doing any more
417 // initialization, if necessary.
418 if (options
->delete_sync_data_folder
) {
419 DeleteSyncDataFolder();
422 // Make sure that the directory exists before initializing the backend.
423 // If it already exists, this will do no harm.
424 if (!base::CreateDirectory(sync_data_folder_path_
)) {
425 DLOG(FATAL
) << "Sync Data directory creation failed.";
429 registrar_
= options
->registrar
;
432 sync_manager_
= options
->sync_manager_factory
->CreateSyncManager(name_
);
433 sync_manager_
->AddObserver(this);
435 syncer::SyncManager::InitArgs args
;
436 args
.database_location
= sync_data_folder_path_
;
437 args
.event_handler
= options
->event_handler
;
438 args
.service_url
= options
->service_url
;
439 args
.post_factory
= options
->http_bridge_factory
.Pass();
440 args
.workers
= options
->workers
;
441 args
.extensions_activity
= options
->extensions_activity
.get();
442 args
.change_delegate
= options
->registrar
; // as SyncManager::ChangeDelegate
443 args
.credentials
= options
->credentials
;
444 args
.invalidator_client_id
= options
->invalidator_client_id
;
445 args
.restored_key_for_bootstrapping
= options
->restored_key_for_bootstrapping
;
446 args
.restored_keystore_key_for_bootstrapping
=
447 options
->restored_keystore_key_for_bootstrapping
;
448 args
.internal_components_factory
=
449 options
->internal_components_factory
.Pass();
450 args
.encryptor
= &encryptor_
;
451 args
.unrecoverable_error_handler
=
452 options
->unrecoverable_error_handler
.Pass();
453 args
.report_unrecoverable_error_function
=
454 options
->report_unrecoverable_error_function
;
455 args
.cancelation_signal
= &stop_syncing_signal_
;
456 args
.saved_nigori_state
= options
->saved_nigori_state
.Pass();
457 args
.clear_data_option
= options
->clear_data_option
;
458 sync_manager_
->Init(&args
);
461 void SyncBackendHostCore::DoUpdateCredentials(
462 const syncer::SyncCredentials
& credentials
) {
463 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
464 // UpdateCredentials can be called during backend initialization, possibly
465 // when backend initialization has failed but hasn't notified the UI thread
466 // yet. In that case, the sync manager may have been destroyed on the sync
467 // thread before this task was executed, so we do nothing.
469 sync_manager_
->UpdateCredentials(credentials
);
473 void SyncBackendHostCore::DoStartSyncing(
474 const syncer::ModelSafeRoutingInfo
& routing_info
,
475 base::Time last_poll_time
) {
476 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
477 sync_manager_
->StartSyncingNormally(routing_info
, last_poll_time
);
480 void SyncBackendHostCore::DoSetEncryptionPassphrase(
481 const std::string
& passphrase
,
483 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
484 sync_manager_
->GetEncryptionHandler()->SetEncryptionPassphrase(
485 passphrase
, is_explicit
);
488 void SyncBackendHostCore::DoInitialProcessControlTypes() {
489 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
491 DVLOG(1) << "Initilalizing Control Types";
493 // Initialize encryption.
494 sync_manager_
->GetEncryptionHandler()->Init();
496 // Note: experiments are currently handled via SBH::AddExperimentalTypes,
497 // which is called at the end of every sync cycle.
498 // TODO(zea): eventually add an experiment handler and initialize it here.
500 if (!sync_manager_
->GetUserShare()) { // NULL in some tests.
501 DVLOG(1) << "Skipping initialization of DeviceInfo";
504 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop
);
508 if (!sync_manager_
->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
509 LOG(ERROR
) << "Failed to download control types";
512 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop
);
516 host_
.Call(FROM_HERE
,
517 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop
,
519 debug_info_listener_
,
520 sync_manager_
->GetSyncContextProxy(),
521 sync_manager_
->cache_guid());
524 debug_info_listener_
.Reset();
527 void SyncBackendHostCore::DoSetDecryptionPassphrase(
528 const std::string
& passphrase
) {
529 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
530 sync_manager_
->GetEncryptionHandler()->SetDecryptionPassphrase(
534 void SyncBackendHostCore::DoEnableEncryptEverything() {
535 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
536 sync_manager_
->GetEncryptionHandler()->EnableEncryptEverything();
539 void SyncBackendHostCore::ShutdownOnUIThread() {
540 // This will cut short any blocking network tasks, cut short any in-progress
541 // sync cycles, and prevent the creation of new blocking network tasks and new
542 // sync cycles. If there was an in-progress network request, it would have
543 // had a reference to the RequestContextGetter. This reference will be
544 // dropped by the time this function returns.
546 // It is safe to call this even if Sync's backend classes have not been
547 // initialized yet. Those classes will receive the message when the sync
548 // thread finally getes around to constructing them.
549 stop_syncing_signal_
.Signal();
551 // This will drop the HttpBridgeFactory's reference to the
552 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can
553 // no longer be used to create new HttpBridge instances. We can get away with
554 // this because the stop_syncing_signal_ has already been signalled, which
555 // guarantees that the ServerConnectionManager will no longer attempt to
556 // create new connections.
557 release_request_context_signal_
.Signal();
560 void SyncBackendHostCore::DoShutdown(syncer::ShutdownReason reason
) {
561 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
563 DoDestroySyncManager(reason
);
567 if (reason
== syncer::DISABLE_SYNC
)
568 DeleteSyncDataFolder();
571 weak_ptr_factory_
.InvalidateWeakPtrs();
574 void SyncBackendHostCore::DoDestroySyncManager(syncer::ShutdownReason reason
) {
575 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
577 DisableDirectoryTypeDebugInfoForwarding();
578 save_changes_timer_
.reset();
579 sync_manager_
->RemoveObserver(this);
580 sync_manager_
->ShutdownOnSyncThread(reason
);
581 sync_manager_
.reset();
585 void SyncBackendHostCore::DoConfigureSyncer(
586 syncer::ConfigureReason reason
,
587 const DoConfigureSyncerTypes
& config_types
,
588 const syncer::ModelSafeRoutingInfo routing_info
,
589 const base::Callback
<void(syncer::ModelTypeSet
,
590 syncer::ModelTypeSet
)>& ready_task
,
591 const base::Closure
& retry_callback
) {
592 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
593 DCHECK(!ready_task
.is_null());
594 DCHECK(!retry_callback
.is_null());
595 base::Closure
chained_ready_task(
596 base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes
,
597 weak_ptr_factory_
.GetWeakPtr(),
598 config_types
.to_download
,
600 base::Closure
chained_retry_task(
601 base::Bind(&SyncBackendHostCore::DoRetryConfiguration
,
602 weak_ptr_factory_
.GetWeakPtr(),
604 sync_manager_
->ConfigureSyncer(reason
,
605 config_types
.to_download
,
606 config_types
.to_purge
,
607 config_types
.to_journal
,
608 config_types
.to_unapply
,
614 void SyncBackendHostCore::DoFinishConfigureDataTypes(
615 syncer::ModelTypeSet types_to_config
,
616 const base::Callback
<void(syncer::ModelTypeSet
,
617 syncer::ModelTypeSet
)>& ready_task
) {
618 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
620 // Update the enabled types for the bridge and sync manager.
621 syncer::ModelSafeRoutingInfo routing_info
;
622 registrar_
->GetModelSafeRoutingInfo(&routing_info
);
623 syncer::ModelTypeSet enabled_types
= GetRoutingInfoTypes(routing_info
);
624 enabled_types
.RemoveAll(syncer::ProxyTypes());
626 const syncer::ModelTypeSet failed_configuration_types
=
627 Difference(types_to_config
, sync_manager_
->InitialSyncEndedTypes());
628 const syncer::ModelTypeSet succeeded_configuration_types
=
629 Difference(types_to_config
, failed_configuration_types
);
630 host_
.Call(FROM_HERE
,
631 &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop
,
633 succeeded_configuration_types
,
634 failed_configuration_types
,
638 void SyncBackendHostCore::DoRetryConfiguration(
639 const base::Closure
& retry_callback
) {
640 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
641 host_
.Call(FROM_HERE
,
642 &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop
,
646 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() {
647 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
648 forward_protocol_events_
= true;
651 // Grab our own copy of the buffered events.
652 // The buffer is not modified by this operation.
653 std::vector
<syncer::ProtocolEvent
*> buffered_events
;
654 sync_manager_
->GetBufferedProtocolEvents().release(&buffered_events
);
656 // Send them all over the fence to the host.
657 for (std::vector
<syncer::ProtocolEvent
*>::iterator it
=
658 buffered_events
.begin(); it
!= buffered_events
.end(); ++it
) {
659 // TODO(rlarocque): Make it explicit that host_ takes ownership.
662 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop
,
668 void SyncBackendHostCore::DisableProtocolEventForwarding() {
669 forward_protocol_events_
= false;
672 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() {
673 DCHECK(sync_manager_
);
675 forward_type_info_
= true;
677 if (!sync_manager_
->HasDirectoryTypeDebugInfoObserver(this))
678 sync_manager_
->RegisterDirectoryTypeDebugInfoObserver(this);
679 sync_manager_
->RequestEmitDebugInfo();
682 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() {
683 DCHECK(sync_manager_
);
685 if (!forward_type_info_
)
688 forward_type_info_
= false;
690 if (sync_manager_
->HasDirectoryTypeDebugInfoObserver(this))
691 sync_manager_
->UnregisterDirectoryTypeDebugInfoObserver(this);
694 void SyncBackendHostCore::DeleteSyncDataFolder() {
695 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
696 if (base::DirectoryExists(sync_data_folder_path_
)) {
697 if (!base::DeleteFile(sync_data_folder_path_
, true))
698 SLOG(DFATAL
) << "Could not delete the Sync Data folder.";
702 void SyncBackendHostCore::GetAllNodesForTypes(
703 syncer::ModelTypeSet types
,
704 scoped_refptr
<base::SequencedTaskRunner
> task_runner
,
705 base::Callback
<void(const std::vector
<syncer::ModelType
>& type
,
706 ScopedVector
<base::ListValue
>)> callback
) {
707 std::vector
<syncer::ModelType
> types_vector
;
708 ScopedVector
<base::ListValue
> node_lists
;
710 syncer::ModelSafeRoutingInfo routes
;
711 registrar_
->GetModelSafeRoutingInfo(&routes
);
712 syncer::ModelTypeSet enabled_types
= GetRoutingInfoTypes(routes
);
714 for (syncer::ModelTypeSet::Iterator it
= types
.First(); it
.Good(); it
.Inc()) {
715 types_vector
.push_back(it
.Get());
716 if (!enabled_types
.Has(it
.Get())) {
717 node_lists
.push_back(new base::ListValue());
719 node_lists
.push_back(
720 sync_manager_
->GetAllNodesForType(it
.Get()).release());
724 task_runner
->PostTask(
726 base::Bind(callback
, types_vector
, base::Passed(&node_lists
)));
729 void SyncBackendHostCore::StartSavingChanges() {
730 // We may already be shut down.
733 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
734 DCHECK(!save_changes_timer_
.get());
735 save_changes_timer_
.reset(new base::RepeatingTimer
<SyncBackendHostCore
>());
736 save_changes_timer_
->Start(FROM_HERE
,
737 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds
),
738 this, &SyncBackendHostCore::SaveChanges
);
741 void SyncBackendHostCore::SaveChanges() {
742 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
743 sync_manager_
->SaveChanges();
746 } // namespace browser_sync