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 "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_context_proxy.h"
23 #include "sync/internal_api/public/sync_manager.h"
24 #include "sync/internal_api/public/sync_manager_factory.h"
27 // Helper macros to log with the syncer thread name; useful when there
28 // are multiple syncers involved.
30 #define SLOG(severity) LOG(severity) << name_ << ": "
32 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
34 static const int kSaveChangesIntervalSeconds
= 10;
37 class InternalComponentsFactory
;
43 enum SyncBackendInitState
{
44 SETUP_COMPLETED_FOUND_RESTORED_TYPES
= 0,
45 SETUP_COMPLETED_NO_RESTORED_TYPES
,
46 FIRST_SETUP_NO_RESTORED_TYPES
,
47 FIRST_SETUP_RESTORED_TYPES
,
48 SYNC_BACKEND_INIT_STATE_COUNT
53 namespace browser_sync
{
55 DoInitializeOptions::DoInitializeOptions(
56 base::MessageLoop
* sync_loop
,
57 SyncBackendRegistrar
* registrar
,
58 const syncer::ModelSafeRoutingInfo
& routing_info
,
59 const std::vector
<scoped_refptr
<syncer::ModelSafeWorker
> >& workers
,
60 const scoped_refptr
<syncer::ExtensionsActivity
>& extensions_activity
,
61 const syncer::WeakHandle
<syncer::JsEventHandler
>& event_handler
,
62 const GURL
& service_url
,
63 scoped_ptr
<syncer::HttpPostProviderFactory
> http_bridge_factory
,
64 const syncer::SyncCredentials
& credentials
,
65 const std::string
& invalidator_client_id
,
66 scoped_ptr
<syncer::SyncManagerFactory
> sync_manager_factory
,
67 bool delete_sync_data_folder
,
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
),
76 routing_info(routing_info
),
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 delete_sync_data_folder(delete_sync_data_folder
),
86 restored_key_for_bootstrapping(restored_key_for_bootstrapping
),
87 restored_keystore_key_for_bootstrapping(
88 restored_keystore_key_for_bootstrapping
),
89 internal_components_factory(internal_components_factory
.Pass()),
90 unrecoverable_error_handler(unrecoverable_error_handler
.Pass()),
91 report_unrecoverable_error_function(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 forward_type_info_(false),
113 weak_ptr_factory_(this) {
114 DCHECK(backend
.get());
117 SyncBackendHostCore::~SyncBackendHostCore() {
118 DCHECK(!sync_manager_
.get());
121 void SyncBackendHostCore::OnSyncCycleCompleted(
122 const syncer::sessions::SyncSessionSnapshot
& snapshot
) {
125 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
129 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop
,
133 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types
) {
134 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
135 sync_manager_
->RefreshTypes(types
);
138 void SyncBackendHostCore::OnInitializationComplete(
139 const syncer::WeakHandle
<syncer::JsBackend
>& js_backend
,
140 const syncer::WeakHandle
<syncer::DataTypeDebugInfoListener
>&
143 const syncer::ModelTypeSet restored_types
) {
144 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
147 DoDestroySyncManager(syncer::STOP_SYNC
);
148 host_
.Call(FROM_HERE
,
149 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop
);
153 // Register for encryption related changes now. We have to do this before
154 // the initializing downloading control types or initializing the encryption
155 // handler in order to receive notifications triggered during encryption
157 sync_manager_
->GetEncryptionHandler()->AddObserver(this);
159 // Sync manager initialization is complete, so we can schedule recurring
161 sync_loop_
->PostTask(FROM_HERE
,
162 base::Bind(&SyncBackendHostCore::StartSavingChanges
,
163 weak_ptr_factory_
.GetWeakPtr()));
165 // Hang on to these for a while longer. We're not ready to hand them back to
166 // the UI thread yet.
167 js_backend_
= js_backend
;
168 debug_info_listener_
= debug_info_listener
;
170 // Track whether or not sync DB and preferences were in sync.
171 SyncBackendInitState backend_init_state
;
172 if (has_sync_setup_completed_
&& !restored_types
.Empty()) {
173 backend_init_state
= SETUP_COMPLETED_FOUND_RESTORED_TYPES
;
174 } else if (has_sync_setup_completed_
&& restored_types
.Empty()) {
175 backend_init_state
= SETUP_COMPLETED_NO_RESTORED_TYPES
;
176 } else if (!has_sync_setup_completed_
&& restored_types
.Empty()) {
177 backend_init_state
= FIRST_SETUP_NO_RESTORED_TYPES
;
178 } else { // (!has_sync_setup_completed_ && !restored_types.Empty())
179 backend_init_state
= FIRST_SETUP_RESTORED_TYPES
;
182 UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState",
184 SYNC_BACKEND_INIT_STATE_COUNT
);
186 // Before proceeding any further, we need to download the control types and
187 // purge any partial data (ie. data downloaded for a type that was on its way
188 // to being initially synced, but didn't quite make it.). The following
189 // configure cycle will take care of this. It depends on the registrar state
190 // which we initialize below to ensure that we don't perform any downloads if
191 // all control types have already completed their initial sync.
192 registrar_
->SetInitialTypes(restored_types
);
194 syncer::ConfigureReason reason
=
195 restored_types
.Empty() ?
196 syncer::CONFIGURE_REASON_NEW_CLIENT
:
197 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE
;
199 syncer::ModelTypeSet new_control_types
= registrar_
->ConfigureDataTypes(
200 syncer::ControlTypes(), syncer::ModelTypeSet());
201 syncer::ModelSafeRoutingInfo routing_info
;
202 registrar_
->GetModelSafeRoutingInfo(&routing_info
);
203 SDVLOG(1) << "Control Types "
204 << syncer::ModelTypeSetToString(new_control_types
)
205 << " added; calling ConfigureSyncer";
207 syncer::ModelTypeSet types_to_purge
=
208 syncer::Difference(syncer::ModelTypeSet::All(),
209 GetRoutingInfoTypes(routing_info
));
211 sync_manager_
->ConfigureSyncer(
215 syncer::ModelTypeSet(),
216 syncer::ModelTypeSet(),
218 base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes
,
219 weak_ptr_factory_
.GetWeakPtr()),
223 void SyncBackendHostCore::OnConnectionStatusChange(
224 syncer::ConnectionStatus status
) {
227 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
230 &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop
, status
);
233 void SyncBackendHostCore::OnPassphraseRequired(
234 syncer::PassphraseRequiredReason reason
,
235 const sync_pb::EncryptedData
& pending_keys
) {
238 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
241 &SyncBackendHostImpl::NotifyPassphraseRequired
, reason
, pending_keys
);
244 void SyncBackendHostCore::OnPassphraseAccepted() {
247 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
250 &SyncBackendHostImpl::NotifyPassphraseAccepted
);
253 void SyncBackendHostCore::OnBootstrapTokenUpdated(
254 const std::string
& bootstrap_token
,
255 syncer::BootstrapTokenType type
) {
258 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
259 host_
.Call(FROM_HERE
,
260 &SyncBackendHostImpl::PersistEncryptionBootstrapToken
,
265 void SyncBackendHostCore::OnEncryptedTypesChanged(
266 syncer::ModelTypeSet encrypted_types
,
267 bool encrypt_everything
) {
270 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
271 // NOTE: We're in a transaction.
274 &SyncBackendHostImpl::NotifyEncryptedTypesChanged
,
275 encrypted_types
, encrypt_everything
);
278 void SyncBackendHostCore::OnEncryptionComplete() {
281 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
282 // NOTE: We're in a transaction.
285 &SyncBackendHostImpl::NotifyEncryptionComplete
);
288 void SyncBackendHostCore::OnCryptographerStateChanged(
289 syncer::Cryptographer
* cryptographer
) {
293 void SyncBackendHostCore::OnPassphraseTypeChanged(
294 syncer::PassphraseType type
, base::Time passphrase_time
) {
297 &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop
,
298 type
, passphrase_time
);
301 void SyncBackendHostCore::OnCommitCountersUpdated(
302 syncer::ModelType type
,
303 const syncer::CommitCounters
& counters
) {
306 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop
,
310 void SyncBackendHostCore::OnUpdateCountersUpdated(
311 syncer::ModelType type
,
312 const syncer::UpdateCounters
& counters
) {
315 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop
,
319 void SyncBackendHostCore::OnStatusCountersUpdated(
320 syncer::ModelType type
,
321 const syncer::StatusCounters
& counters
) {
324 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop
,
328 void SyncBackendHostCore::OnActionableError(
329 const syncer::SyncProtocolError
& sync_error
) {
332 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
335 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop
,
339 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types
) {
340 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
343 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop
,
347 void SyncBackendHostCore::OnProtocolEvent(
348 const syncer::ProtocolEvent
& event
) {
349 // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr.
350 if (forward_protocol_events_
) {
351 scoped_ptr
<syncer::ProtocolEvent
> event_clone(event
.Clone());
354 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop
,
355 event_clone
.release());
359 void SyncBackendHostCore::DoOnInvalidatorStateChange(
360 syncer::InvalidatorState state
) {
361 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
362 sync_manager_
->SetInvalidatorEnabled(state
== syncer::INVALIDATIONS_ENABLED
);
365 void SyncBackendHostCore::DoOnIncomingInvalidation(
366 const syncer::ObjectIdInvalidationMap
& invalidation_map
) {
367 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
369 syncer::ObjectIdSet ids
= invalidation_map
.GetObjectIds();
370 for (syncer::ObjectIdSet::const_iterator ids_it
= ids
.begin();
373 syncer::ModelType type
;
374 if (!NotificationTypeToRealModelType(ids_it
->name(), &type
)) {
375 DLOG(WARNING
) << "Notification has invalid id: "
376 << syncer::ObjectIdToString(*ids_it
);
378 syncer::SingleObjectInvalidationSet invalidation_set
=
379 invalidation_map
.ForObject(*ids_it
);
380 for (syncer::SingleObjectInvalidationSet::const_iterator inv_it
=
381 invalidation_set
.begin();
382 inv_it
!= invalidation_set
.end();
384 scoped_ptr
<syncer::InvalidationInterface
> inv_adapter(
385 new InvalidationAdapter(*inv_it
));
386 sync_manager_
->OnIncomingInvalidation(type
, inv_adapter
.Pass());
392 void SyncBackendHostCore::DoInitialize(
393 scoped_ptr
<DoInitializeOptions
> options
) {
395 sync_loop_
= options
->sync_loop
;
398 // Finish initializing the HttpBridgeFactory. We do this here because
399 // building the user agent may block on some platforms.
400 chrome::VersionInfo version_info
;
401 options
->http_bridge_factory
->Init(
402 LocalDeviceInfoProviderImpl::MakeUserAgentForSyncApi(version_info
));
404 // Blow away the partial or corrupt sync data folder before doing any more
405 // initialization, if necessary.
406 if (options
->delete_sync_data_folder
) {
407 DeleteSyncDataFolder();
410 // Make sure that the directory exists before initializing the backend.
411 // If it already exists, this will do no harm.
412 if (!base::CreateDirectory(sync_data_folder_path_
)) {
413 DLOG(FATAL
) << "Sync Data directory creation failed.";
417 registrar_
= options
->registrar
;
420 sync_manager_
= options
->sync_manager_factory
->CreateSyncManager(name_
);
421 sync_manager_
->AddObserver(this);
423 syncer::SyncManager::InitArgs args
;
424 args
.database_location
= sync_data_folder_path_
;
425 args
.event_handler
= options
->event_handler
;
426 args
.service_url
= options
->service_url
;
427 args
.post_factory
= options
->http_bridge_factory
.Pass();
428 args
.workers
= options
->workers
;
429 args
.extensions_activity
= options
->extensions_activity
.get();
430 args
.change_delegate
= options
->registrar
; // as SyncManager::ChangeDelegate
431 args
.credentials
= options
->credentials
;
432 args
.invalidator_client_id
= options
->invalidator_client_id
;
433 args
.restored_key_for_bootstrapping
= options
->restored_key_for_bootstrapping
;
434 args
.restored_keystore_key_for_bootstrapping
=
435 options
->restored_keystore_key_for_bootstrapping
;
436 args
.internal_components_factory
=
437 options
->internal_components_factory
.Pass();
438 args
.encryptor
= &encryptor_
;
439 args
.unrecoverable_error_handler
=
440 options
->unrecoverable_error_handler
.Pass();
441 args
.report_unrecoverable_error_function
=
442 options
->report_unrecoverable_error_function
;
443 args
.cancelation_signal
= &stop_syncing_signal_
;
444 sync_manager_
->Init(&args
);
447 void SyncBackendHostCore::DoUpdateCredentials(
448 const syncer::SyncCredentials
& credentials
) {
449 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
450 // UpdateCredentials can be called during backend initialization, possibly
451 // when backend initialization has failed but hasn't notified the UI thread
452 // yet. In that case, the sync manager may have been destroyed on the sync
453 // thread before this task was executed, so we do nothing.
455 sync_manager_
->UpdateCredentials(credentials
);
459 void SyncBackendHostCore::DoStartSyncing(
460 const syncer::ModelSafeRoutingInfo
& routing_info
) {
461 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
462 sync_manager_
->StartSyncingNormally(routing_info
);
465 void SyncBackendHostCore::DoSetEncryptionPassphrase(
466 const std::string
& passphrase
,
468 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
469 sync_manager_
->GetEncryptionHandler()->SetEncryptionPassphrase(
470 passphrase
, is_explicit
);
473 void SyncBackendHostCore::DoInitialProcessControlTypes() {
474 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
476 DVLOG(1) << "Initilalizing Control Types";
478 // Initialize encryption.
479 sync_manager_
->GetEncryptionHandler()->Init();
481 // Note: experiments are currently handled via SBH::AddExperimentalTypes,
482 // which is called at the end of every sync cycle.
483 // TODO(zea): eventually add an experiment handler and initialize it here.
485 if (!sync_manager_
->GetUserShare()) { // NULL in some tests.
486 DVLOG(1) << "Skipping initialization of DeviceInfo";
489 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop
);
493 if (!sync_manager_
->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
494 LOG(ERROR
) << "Failed to download control types";
497 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop
);
501 host_
.Call(FROM_HERE
,
502 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop
,
504 debug_info_listener_
,
505 sync_manager_
->GetSyncContextProxy(),
506 sync_manager_
->cache_guid());
509 debug_info_listener_
.Reset();
512 void SyncBackendHostCore::DoSetDecryptionPassphrase(
513 const std::string
& passphrase
) {
514 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
515 sync_manager_
->GetEncryptionHandler()->SetDecryptionPassphrase(
519 void SyncBackendHostCore::DoEnableEncryptEverything() {
520 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
521 sync_manager_
->GetEncryptionHandler()->EnableEncryptEverything();
524 void SyncBackendHostCore::ShutdownOnUIThread() {
525 // This will cut short any blocking network tasks, cut short any in-progress
526 // sync cycles, and prevent the creation of new blocking network tasks and new
527 // sync cycles. If there was an in-progress network request, it would have
528 // had a reference to the RequestContextGetter. This reference will be
529 // dropped by the time this function returns.
531 // It is safe to call this even if Sync's backend classes have not been
532 // initialized yet. Those classes will receive the message when the sync
533 // thread finally getes around to constructing them.
534 stop_syncing_signal_
.Signal();
536 // This will drop the HttpBridgeFactory's reference to the
537 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can
538 // no longer be used to create new HttpBridge instances. We can get away with
539 // this because the stop_syncing_signal_ has already been signalled, which
540 // guarantees that the ServerConnectionManager will no longer attempt to
541 // create new connections.
542 release_request_context_signal_
.Signal();
545 void SyncBackendHostCore::DoShutdown(syncer::ShutdownReason reason
) {
546 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
548 DoDestroySyncManager(reason
);
552 if (reason
== syncer::DISABLE_SYNC
)
553 DeleteSyncDataFolder();
556 weak_ptr_factory_
.InvalidateWeakPtrs();
559 void SyncBackendHostCore::DoDestroySyncManager(syncer::ShutdownReason reason
) {
560 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
562 DisableDirectoryTypeDebugInfoForwarding();
563 save_changes_timer_
.reset();
564 sync_manager_
->RemoveObserver(this);
565 sync_manager_
->ShutdownOnSyncThread(reason
);
566 sync_manager_
.reset();
570 void SyncBackendHostCore::DoConfigureSyncer(
571 syncer::ConfigureReason reason
,
572 const DoConfigureSyncerTypes
& config_types
,
573 const syncer::ModelSafeRoutingInfo routing_info
,
574 const base::Callback
<void(syncer::ModelTypeSet
,
575 syncer::ModelTypeSet
)>& ready_task
,
576 const base::Closure
& retry_callback
) {
577 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
578 DCHECK(!ready_task
.is_null());
579 DCHECK(!retry_callback
.is_null());
580 base::Closure
chained_ready_task(
581 base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes
,
582 weak_ptr_factory_
.GetWeakPtr(),
583 config_types
.to_download
,
585 base::Closure
chained_retry_task(
586 base::Bind(&SyncBackendHostCore::DoRetryConfiguration
,
587 weak_ptr_factory_
.GetWeakPtr(),
589 sync_manager_
->ConfigureSyncer(reason
,
590 config_types
.to_download
,
591 config_types
.to_purge
,
592 config_types
.to_journal
,
593 config_types
.to_unapply
,
599 void SyncBackendHostCore::DoFinishConfigureDataTypes(
600 syncer::ModelTypeSet types_to_config
,
601 const base::Callback
<void(syncer::ModelTypeSet
,
602 syncer::ModelTypeSet
)>& ready_task
) {
603 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
605 // Update the enabled types for the bridge and sync manager.
606 syncer::ModelSafeRoutingInfo routing_info
;
607 registrar_
->GetModelSafeRoutingInfo(&routing_info
);
608 syncer::ModelTypeSet enabled_types
= GetRoutingInfoTypes(routing_info
);
609 enabled_types
.RemoveAll(syncer::ProxyTypes());
611 const syncer::ModelTypeSet failed_configuration_types
=
612 Difference(types_to_config
, sync_manager_
->InitialSyncEndedTypes());
613 const syncer::ModelTypeSet succeeded_configuration_types
=
614 Difference(types_to_config
, failed_configuration_types
);
615 host_
.Call(FROM_HERE
,
616 &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop
,
618 succeeded_configuration_types
,
619 failed_configuration_types
,
623 void SyncBackendHostCore::DoRetryConfiguration(
624 const base::Closure
& retry_callback
) {
625 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
626 host_
.Call(FROM_HERE
,
627 &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop
,
631 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() {
632 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
633 forward_protocol_events_
= true;
636 // Grab our own copy of the buffered events.
637 // The buffer is not modified by this operation.
638 std::vector
<syncer::ProtocolEvent
*> buffered_events
;
639 sync_manager_
->GetBufferedProtocolEvents().release(&buffered_events
);
641 // Send them all over the fence to the host.
642 for (std::vector
<syncer::ProtocolEvent
*>::iterator it
=
643 buffered_events
.begin(); it
!= buffered_events
.end(); ++it
) {
644 // TODO(rlarocque): Make it explicit that host_ takes ownership.
647 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop
,
653 void SyncBackendHostCore::DisableProtocolEventForwarding() {
654 forward_protocol_events_
= false;
657 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() {
658 DCHECK(sync_manager_
);
660 forward_type_info_
= true;
662 if (!sync_manager_
->HasDirectoryTypeDebugInfoObserver(this))
663 sync_manager_
->RegisterDirectoryTypeDebugInfoObserver(this);
664 sync_manager_
->RequestEmitDebugInfo();
667 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() {
668 DCHECK(sync_manager_
);
670 if (!forward_type_info_
)
673 forward_type_info_
= false;
675 if (sync_manager_
->HasDirectoryTypeDebugInfoObserver(this))
676 sync_manager_
->UnregisterDirectoryTypeDebugInfoObserver(this);
679 void SyncBackendHostCore::DeleteSyncDataFolder() {
680 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
681 if (base::DirectoryExists(sync_data_folder_path_
)) {
682 if (!base::DeleteFile(sync_data_folder_path_
, true))
683 SLOG(DFATAL
) << "Could not delete the Sync Data folder.";
687 void SyncBackendHostCore::GetAllNodesForTypes(
688 syncer::ModelTypeSet types
,
689 scoped_refptr
<base::SequencedTaskRunner
> task_runner
,
690 base::Callback
<void(const std::vector
<syncer::ModelType
>& type
,
691 ScopedVector
<base::ListValue
>)> callback
) {
692 std::vector
<syncer::ModelType
> types_vector
;
693 ScopedVector
<base::ListValue
> node_lists
;
695 syncer::ModelSafeRoutingInfo routes
;
696 registrar_
->GetModelSafeRoutingInfo(&routes
);
697 syncer::ModelTypeSet enabled_types
= GetRoutingInfoTypes(routes
);
699 for (syncer::ModelTypeSet::Iterator it
= types
.First(); it
.Good(); it
.Inc()) {
700 types_vector
.push_back(it
.Get());
701 if (!enabled_types
.Has(it
.Get())) {
702 node_lists
.push_back(new base::ListValue());
704 node_lists
.push_back(
705 sync_manager_
->GetAllNodesForType(it
.Get()).release());
709 task_runner
->PostTask(
711 base::Bind(callback
, types_vector
, base::Passed(&node_lists
)));
714 void SyncBackendHostCore::StartSavingChanges() {
715 // We may already be shut down.
718 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
719 DCHECK(!save_changes_timer_
.get());
720 save_changes_timer_
.reset(new base::RepeatingTimer
<SyncBackendHostCore
>());
721 save_changes_timer_
->Start(FROM_HERE
,
722 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds
),
723 this, &SyncBackendHostCore::SaveChanges
);
726 void SyncBackendHostCore::SaveChanges() {
727 DCHECK_EQ(base::MessageLoop::current(), sync_loop_
);
728 sync_manager_
->SaveChanges();
731 } // namespace browser_sync