Update V8 to version 4.6.22.
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_host_core.cc
blobc0b962cec436be26d1efced2df2e0c3313c2cdb9
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"
27 #include "url/gurl.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;
38 namespace syncer {
39 class InternalComponentsFactory;
40 } // namespace syncer
42 namespace {
44 // Enums for UMAs.
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
53 } // namespace
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),
78 registrar(registrar),
79 routing_info(routing_info),
80 workers(workers),
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)
109 : name_(name),
110 sync_data_folder_path_(sync_data_folder_path),
111 host_(backend),
112 sync_loop_(NULL),
113 registrar_(NULL),
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) {
127 if (!sync_loop_)
128 return;
129 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
131 host_.Call(
132 FROM_HERE,
133 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop,
134 snapshot);
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>&
145 debug_info_listener,
146 bool success,
147 const syncer::ModelTypeSet restored_types) {
148 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
150 if (!success) {
151 DoDestroySyncManager(syncer::STOP_SYNC);
152 host_.Call(FROM_HERE,
153 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
154 return;
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
160 // startup.
161 sync_manager_->GetEncryptionHandler()->AddObserver(this);
163 // Sync manager initialization is complete, so we can schedule recurring
164 // SaveChanges.
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",
187 backend_init_state,
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(
216 reason,
217 new_control_types,
218 types_to_purge,
219 syncer::ModelTypeSet(),
220 syncer::ModelTypeSet(),
221 routing_info,
222 base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes,
223 weak_ptr_factory_.GetWeakPtr()),
224 base::Closure());
227 void SyncBackendHostCore::OnConnectionStatusChange(
228 syncer::ConnectionStatus status) {
229 if (!sync_loop_)
230 return;
231 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
232 host_.Call(
233 FROM_HERE,
234 &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop, status);
237 void SyncBackendHostCore::OnPassphraseRequired(
238 syncer::PassphraseRequiredReason reason,
239 const sync_pb::EncryptedData& pending_keys) {
240 if (!sync_loop_)
241 return;
242 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
243 host_.Call(
244 FROM_HERE,
245 &SyncBackendHostImpl::NotifyPassphraseRequired, reason, pending_keys);
248 void SyncBackendHostCore::OnPassphraseAccepted() {
249 if (!sync_loop_)
250 return;
251 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
252 host_.Call(
253 FROM_HERE,
254 &SyncBackendHostImpl::NotifyPassphraseAccepted);
257 void SyncBackendHostCore::OnBootstrapTokenUpdated(
258 const std::string& bootstrap_token,
259 syncer::BootstrapTokenType type) {
260 if (!sync_loop_)
261 return;
262 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
263 host_.Call(FROM_HERE,
264 &SyncBackendHostImpl::PersistEncryptionBootstrapToken,
265 bootstrap_token,
266 type);
269 void SyncBackendHostCore::OnEncryptedTypesChanged(
270 syncer::ModelTypeSet encrypted_types,
271 bool encrypt_everything) {
272 if (!sync_loop_)
273 return;
274 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
275 // NOTE: We're in a transaction.
276 host_.Call(
277 FROM_HERE,
278 &SyncBackendHostImpl::NotifyEncryptedTypesChanged,
279 encrypted_types, encrypt_everything);
282 void SyncBackendHostCore::OnEncryptionComplete() {
283 if (!sync_loop_)
284 return;
285 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
286 // NOTE: We're in a transaction.
287 host_.Call(
288 FROM_HERE,
289 &SyncBackendHostImpl::NotifyEncryptionComplete);
292 void SyncBackendHostCore::OnCryptographerStateChanged(
293 syncer::Cryptographer* cryptographer) {
294 // Do nothing.
297 void SyncBackendHostCore::OnPassphraseTypeChanged(
298 syncer::PassphraseType type, base::Time passphrase_time) {
299 host_.Call(
300 FROM_HERE,
301 &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop,
302 type, passphrase_time);
305 void SyncBackendHostCore::OnLocalSetPassphraseEncryption(
306 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) {
307 host_.Call(
308 FROM_HERE,
309 &SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop,
310 nigori_state);
313 void SyncBackendHostCore::OnCommitCountersUpdated(
314 syncer::ModelType type,
315 const syncer::CommitCounters& counters) {
316 host_.Call(
317 FROM_HERE,
318 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop,
319 type, counters);
322 void SyncBackendHostCore::OnUpdateCountersUpdated(
323 syncer::ModelType type,
324 const syncer::UpdateCounters& counters) {
325 host_.Call(
326 FROM_HERE,
327 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop,
328 type, counters);
331 void SyncBackendHostCore::OnStatusCountersUpdated(
332 syncer::ModelType type,
333 const syncer::StatusCounters& counters) {
334 host_.Call(
335 FROM_HERE,
336 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop,
337 type, counters);
340 void SyncBackendHostCore::OnActionableError(
341 const syncer::SyncProtocolError& sync_error) {
342 if (!sync_loop_)
343 return;
344 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
345 host_.Call(
346 FROM_HERE,
347 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop,
348 sync_error);
351 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types) {
352 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
353 host_.Call(
354 FROM_HERE,
355 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop,
356 types);
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());
364 host_.Call(
365 FROM_HERE,
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();
383 ids_it != ids.end();
384 ++ids_it) {
385 syncer::ModelType type;
386 if (!NotificationTypeToRealModelType(ids_it->name(), &type)) {
387 DLOG(WARNING) << "Notification has invalid id: "
388 << syncer::ObjectIdToString(*ids_it);
389 } else {
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();
395 ++inv_it) {
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) {
406 DCHECK(!sync_loop_);
407 sync_loop_ = options->sync_loop;
408 DCHECK(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.";
428 DCHECK(!registrar_);
429 registrar_ = options->registrar;
430 DCHECK(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.
468 if (sync_manager_) {
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,
482 bool is_explicit) {
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";
502 host_.Call(
503 FROM_HERE,
504 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
505 return;
508 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
509 LOG(ERROR) << "Failed to download control types";
510 host_.Call(
511 FROM_HERE,
512 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
513 return;
516 host_.Call(FROM_HERE,
517 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop,
518 js_backend_,
519 debug_info_listener_,
520 sync_manager_->GetSyncContextProxy(),
521 sync_manager_->cache_guid());
523 js_backend_.Reset();
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(
531 passphrase);
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);
565 registrar_ = NULL;
567 if (reason == syncer::DISABLE_SYNC)
568 DeleteSyncDataFolder();
570 host_.Reset();
571 weak_ptr_factory_.InvalidateWeakPtrs();
574 void SyncBackendHostCore::DoDestroySyncManager(syncer::ShutdownReason reason) {
575 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
576 if (sync_manager_) {
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,
599 ready_task));
600 base::Closure chained_retry_task(
601 base::Bind(&SyncBackendHostCore::DoRetryConfiguration,
602 weak_ptr_factory_.GetWeakPtr(),
603 retry_callback));
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,
609 routing_info,
610 chained_ready_task,
611 chained_retry_task);
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,
632 enabled_types,
633 succeeded_configuration_types,
634 failed_configuration_types,
635 ready_task);
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,
643 retry_callback);
646 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() {
647 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
648 forward_protocol_events_ = true;
650 if (sync_manager_) {
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.
660 host_.Call(
661 FROM_HERE,
662 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
663 *it);
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_)
686 return;
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());
718 } else {
719 node_lists.push_back(
720 sync_manager_->GetAllNodesForType(it.Get()).release());
724 task_runner->PostTask(
725 FROM_HERE,
726 base::Bind(callback, types_vector, base::Passed(&node_lists)));
729 void SyncBackendHostCore::StartSavingChanges() {
730 // We may already be shut down.
731 if (!sync_loop_)
732 return;
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