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.
4
5 #include "chrome/browser/sync/glue/sync_backend_host_core.h"
6
7 #include "base/file_util.h"
8 #include "base/metrics/histogram.h"
9 #include "chrome/browser/sync/glue/device_info.h"
10 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
11 #include "chrome/browser/sync/glue/synced_device_tracker.h"
12 #include "chrome/common/chrome_version_info.h"
13 #include "sync/internal_api/public/events/protocol_event.h"
14 #include "sync/internal_api/public/http_post_provider_factory.h"
15 #include "sync/internal_api/public/internal_components_factory.h"
16 #include "sync/internal_api/public/sessions/commit_counters.h"
17 #include "sync/internal_api/public/sessions/status_counters.h"
18 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
19 #include "sync/internal_api/public/sessions/update_counters.h"
20 #include "sync/internal_api/public/sync_core_proxy.h"
21 #include "sync/internal_api/public/sync_manager.h"
22 #include "sync/internal_api/public/sync_manager_factory.h"
23
24 // Helper macros to log with the syncer thread name; useful when there
25 // are multiple syncers involved.
26
27 #define SLOG(severity) LOG(severity) << name_ << ": "
28
29 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
30
31 static const int kSaveChangesIntervalSeconds = 10;
32
33 namespace syncer {
34 class InternalComponentsFactory;
35 } // namespace syncer
36
37 namespace {
38
39 // Enums for UMAs.
40 enum SyncBackendInitState {
41 SETUP_COMPLETED_FOUND_RESTORED_TYPES = 0,
42 SETUP_COMPLETED_NO_RESTORED_TYPES,
43 FIRST_SETUP_NO_RESTORED_TYPES,
44 FIRST_SETUP_RESTORED_TYPES,
45 SYNC_BACKEND_INIT_STATE_COUNT
46 };
47
48 } // namespace
49
50 namespace browser_sync {
51
DoInitializeOptions(base::MessageLoop * sync_loop,SyncBackendRegistrar * registrar,const syncer::ModelSafeRoutingInfo & routing_info,const std::vector<scoped_refptr<syncer::ModelSafeWorker>> & workers,const scoped_refptr<syncer::ExtensionsActivity> & extensions_activity,const syncer::WeakHandle<syncer::JsEventHandler> & event_handler,const GURL & service_url,scoped_ptr<syncer::HttpPostProviderFactory> http_bridge_factory,const syncer::SyncCredentials & credentials,const std::string & invalidator_client_id,scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,bool delete_sync_data_folder,const std::string & restored_key_for_bootstrapping,const std::string & restored_keystore_key_for_bootstrapping,scoped_ptr<syncer::InternalComponentsFactory> internal_components_factory,scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,syncer::ReportUnrecoverableErrorFunction report_unrecoverable_error_function)52 DoInitializeOptions::DoInitializeOptions(
53 base::MessageLoop* sync_loop,
54 SyncBackendRegistrar* registrar,
55 const syncer::ModelSafeRoutingInfo& routing_info,
56 const std::vector<scoped_refptr<syncer::ModelSafeWorker> >& workers,
57 const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity,
58 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
59 const GURL& service_url,
60 scoped_ptr<syncer::HttpPostProviderFactory> http_bridge_factory,
61 const syncer::SyncCredentials& credentials,
62 const std::string& invalidator_client_id,
63 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
64 bool delete_sync_data_folder,
65 const std::string& restored_key_for_bootstrapping,
66 const std::string& restored_keystore_key_for_bootstrapping,
67 scoped_ptr<syncer::InternalComponentsFactory> internal_components_factory,
68 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
69 syncer::ReportUnrecoverableErrorFunction
70 report_unrecoverable_error_function)
71 : sync_loop(sync_loop),
72 registrar(registrar),
73 routing_info(routing_info),
74 workers(workers),
75 extensions_activity(extensions_activity),
76 event_handler(event_handler),
77 service_url(service_url),
78 http_bridge_factory(http_bridge_factory.Pass()),
79 credentials(credentials),
80 invalidator_client_id(invalidator_client_id),
81 sync_manager_factory(sync_manager_factory.Pass()),
82 delete_sync_data_folder(delete_sync_data_folder),
83 restored_key_for_bootstrapping(restored_key_for_bootstrapping),
84 restored_keystore_key_for_bootstrapping(
85 restored_keystore_key_for_bootstrapping),
86 internal_components_factory(internal_components_factory.Pass()),
87 unrecoverable_error_handler(unrecoverable_error_handler.Pass()),
88 report_unrecoverable_error_function(
89 report_unrecoverable_error_function) {
90 }
91
~DoInitializeOptions()92 DoInitializeOptions::~DoInitializeOptions() {}
93
DoConfigureSyncerTypes()94 DoConfigureSyncerTypes::DoConfigureSyncerTypes() {}
95
~DoConfigureSyncerTypes()96 DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {}
97
SyncBackendHostCore(const std::string & name,const base::FilePath & sync_data_folder_path,bool has_sync_setup_completed,const base::WeakPtr<SyncBackendHostImpl> & backend)98 SyncBackendHostCore::SyncBackendHostCore(
99 const std::string& name,
100 const base::FilePath& sync_data_folder_path,
101 bool has_sync_setup_completed,
102 const base::WeakPtr<SyncBackendHostImpl>& backend)
103 : name_(name),
104 sync_data_folder_path_(sync_data_folder_path),
105 host_(backend),
106 sync_loop_(NULL),
107 registrar_(NULL),
108 has_sync_setup_completed_(has_sync_setup_completed),
109 forward_protocol_events_(false),
110 forward_type_info_(false),
111 weak_ptr_factory_(this) {
112 DCHECK(backend.get());
113 }
114
~SyncBackendHostCore()115 SyncBackendHostCore::~SyncBackendHostCore() {
116 DCHECK(!sync_manager_.get());
117 }
118
OnSyncCycleCompleted(const syncer::sessions::SyncSessionSnapshot & snapshot)119 void SyncBackendHostCore::OnSyncCycleCompleted(
120 const syncer::sessions::SyncSessionSnapshot& snapshot) {
121 if (!sync_loop_)
122 return;
123 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
124
125 host_.Call(
126 FROM_HERE,
127 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop,
128 snapshot);
129 }
130
DoRefreshTypes(syncer::ModelTypeSet types)131 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) {
132 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
133 sync_manager_->RefreshTypes(types);
134 }
135
OnControlTypesDownloadRetry()136 void SyncBackendHostCore::OnControlTypesDownloadRetry() {
137 host_.Call(FROM_HERE,
138 &SyncBackendHostImpl::HandleControlTypesDownloadRetry);
139 }
140
OnInitializationComplete(const syncer::WeakHandle<syncer::JsBackend> & js_backend,const syncer::WeakHandle<syncer::DataTypeDebugInfoListener> & debug_info_listener,bool success,const syncer::ModelTypeSet restored_types)141 void SyncBackendHostCore::OnInitializationComplete(
142 const syncer::WeakHandle<syncer::JsBackend>& js_backend,
143 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
144 debug_info_listener,
145 bool success,
146 const syncer::ModelTypeSet restored_types) {
147 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
148
149 if (!success) {
150 DoDestroySyncManager();
151 host_.Call(FROM_HERE,
152 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
153 return;
154 }
155
156 // Register for encryption related changes now. We have to do this before
157 // the initializing downloading control types or initializing the encryption
158 // handler in order to receive notifications triggered during encryption
159 // startup.
160 sync_manager_->GetEncryptionHandler()->AddObserver(this);
161
162 // Sync manager initialization is complete, so we can schedule recurring
163 // SaveChanges.
164 sync_loop_->PostTask(FROM_HERE,
165 base::Bind(&SyncBackendHostCore::StartSavingChanges,
166 weak_ptr_factory_.GetWeakPtr()));
167
168 // Hang on to these for a while longer. We're not ready to hand them back to
169 // the UI thread yet.
170 js_backend_ = js_backend;
171 debug_info_listener_ = debug_info_listener;
172
173 // Track whether or not sync DB and preferences were in sync.
174 SyncBackendInitState backend_init_state;
175 if (has_sync_setup_completed_ && !restored_types.Empty()) {
176 backend_init_state = SETUP_COMPLETED_FOUND_RESTORED_TYPES;
177 } else if (has_sync_setup_completed_ && restored_types.Empty()) {
178 backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES;
179 } else if (!has_sync_setup_completed_ && restored_types.Empty()) {
180 backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES;
181 } else { // (!has_sync_setup_completed_ && !restored_types.Empty())
182 backend_init_state = FIRST_SETUP_RESTORED_TYPES;
183 }
184
185 UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState",
186 backend_init_state,
187 SYNC_BACKEND_INIT_STATE_COUNT);
188
189 // Before proceeding any further, we need to download the control types and
190 // purge any partial data (ie. data downloaded for a type that was on its way
191 // to being initially synced, but didn't quite make it.). The following
192 // configure cycle will take care of this. It depends on the registrar state
193 // which we initialize below to ensure that we don't perform any downloads if
194 // all control types have already completed their initial sync.
195 registrar_->SetInitialTypes(restored_types);
196
197 syncer::ConfigureReason reason =
198 restored_types.Empty() ?
199 syncer::CONFIGURE_REASON_NEW_CLIENT :
200 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
201
202 syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes(
203 syncer::ControlTypes(), syncer::ModelTypeSet());
204 syncer::ModelSafeRoutingInfo routing_info;
205 registrar_->GetModelSafeRoutingInfo(&routing_info);
206 SDVLOG(1) << "Control Types "
207 << syncer::ModelTypeSetToString(new_control_types)
208 << " added; calling ConfigureSyncer";
209
210 syncer::ModelTypeSet types_to_purge =
211 syncer::Difference(syncer::ModelTypeSet::All(),
212 GetRoutingInfoTypes(routing_info));
213
214 sync_manager_->ConfigureSyncer(
215 reason,
216 new_control_types,
217 types_to_purge,
218 syncer::ModelTypeSet(),
219 syncer::ModelTypeSet(),
220 routing_info,
221 base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes,
222 weak_ptr_factory_.GetWeakPtr()),
223 base::Bind(&SyncBackendHostCore::OnControlTypesDownloadRetry,
224 weak_ptr_factory_.GetWeakPtr()));
225 }
226
OnConnectionStatusChange(syncer::ConnectionStatus status)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);
235 }
236
OnPassphraseRequired(syncer::PassphraseRequiredReason reason,const sync_pb::EncryptedData & pending_keys)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);
246 }
247
OnPassphraseAccepted()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);
255 }
256
OnBootstrapTokenUpdated(const std::string & bootstrap_token,syncer::BootstrapTokenType type)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);
267 }
268
OnEncryptedTypesChanged(syncer::ModelTypeSet encrypted_types,bool encrypt_everything)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);
280 }
281
OnEncryptionComplete()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);
290 }
291
OnCryptographerStateChanged(syncer::Cryptographer * cryptographer)292 void SyncBackendHostCore::OnCryptographerStateChanged(
293 syncer::Cryptographer* cryptographer) {
294 // Do nothing.
295 }
296
OnPassphraseTypeChanged(syncer::PassphraseType type,base::Time passphrase_time)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);
303 }
304
OnCommitCountersUpdated(syncer::ModelType type,const syncer::CommitCounters & counters)305 void SyncBackendHostCore::OnCommitCountersUpdated(
306 syncer::ModelType type,
307 const syncer::CommitCounters& counters) {
308 host_.Call(
309 FROM_HERE,
310 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop,
311 type, counters);
312 }
313
OnUpdateCountersUpdated(syncer::ModelType type,const syncer::UpdateCounters & counters)314 void SyncBackendHostCore::OnUpdateCountersUpdated(
315 syncer::ModelType type,
316 const syncer::UpdateCounters& counters) {
317 host_.Call(
318 FROM_HERE,
319 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop,
320 type, counters);
321 }
322
OnStatusCountersUpdated(syncer::ModelType type,const syncer::StatusCounters & counters)323 void SyncBackendHostCore::OnStatusCountersUpdated(
324 syncer::ModelType type,
325 const syncer::StatusCounters& counters) {
326 host_.Call(
327 FROM_HERE,
328 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop,
329 type, counters);
330 }
331
OnActionableError(const syncer::SyncProtocolError & sync_error)332 void SyncBackendHostCore::OnActionableError(
333 const syncer::SyncProtocolError& sync_error) {
334 if (!sync_loop_)
335 return;
336 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
337 host_.Call(
338 FROM_HERE,
339 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop,
340 sync_error);
341 }
342
OnMigrationRequested(syncer::ModelTypeSet types)343 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types) {
344 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
345 host_.Call(
346 FROM_HERE,
347 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop,
348 types);
349 }
350
OnProtocolEvent(const syncer::ProtocolEvent & event)351 void SyncBackendHostCore::OnProtocolEvent(
352 const syncer::ProtocolEvent& event) {
353 // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr.
354 if (forward_protocol_events_) {
355 scoped_ptr<syncer::ProtocolEvent> event_clone(event.Clone());
356 host_.Call(
357 FROM_HERE,
358 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
359 event_clone.release());
360 }
361 }
362
DoOnInvalidatorStateChange(syncer::InvalidatorState state)363 void SyncBackendHostCore::DoOnInvalidatorStateChange(
364 syncer::InvalidatorState state) {
365 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
366 sync_manager_->OnInvalidatorStateChange(state);
367 }
368
DoOnIncomingInvalidation(const syncer::ObjectIdInvalidationMap & invalidation_map)369 void SyncBackendHostCore::DoOnIncomingInvalidation(
370 const syncer::ObjectIdInvalidationMap& invalidation_map) {
371 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
372 sync_manager_->OnIncomingInvalidation(invalidation_map);
373 }
374
DoInitialize(scoped_ptr<DoInitializeOptions> options)375 void SyncBackendHostCore::DoInitialize(
376 scoped_ptr<DoInitializeOptions> options) {
377 DCHECK(!sync_loop_);
378 sync_loop_ = options->sync_loop;
379 DCHECK(sync_loop_);
380
381 // Finish initializing the HttpBridgeFactory. We do this here because
382 // building the user agent may block on some platforms.
383 chrome::VersionInfo version_info;
384 options->http_bridge_factory->Init(
385 DeviceInfo::MakeUserAgentForSyncApi(version_info));
386
387 // Blow away the partial or corrupt sync data folder before doing any more
388 // initialization, if necessary.
389 if (options->delete_sync_data_folder) {
390 DeleteSyncDataFolder();
391 }
392
393 // Make sure that the directory exists before initializing the backend.
394 // If it already exists, this will do no harm.
395 if (!base::CreateDirectory(sync_data_folder_path_)) {
396 DLOG(FATAL) << "Sync Data directory creation failed.";
397 }
398
399 DCHECK(!registrar_);
400 registrar_ = options->registrar;
401 DCHECK(registrar_);
402
403 sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_);
404 sync_manager_->AddObserver(this);
405 sync_manager_->Init(sync_data_folder_path_,
406 options->event_handler,
407 options->service_url.host() + options->service_url.path(),
408 options->service_url.EffectiveIntPort(),
409 options->service_url.SchemeIsSecure(),
410 options->http_bridge_factory.Pass(),
411 options->workers,
412 options->extensions_activity,
413 options->registrar /* as SyncManager::ChangeDelegate */,
414 options->credentials,
415 options->invalidator_client_id,
416 options->restored_key_for_bootstrapping,
417 options->restored_keystore_key_for_bootstrapping,
418 options->internal_components_factory.get(),
419 &encryptor_,
420 options->unrecoverable_error_handler.Pass(),
421 options->report_unrecoverable_error_function,
422 &stop_syncing_signal_);
423 }
424
DoUpdateCredentials(const syncer::SyncCredentials & credentials)425 void SyncBackendHostCore::DoUpdateCredentials(
426 const syncer::SyncCredentials& credentials) {
427 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
428 // UpdateCredentials can be called during backend initialization, possibly
429 // when backend initialization has failed but hasn't notified the UI thread
430 // yet. In that case, the sync manager may have been destroyed on the sync
431 // thread before this task was executed, so we do nothing.
432 if (sync_manager_) {
433 sync_manager_->UpdateCredentials(credentials);
434 }
435 }
436
DoStartSyncing(const syncer::ModelSafeRoutingInfo & routing_info)437 void SyncBackendHostCore::DoStartSyncing(
438 const syncer::ModelSafeRoutingInfo& routing_info) {
439 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
440 sync_manager_->StartSyncingNormally(routing_info);
441 }
442
DoSetEncryptionPassphrase(const std::string & passphrase,bool is_explicit)443 void SyncBackendHostCore::DoSetEncryptionPassphrase(
444 const std::string& passphrase,
445 bool is_explicit) {
446 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
447 sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(
448 passphrase, is_explicit);
449 }
450
DoInitialProcessControlTypes()451 void SyncBackendHostCore::DoInitialProcessControlTypes() {
452 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
453
454 DVLOG(1) << "Initilalizing Control Types";
455
456 // Initialize encryption.
457 sync_manager_->GetEncryptionHandler()->Init();
458
459 // Note: experiments are currently handled via SBH::AddExperimentalTypes,
460 // which is called at the end of every sync cycle.
461 // TODO(zea): eventually add an experiment handler and initialize it here.
462
463 if (!sync_manager_->GetUserShare()) { // NULL in some tests.
464 DVLOG(1) << "Skipping initialization of DeviceInfo";
465 host_.Call(
466 FROM_HERE,
467 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
468 return;
469 }
470
471 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
472 LOG(ERROR) << "Failed to download control types";
473 host_.Call(
474 FROM_HERE,
475 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
476 return;
477 }
478
479 // Initialize device info. This is asynchronous on some platforms, so we
480 // provide a callback for when it finishes.
481 synced_device_tracker_.reset(
482 new SyncedDeviceTracker(sync_manager_->GetUserShare(),
483 sync_manager_->cache_guid()));
484 synced_device_tracker_->InitLocalDeviceInfo(
485 base::Bind(&SyncBackendHostCore::DoFinishInitialProcessControlTypes,
486 weak_ptr_factory_.GetWeakPtr()));
487 }
488
DoFinishInitialProcessControlTypes()489 void SyncBackendHostCore::DoFinishInitialProcessControlTypes() {
490 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
491
492 registrar_->ActivateDataType(syncer::DEVICE_INFO,
493 syncer::GROUP_PASSIVE,
494 synced_device_tracker_.get(),
495 sync_manager_->GetUserShare());
496
497 host_.Call(
498 FROM_HERE,
499 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop,
500 js_backend_,
501 debug_info_listener_,
502 sync_manager_->GetSyncCoreProxy());
503
504 js_backend_.Reset();
505 debug_info_listener_.Reset();
506 }
507
DoSetDecryptionPassphrase(const std::string & passphrase)508 void SyncBackendHostCore::DoSetDecryptionPassphrase(
509 const std::string& passphrase) {
510 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
511 sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(
512 passphrase);
513 }
514
DoEnableEncryptEverything()515 void SyncBackendHostCore::DoEnableEncryptEverything() {
516 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
517 sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
518 }
519
ShutdownOnUIThread()520 void SyncBackendHostCore::ShutdownOnUIThread() {
521 // This will cut short any blocking network tasks, cut short any in-progress
522 // sync cycles, and prevent the creation of new blocking network tasks and new
523 // sync cycles. If there was an in-progress network request, it would have
524 // had a reference to the RequestContextGetter. This reference will be
525 // dropped by the time this function returns.
526 //
527 // It is safe to call this even if Sync's backend classes have not been
528 // initialized yet. Those classes will receive the message when the sync
529 // thread finally getes around to constructing them.
530 stop_syncing_signal_.Signal();
531
532 // This will drop the HttpBridgeFactory's reference to the
533 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can
534 // no longer be used to create new HttpBridge instances. We can get away with
535 // this because the stop_syncing_signal_ has already been signalled, which
536 // guarantees that the ServerConnectionManager will no longer attempt to
537 // create new connections.
538 release_request_context_signal_.Signal();
539 }
540
DoShutdown(bool sync_disabled)541 void SyncBackendHostCore::DoShutdown(bool sync_disabled) {
542 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
543
544 // It's safe to do this even if the type was never activated.
545 registrar_->DeactivateDataType(syncer::DEVICE_INFO);
546 synced_device_tracker_.reset();
547
548 DoDestroySyncManager();
549
550 registrar_ = NULL;
551
552 if (sync_disabled)
553 DeleteSyncDataFolder();
554
555 host_.Reset();
556 weak_ptr_factory_.InvalidateWeakPtrs();
557 }
558
DoDestroySyncManager()559 void SyncBackendHostCore::DoDestroySyncManager() {
560 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
561 if (sync_manager_) {
562 DisableDirectoryTypeDebugInfoForwarding();
563 save_changes_timer_.reset();
564 sync_manager_->RemoveObserver(this);
565 sync_manager_->ShutdownOnSyncThread();
566 sync_manager_.reset();
567 }
568 }
569
DoConfigureSyncer(syncer::ConfigureReason reason,const DoConfigureSyncerTypes & config_types,const syncer::ModelSafeRoutingInfo routing_info,const base::Callback<void (syncer::ModelTypeSet,syncer::ModelTypeSet)> & ready_task,const base::Closure & retry_callback)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 sync_manager_->ConfigureSyncer(
579 reason,
580 config_types.to_download,
581 config_types.to_purge,
582 config_types.to_journal,
583 config_types.to_unapply,
584 routing_info,
585 base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes,
586 weak_ptr_factory_.GetWeakPtr(),
587 config_types.to_download,
588 ready_task),
589 base::Bind(&SyncBackendHostCore::DoRetryConfiguration,
590 weak_ptr_factory_.GetWeakPtr(),
591 retry_callback));
592 }
593
DoFinishConfigureDataTypes(syncer::ModelTypeSet types_to_config,const base::Callback<void (syncer::ModelTypeSet,syncer::ModelTypeSet)> & ready_task)594 void SyncBackendHostCore::DoFinishConfigureDataTypes(
595 syncer::ModelTypeSet types_to_config,
596 const base::Callback<void(syncer::ModelTypeSet,
597 syncer::ModelTypeSet)>& ready_task) {
598 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
599
600 // Update the enabled types for the bridge and sync manager.
601 syncer::ModelSafeRoutingInfo routing_info;
602 registrar_->GetModelSafeRoutingInfo(&routing_info);
603 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
604 enabled_types.RemoveAll(syncer::ProxyTypes());
605
606 const syncer::ModelTypeSet failed_configuration_types =
607 Difference(types_to_config, sync_manager_->InitialSyncEndedTypes());
608 const syncer::ModelTypeSet succeeded_configuration_types =
609 Difference(types_to_config, failed_configuration_types);
610 host_.Call(FROM_HERE,
611 &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop,
612 enabled_types,
613 succeeded_configuration_types,
614 failed_configuration_types,
615 ready_task);
616 }
617
DoRetryConfiguration(const base::Closure & retry_callback)618 void SyncBackendHostCore::DoRetryConfiguration(
619 const base::Closure& retry_callback) {
620 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
621 host_.Call(FROM_HERE,
622 &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop,
623 retry_callback);
624 }
625
SendBufferedProtocolEventsAndEnableForwarding()626 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() {
627 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
628 forward_protocol_events_ = true;
629
630 if (sync_manager_) {
631 // Grab our own copy of the buffered events.
632 // The buffer is not modified by this operation.
633 std::vector<syncer::ProtocolEvent*> buffered_events;
634 sync_manager_->GetBufferedProtocolEvents().release(&buffered_events);
635
636 // Send them all over the fence to the host.
637 for (std::vector<syncer::ProtocolEvent*>::iterator it =
638 buffered_events.begin(); it != buffered_events.end(); ++it) {
639 // TODO(rlarocque): Make it explicit that host_ takes ownership.
640 host_.Call(
641 FROM_HERE,
642 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
643 *it);
644 }
645 }
646 }
647
DisableProtocolEventForwarding()648 void SyncBackendHostCore::DisableProtocolEventForwarding() {
649 forward_protocol_events_ = false;
650 }
651
EnableDirectoryTypeDebugInfoForwarding()652 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() {
653 DCHECK(sync_manager_);
654
655 forward_type_info_ = true;
656
657 if (!sync_manager_->HasDirectoryTypeDebugInfoObserver(this))
658 sync_manager_->RegisterDirectoryTypeDebugInfoObserver(this);
659 sync_manager_->RequestEmitDebugInfo();
660 }
661
DisableDirectoryTypeDebugInfoForwarding()662 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() {
663 DCHECK(sync_manager_);
664
665 if (!forward_type_info_)
666 return;
667
668 forward_type_info_ = false;
669
670 if (sync_manager_->HasDirectoryTypeDebugInfoObserver(this))
671 sync_manager_->UnregisterDirectoryTypeDebugInfoObserver(this);
672 }
673
DeleteSyncDataFolder()674 void SyncBackendHostCore::DeleteSyncDataFolder() {
675 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
676 if (base::DirectoryExists(sync_data_folder_path_)) {
677 if (!base::DeleteFile(sync_data_folder_path_, true))
678 SLOG(DFATAL) << "Could not delete the Sync Data folder.";
679 }
680 }
681
GetAllNodesForTypes(syncer::ModelTypeSet types,scoped_refptr<base::SequencedTaskRunner> task_runner,base::Callback<void (const std::vector<syncer::ModelType> & type,ScopedVector<base::ListValue>)> callback)682 void SyncBackendHostCore::GetAllNodesForTypes(
683 syncer::ModelTypeSet types,
684 scoped_refptr<base::SequencedTaskRunner> task_runner,
685 base::Callback<void(const std::vector<syncer::ModelType>& type,
686 ScopedVector<base::ListValue>)> callback) {
687 std::vector<syncer::ModelType> types_vector;
688 ScopedVector<base::ListValue> node_lists;
689
690 syncer::ModelSafeRoutingInfo routes;
691 registrar_->GetModelSafeRoutingInfo(&routes);
692 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routes);
693
694 for (syncer::ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
695 types_vector.push_back(it.Get());
696 if (!enabled_types.Has(it.Get())) {
697 node_lists.push_back(new base::ListValue());
698 } else {
699 node_lists.push_back(
700 sync_manager_->GetAllNodesForType(it.Get()).release());
701 }
702 }
703
704 task_runner->PostTask(
705 FROM_HERE,
706 base::Bind(callback, types_vector, base::Passed(&node_lists)));
707 }
708
StartSavingChanges()709 void SyncBackendHostCore::StartSavingChanges() {
710 // We may already be shut down.
711 if (!sync_loop_)
712 return;
713 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
714 DCHECK(!save_changes_timer_.get());
715 save_changes_timer_.reset(new base::RepeatingTimer<SyncBackendHostCore>());
716 save_changes_timer_->Start(FROM_HERE,
717 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
718 this, &SyncBackendHostCore::SaveChanges);
719 }
720
SaveChanges()721 void SyncBackendHostCore::SaveChanges() {
722 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
723 sync_manager_->SaveChanges();
724 }
725
726 } // namespace browser_sync
727
728