Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_host_core.cc
blob4634c8178ddffb403b7909aadeda6c360d15e29c
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/local_device_info_provider_impl.h"
12 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
13 #include "components/invalidation/public/invalidation_util.h"
14 #include "components/invalidation/public/object_id_invalidation_map.h"
15 #include "components/sync_driver/invalidation_adapter.h"
16 #include "sync/internal_api/public/events/protocol_event.h"
17 #include "sync/internal_api/public/http_post_provider_factory.h"
18 #include "sync/internal_api/public/internal_components_factory.h"
19 #include "sync/internal_api/public/sessions/commit_counters.h"
20 #include "sync/internal_api/public/sessions/status_counters.h"
21 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
22 #include "sync/internal_api/public/sessions/update_counters.h"
23 #include "sync/internal_api/public/sync_context_proxy.h"
24 #include "sync/internal_api/public/sync_manager.h"
25 #include "sync/internal_api/public/sync_manager_factory.h"
26 #include "url/gurl.h"
28 // Helper macros to log with the syncer thread name; useful when there
29 // are multiple syncers involved.
31 #define SLOG(severity) LOG(severity) << name_ << ": "
33 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
35 static const int kSaveChangesIntervalSeconds = 10;
37 namespace syncer {
38 class InternalComponentsFactory;
39 } // namespace syncer
41 namespace {
43 // Enums for UMAs.
44 enum SyncBackendInitState {
45 SETUP_COMPLETED_FOUND_RESTORED_TYPES = 0,
46 SETUP_COMPLETED_NO_RESTORED_TYPES,
47 FIRST_SETUP_NO_RESTORED_TYPES,
48 FIRST_SETUP_RESTORED_TYPES,
49 SYNC_BACKEND_INIT_STATE_COUNT
52 } // namespace
54 namespace browser_sync {
56 DoInitializeOptions::DoInitializeOptions(
57 base::MessageLoop* sync_loop,
58 SyncBackendRegistrar* registrar,
59 const syncer::ModelSafeRoutingInfo& routing_info,
60 const std::vector<scoped_refptr<syncer::ModelSafeWorker>>& workers,
61 const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity,
62 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
63 const GURL& service_url,
64 const std::string& sync_user_agent,
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 const syncer::WeakHandle<syncer::UnrecoverableErrorHandler>&
74 unrecoverable_error_handler,
75 const base::Closure& report_unrecoverable_error_function,
76 scoped_ptr<syncer::SyncEncryptionHandler::NigoriState> saved_nigori_state,
77 syncer::PassphraseTransitionClearDataOption clear_data_option,
78 const std::map<syncer::ModelType, int64>& invalidation_versions)
79 : sync_loop(sync_loop),
80 registrar(registrar),
81 routing_info(routing_info),
82 workers(workers),
83 extensions_activity(extensions_activity),
84 event_handler(event_handler),
85 service_url(service_url),
86 sync_user_agent(sync_user_agent),
87 http_bridge_factory(http_bridge_factory.Pass()),
88 credentials(credentials),
89 invalidator_client_id(invalidator_client_id),
90 sync_manager_factory(sync_manager_factory.Pass()),
91 delete_sync_data_folder(delete_sync_data_folder),
92 restored_key_for_bootstrapping(restored_key_for_bootstrapping),
93 restored_keystore_key_for_bootstrapping(
94 restored_keystore_key_for_bootstrapping),
95 internal_components_factory(internal_components_factory.Pass()),
96 unrecoverable_error_handler(unrecoverable_error_handler),
97 report_unrecoverable_error_function(report_unrecoverable_error_function),
98 saved_nigori_state(saved_nigori_state.Pass()),
99 clear_data_option(clear_data_option),
100 invalidation_versions(invalidation_versions) {}
102 DoInitializeOptions::~DoInitializeOptions() {}
104 DoConfigureSyncerTypes::DoConfigureSyncerTypes() {}
106 DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {}
108 SyncBackendHostCore::SyncBackendHostCore(
109 const std::string& name,
110 const base::FilePath& sync_data_folder_path,
111 bool has_sync_setup_completed,
112 const base::WeakPtr<SyncBackendHostImpl>& backend)
113 : name_(name),
114 sync_data_folder_path_(sync_data_folder_path),
115 host_(backend),
116 sync_loop_(NULL),
117 registrar_(NULL),
118 has_sync_setup_completed_(has_sync_setup_completed),
119 forward_protocol_events_(false),
120 forward_type_info_(false),
121 weak_ptr_factory_(this) {
122 DCHECK(backend.get());
125 SyncBackendHostCore::~SyncBackendHostCore() {
126 DCHECK(!sync_manager_.get());
129 void SyncBackendHostCore::OnSyncCycleCompleted(
130 const syncer::sessions::SyncSessionSnapshot& snapshot) {
131 if (!sync_loop_)
132 return;
133 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
135 host_.Call(
136 FROM_HERE,
137 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop,
138 snapshot);
141 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) {
142 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
143 sync_manager_->RefreshTypes(types);
146 void SyncBackendHostCore::OnInitializationComplete(
147 const syncer::WeakHandle<syncer::JsBackend>& js_backend,
148 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
149 debug_info_listener,
150 bool success,
151 const syncer::ModelTypeSet restored_types) {
152 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
154 if (!success) {
155 DoDestroySyncManager(syncer::STOP_SYNC);
156 host_.Call(FROM_HERE,
157 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
158 return;
161 // Register for encryption related changes now. We have to do this before
162 // the initializing downloading control types or initializing the encryption
163 // handler in order to receive notifications triggered during encryption
164 // startup.
165 sync_manager_->GetEncryptionHandler()->AddObserver(this);
167 // Sync manager initialization is complete, so we can schedule recurring
168 // SaveChanges.
169 sync_loop_->task_runner()->PostTask(
170 FROM_HERE, base::Bind(&SyncBackendHostCore::StartSavingChanges,
171 weak_ptr_factory_.GetWeakPtr()));
173 // Hang on to these for a while longer. We're not ready to hand them back to
174 // the UI thread yet.
175 js_backend_ = js_backend;
176 debug_info_listener_ = debug_info_listener;
178 // Track whether or not sync DB and preferences were in sync.
179 SyncBackendInitState backend_init_state;
180 if (has_sync_setup_completed_ && !restored_types.Empty()) {
181 backend_init_state = SETUP_COMPLETED_FOUND_RESTORED_TYPES;
182 } else if (has_sync_setup_completed_ && restored_types.Empty()) {
183 backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES;
184 } else if (!has_sync_setup_completed_ && restored_types.Empty()) {
185 backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES;
186 } else { // (!has_sync_setup_completed_ && !restored_types.Empty())
187 backend_init_state = FIRST_SETUP_RESTORED_TYPES;
190 UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState",
191 backend_init_state,
192 SYNC_BACKEND_INIT_STATE_COUNT);
194 // Before proceeding any further, we need to download the control types and
195 // purge any partial data (ie. data downloaded for a type that was on its way
196 // to being initially synced, but didn't quite make it.). The following
197 // configure cycle will take care of this. It depends on the registrar state
198 // which we initialize below to ensure that we don't perform any downloads if
199 // all control types have already completed their initial sync.
200 registrar_->SetInitialTypes(restored_types);
202 syncer::ConfigureReason reason =
203 restored_types.Empty() ?
204 syncer::CONFIGURE_REASON_NEW_CLIENT :
205 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
207 syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes(
208 syncer::ControlTypes(), syncer::ModelTypeSet());
209 syncer::ModelSafeRoutingInfo routing_info;
210 registrar_->GetModelSafeRoutingInfo(&routing_info);
211 SDVLOG(1) << "Control Types "
212 << syncer::ModelTypeSetToString(new_control_types)
213 << " added; calling ConfigureSyncer";
215 syncer::ModelTypeSet types_to_purge =
216 syncer::Difference(syncer::ModelTypeSet::All(),
217 GetRoutingInfoTypes(routing_info));
219 sync_manager_->ConfigureSyncer(
220 reason,
221 new_control_types,
222 types_to_purge,
223 syncer::ModelTypeSet(),
224 syncer::ModelTypeSet(),
225 routing_info,
226 base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes,
227 weak_ptr_factory_.GetWeakPtr()),
228 base::Closure());
231 void SyncBackendHostCore::OnConnectionStatusChange(
232 syncer::ConnectionStatus status) {
233 if (!sync_loop_)
234 return;
235 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
236 host_.Call(
237 FROM_HERE,
238 &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop, status);
241 void SyncBackendHostCore::OnPassphraseRequired(
242 syncer::PassphraseRequiredReason reason,
243 const sync_pb::EncryptedData& pending_keys) {
244 if (!sync_loop_)
245 return;
246 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
247 host_.Call(
248 FROM_HERE,
249 &SyncBackendHostImpl::NotifyPassphraseRequired, reason, pending_keys);
252 void SyncBackendHostCore::OnPassphraseAccepted() {
253 if (!sync_loop_)
254 return;
255 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
256 host_.Call(
257 FROM_HERE,
258 &SyncBackendHostImpl::NotifyPassphraseAccepted);
261 void SyncBackendHostCore::OnBootstrapTokenUpdated(
262 const std::string& bootstrap_token,
263 syncer::BootstrapTokenType type) {
264 if (!sync_loop_)
265 return;
266 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
267 host_.Call(FROM_HERE,
268 &SyncBackendHostImpl::PersistEncryptionBootstrapToken,
269 bootstrap_token,
270 type);
273 void SyncBackendHostCore::OnEncryptedTypesChanged(
274 syncer::ModelTypeSet encrypted_types,
275 bool encrypt_everything) {
276 if (!sync_loop_)
277 return;
278 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
279 // NOTE: We're in a transaction.
280 host_.Call(
281 FROM_HERE,
282 &SyncBackendHostImpl::NotifyEncryptedTypesChanged,
283 encrypted_types, encrypt_everything);
286 void SyncBackendHostCore::OnEncryptionComplete() {
287 if (!sync_loop_)
288 return;
289 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
290 // NOTE: We're in a transaction.
291 host_.Call(
292 FROM_HERE,
293 &SyncBackendHostImpl::NotifyEncryptionComplete);
296 void SyncBackendHostCore::OnCryptographerStateChanged(
297 syncer::Cryptographer* cryptographer) {
298 // Do nothing.
301 void SyncBackendHostCore::OnPassphraseTypeChanged(
302 syncer::PassphraseType type, base::Time passphrase_time) {
303 host_.Call(
304 FROM_HERE,
305 &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop,
306 type, passphrase_time);
309 void SyncBackendHostCore::OnLocalSetPassphraseEncryption(
310 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) {
311 host_.Call(
312 FROM_HERE,
313 &SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop,
314 nigori_state);
317 void SyncBackendHostCore::OnCommitCountersUpdated(
318 syncer::ModelType type,
319 const syncer::CommitCounters& counters) {
320 host_.Call(
321 FROM_HERE,
322 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop,
323 type, counters);
326 void SyncBackendHostCore::OnUpdateCountersUpdated(
327 syncer::ModelType type,
328 const syncer::UpdateCounters& counters) {
329 host_.Call(
330 FROM_HERE,
331 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop,
332 type, counters);
335 void SyncBackendHostCore::OnStatusCountersUpdated(
336 syncer::ModelType type,
337 const syncer::StatusCounters& counters) {
338 host_.Call(
339 FROM_HERE,
340 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop,
341 type, counters);
344 void SyncBackendHostCore::OnActionableError(
345 const syncer::SyncProtocolError& sync_error) {
346 if (!sync_loop_)
347 return;
348 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
349 host_.Call(
350 FROM_HERE,
351 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop,
352 sync_error);
355 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types) {
356 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
357 host_.Call(
358 FROM_HERE,
359 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop,
360 types);
363 void SyncBackendHostCore::OnProtocolEvent(
364 const syncer::ProtocolEvent& event) {
365 // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr.
366 if (forward_protocol_events_) {
367 scoped_ptr<syncer::ProtocolEvent> event_clone(event.Clone());
368 host_.Call(
369 FROM_HERE,
370 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
371 event_clone.release());
375 void SyncBackendHostCore::DoOnInvalidatorStateChange(
376 syncer::InvalidatorState state) {
377 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
378 sync_manager_->SetInvalidatorEnabled(state == syncer::INVALIDATIONS_ENABLED);
381 void SyncBackendHostCore::DoOnIncomingInvalidation(
382 const syncer::ObjectIdInvalidationMap& invalidation_map) {
383 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
385 syncer::ObjectIdSet ids = invalidation_map.GetObjectIds();
386 for (const invalidation::ObjectId& object_id : ids) {
387 syncer::ModelType type;
388 if (!NotificationTypeToRealModelType(object_id.name(), &type)) {
389 DLOG(WARNING) << "Notification has invalid id: "
390 << syncer::ObjectIdToString(object_id);
391 } else {
392 syncer::SingleObjectInvalidationSet invalidation_set =
393 invalidation_map.ForObject(object_id);
394 for (syncer::Invalidation invalidation : invalidation_set) {
395 auto last_invalidation = last_invalidation_versions_.find(type);
396 if (!invalidation.is_unknown_version() &&
397 last_invalidation != last_invalidation_versions_.end() &&
398 invalidation.version() <= last_invalidation->second) {
399 DVLOG(1) << "Ignoring redundant invalidation for "
400 << syncer::ModelTypeToString(type) << " with version "
401 << invalidation.version() << ", last seen version was "
402 << last_invalidation->second;
403 continue;
405 scoped_ptr<syncer::InvalidationInterface> inv_adapter(
406 new InvalidationAdapter(invalidation));
407 sync_manager_->OnIncomingInvalidation(type, inv_adapter.Pass());
408 if (!invalidation.is_unknown_version())
409 last_invalidation_versions_[type] = invalidation.version();
414 host_.Call(
415 FROM_HERE,
416 &SyncBackendHostImpl::UpdateInvalidationVersions,
417 last_invalidation_versions_);
420 void SyncBackendHostCore::DoInitialize(
421 scoped_ptr<DoInitializeOptions> options) {
422 DCHECK(!sync_loop_);
423 sync_loop_ = options->sync_loop;
424 DCHECK(sync_loop_);
426 // Finish initializing the HttpBridgeFactory. We do this here because
427 // building the user agent may block on some platforms.
428 options->http_bridge_factory->Init(options->sync_user_agent);
430 // Blow away the partial or corrupt sync data folder before doing any more
431 // initialization, if necessary.
432 if (options->delete_sync_data_folder) {
433 DeleteSyncDataFolder();
436 // Make sure that the directory exists before initializing the backend.
437 // If it already exists, this will do no harm.
438 if (!base::CreateDirectory(sync_data_folder_path_)) {
439 DLOG(FATAL) << "Sync Data directory creation failed.";
442 // Load the previously persisted set of invalidation versions into memory.
443 last_invalidation_versions_ = options->invalidation_versions;
445 DCHECK(!registrar_);
446 registrar_ = options->registrar;
447 DCHECK(registrar_);
449 sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_);
450 sync_manager_->AddObserver(this);
452 syncer::SyncManager::InitArgs args;
453 args.database_location = sync_data_folder_path_;
454 args.event_handler = options->event_handler;
455 args.service_url = options->service_url;
456 args.post_factory = options->http_bridge_factory.Pass();
457 args.workers = options->workers;
458 args.extensions_activity = options->extensions_activity.get();
459 args.change_delegate = options->registrar; // as SyncManager::ChangeDelegate
460 args.credentials = options->credentials;
461 args.invalidator_client_id = options->invalidator_client_id;
462 args.restored_key_for_bootstrapping = options->restored_key_for_bootstrapping;
463 args.restored_keystore_key_for_bootstrapping =
464 options->restored_keystore_key_for_bootstrapping;
465 args.internal_components_factory =
466 options->internal_components_factory.Pass();
467 args.encryptor = &encryptor_;
468 args.unrecoverable_error_handler = options->unrecoverable_error_handler;
469 args.report_unrecoverable_error_function =
470 options->report_unrecoverable_error_function;
471 args.cancelation_signal = &stop_syncing_signal_;
472 args.saved_nigori_state = options->saved_nigori_state.Pass();
473 args.clear_data_option = options->clear_data_option;
474 sync_manager_->Init(&args);
477 void SyncBackendHostCore::DoUpdateCredentials(
478 const syncer::SyncCredentials& credentials) {
479 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
480 // UpdateCredentials can be called during backend initialization, possibly
481 // when backend initialization has failed but hasn't notified the UI thread
482 // yet. In that case, the sync manager may have been destroyed on the sync
483 // thread before this task was executed, so we do nothing.
484 if (sync_manager_) {
485 sync_manager_->UpdateCredentials(credentials);
489 void SyncBackendHostCore::DoStartSyncing(
490 const syncer::ModelSafeRoutingInfo& routing_info,
491 base::Time last_poll_time) {
492 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
493 sync_manager_->StartSyncingNormally(routing_info, last_poll_time);
496 void SyncBackendHostCore::DoSetEncryptionPassphrase(
497 const std::string& passphrase,
498 bool is_explicit) {
499 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
500 sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(
501 passphrase, is_explicit);
504 void SyncBackendHostCore::DoInitialProcessControlTypes() {
505 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
507 DVLOG(1) << "Initilalizing Control Types";
509 // Initialize encryption.
510 sync_manager_->GetEncryptionHandler()->Init();
512 // Note: experiments are currently handled via SBH::AddExperimentalTypes,
513 // which is called at the end of every sync cycle.
514 // TODO(zea): eventually add an experiment handler and initialize it here.
516 if (!sync_manager_->GetUserShare()) { // NULL in some tests.
517 DVLOG(1) << "Skipping initialization of DeviceInfo";
518 host_.Call(
519 FROM_HERE,
520 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
521 return;
524 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
525 LOG(ERROR) << "Failed to download control types";
526 host_.Call(
527 FROM_HERE,
528 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
529 return;
532 host_.Call(FROM_HERE,
533 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop,
534 js_backend_,
535 debug_info_listener_,
536 sync_manager_->GetSyncContextProxy(),
537 sync_manager_->cache_guid());
539 js_backend_.Reset();
540 debug_info_listener_.Reset();
543 void SyncBackendHostCore::DoSetDecryptionPassphrase(
544 const std::string& passphrase) {
545 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
546 sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(
547 passphrase);
550 void SyncBackendHostCore::DoEnableEncryptEverything() {
551 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
552 sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
555 void SyncBackendHostCore::ShutdownOnUIThread() {
556 // This will cut short any blocking network tasks, cut short any in-progress
557 // sync cycles, and prevent the creation of new blocking network tasks and new
558 // sync cycles. If there was an in-progress network request, it would have
559 // had a reference to the RequestContextGetter. This reference will be
560 // dropped by the time this function returns.
562 // It is safe to call this even if Sync's backend classes have not been
563 // initialized yet. Those classes will receive the message when the sync
564 // thread finally getes around to constructing them.
565 stop_syncing_signal_.Signal();
567 // This will drop the HttpBridgeFactory's reference to the
568 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can
569 // no longer be used to create new HttpBridge instances. We can get away with
570 // this because the stop_syncing_signal_ has already been signalled, which
571 // guarantees that the ServerConnectionManager will no longer attempt to
572 // create new connections.
573 release_request_context_signal_.Signal();
576 void SyncBackendHostCore::DoShutdown(syncer::ShutdownReason reason) {
577 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
579 DoDestroySyncManager(reason);
581 registrar_ = NULL;
583 if (reason == syncer::DISABLE_SYNC)
584 DeleteSyncDataFolder();
586 host_.Reset();
587 weak_ptr_factory_.InvalidateWeakPtrs();
590 void SyncBackendHostCore::DoDestroySyncManager(syncer::ShutdownReason reason) {
591 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
592 if (sync_manager_) {
593 DisableDirectoryTypeDebugInfoForwarding();
594 save_changes_timer_.reset();
595 sync_manager_->RemoveObserver(this);
596 sync_manager_->ShutdownOnSyncThread(reason);
597 sync_manager_.reset();
601 void SyncBackendHostCore::DoConfigureSyncer(
602 syncer::ConfigureReason reason,
603 const DoConfigureSyncerTypes& config_types,
604 const syncer::ModelSafeRoutingInfo routing_info,
605 const base::Callback<void(syncer::ModelTypeSet,
606 syncer::ModelTypeSet)>& ready_task,
607 const base::Closure& retry_callback) {
608 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
609 DCHECK(!ready_task.is_null());
610 DCHECK(!retry_callback.is_null());
611 base::Closure chained_ready_task(
612 base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes,
613 weak_ptr_factory_.GetWeakPtr(),
614 config_types.to_download,
615 ready_task));
616 base::Closure chained_retry_task(
617 base::Bind(&SyncBackendHostCore::DoRetryConfiguration,
618 weak_ptr_factory_.GetWeakPtr(),
619 retry_callback));
620 sync_manager_->ConfigureSyncer(reason,
621 config_types.to_download,
622 config_types.to_purge,
623 config_types.to_journal,
624 config_types.to_unapply,
625 routing_info,
626 chained_ready_task,
627 chained_retry_task);
630 void SyncBackendHostCore::DoFinishConfigureDataTypes(
631 syncer::ModelTypeSet types_to_config,
632 const base::Callback<void(syncer::ModelTypeSet,
633 syncer::ModelTypeSet)>& ready_task) {
634 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
636 // Update the enabled types for the bridge and sync manager.
637 syncer::ModelSafeRoutingInfo routing_info;
638 registrar_->GetModelSafeRoutingInfo(&routing_info);
639 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
640 enabled_types.RemoveAll(syncer::ProxyTypes());
642 const syncer::ModelTypeSet failed_configuration_types =
643 Difference(types_to_config, sync_manager_->InitialSyncEndedTypes());
644 const syncer::ModelTypeSet succeeded_configuration_types =
645 Difference(types_to_config, failed_configuration_types);
646 host_.Call(FROM_HERE,
647 &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop,
648 enabled_types,
649 succeeded_configuration_types,
650 failed_configuration_types,
651 ready_task);
654 void SyncBackendHostCore::DoRetryConfiguration(
655 const base::Closure& retry_callback) {
656 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
657 host_.Call(FROM_HERE,
658 &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop,
659 retry_callback);
662 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() {
663 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
664 forward_protocol_events_ = true;
666 if (sync_manager_) {
667 // Grab our own copy of the buffered events.
668 // The buffer is not modified by this operation.
669 std::vector<syncer::ProtocolEvent*> buffered_events;
670 sync_manager_->GetBufferedProtocolEvents().release(&buffered_events);
672 // Send them all over the fence to the host.
673 for (std::vector<syncer::ProtocolEvent*>::iterator it =
674 buffered_events.begin(); it != buffered_events.end(); ++it) {
675 // TODO(rlarocque): Make it explicit that host_ takes ownership.
676 host_.Call(
677 FROM_HERE,
678 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
679 *it);
684 void SyncBackendHostCore::DisableProtocolEventForwarding() {
685 forward_protocol_events_ = false;
688 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() {
689 DCHECK(sync_manager_);
691 forward_type_info_ = true;
693 if (!sync_manager_->HasDirectoryTypeDebugInfoObserver(this))
694 sync_manager_->RegisterDirectoryTypeDebugInfoObserver(this);
695 sync_manager_->RequestEmitDebugInfo();
698 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() {
699 DCHECK(sync_manager_);
701 if (!forward_type_info_)
702 return;
704 forward_type_info_ = false;
706 if (sync_manager_->HasDirectoryTypeDebugInfoObserver(this))
707 sync_manager_->UnregisterDirectoryTypeDebugInfoObserver(this);
710 void SyncBackendHostCore::DeleteSyncDataFolder() {
711 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
712 if (base::DirectoryExists(sync_data_folder_path_)) {
713 if (!base::DeleteFile(sync_data_folder_path_, true))
714 SLOG(DFATAL) << "Could not delete the Sync Data folder.";
718 void SyncBackendHostCore::GetAllNodesForTypes(
719 syncer::ModelTypeSet types,
720 scoped_refptr<base::SequencedTaskRunner> task_runner,
721 base::Callback<void(const std::vector<syncer::ModelType>& type,
722 ScopedVector<base::ListValue>)> callback) {
723 std::vector<syncer::ModelType> types_vector;
724 ScopedVector<base::ListValue> node_lists;
726 syncer::ModelSafeRoutingInfo routes;
727 registrar_->GetModelSafeRoutingInfo(&routes);
728 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routes);
730 for (syncer::ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
731 types_vector.push_back(it.Get());
732 if (!enabled_types.Has(it.Get())) {
733 node_lists.push_back(new base::ListValue());
734 } else {
735 node_lists.push_back(
736 sync_manager_->GetAllNodesForType(it.Get()).release());
740 task_runner->PostTask(
741 FROM_HERE,
742 base::Bind(callback, types_vector, base::Passed(&node_lists)));
745 void SyncBackendHostCore::StartSavingChanges() {
746 // We may already be shut down.
747 if (!sync_loop_)
748 return;
749 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
750 DCHECK(!save_changes_timer_.get());
751 save_changes_timer_.reset(new base::RepeatingTimer<SyncBackendHostCore>());
752 save_changes_timer_->Start(FROM_HERE,
753 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
754 this, &SyncBackendHostCore::SaveChanges);
757 void SyncBackendHostCore::SaveChanges() {
758 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
759 sync_manager_->SaveChanges();
762 void SyncBackendHostCore::DoClearServerData(
763 const syncer::SyncManager::ClearServerDataCallback& frontend_callback) {
764 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
765 const syncer::SyncManager::ClearServerDataCallback callback =
766 base::Bind(&SyncBackendHostCore::ClearServerDataDone,
767 weak_ptr_factory_.GetWeakPtr(), frontend_callback);
768 sync_manager_->ClearServerData(callback);
771 void SyncBackendHostCore::ClearServerDataDone(
772 const base::Closure& frontend_callback) {
773 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
774 host_.Call(FROM_HERE, &SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop,
775 frontend_callback);
779 } // namespace browser_sync