Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(211)

Side by Side Diff: chrome/browser/sync/glue/sync_backend_host.cc

Issue 61183003: Refactor SyncBackendHost (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove double virtual Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync/glue/sync_backend_host.h" 5 #include "chrome/browser/sync/glue/sync_backend_host.h"
6 6
7 #include <algorithm>
8 #include <map>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/compiler_specific.h"
13 #include "base/file_util.h"
14 #include "base/files/file_path.h"
15 #include "base/location.h"
16 #include "base/metrics/histogram.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/thread_restrictions.h"
19 #include "base/timer/timer.h"
20 #include "base/tracked_objects.h"
21 #include "build/build_config.h"
22 #include "chrome/browser/invalidation/invalidation_service.h"
23 #include "chrome/browser/invalidation/invalidation_service_factory.h"
24 #include "chrome/browser/chrome_notification_types.h"
25 #include "chrome/browser/network_time/network_time_tracker.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/signin/token_service.h"
28 #include "chrome/browser/signin/token_service_factory.h"
29 #include "chrome/browser/sync/glue/change_processor.h"
30 #include "chrome/browser/sync/glue/chrome_encryptor.h"
31 #include "chrome/browser/sync/glue/device_info.h"
32 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
33 #include "chrome/browser/sync/glue/synced_device_tracker.h"
34 #include "chrome/browser/sync/sync_prefs.h"
35 #include "chrome/common/chrome_switches.h"
36 #include "chrome/common/chrome_version_info.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/notification_details.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/notification_source.h"
41 #include "content/public/common/content_client.h"
42 #include "google_apis/gaia/gaia_constants.h"
43 #include "jingle/notifier/base/notification_method.h"
44 #include "jingle/notifier/base/notifier_options.h"
45 #include "net/base/host_port_pair.h"
46 #include "net/url_request/url_request_context_getter.h"
47 #include "sync/internal_api/public/base/cancelation_signal.h"
48 #include "sync/internal_api/public/base_transaction.h"
49 #include "sync/internal_api/public/engine/model_safe_worker.h"
50 #include "sync/internal_api/public/http_bridge.h"
51 #include "sync/internal_api/public/internal_components_factory_impl.h"
52 #include "sync/internal_api/public/read_transaction.h"
53 #include "sync/internal_api/public/sync_manager_factory.h"
54 #include "sync/internal_api/public/util/experiments.h"
55 #include "sync/internal_api/public/util/sync_string_conversions.h"
56 #include "sync/protocol/encryption.pb.h"
57 #include "sync/protocol/sync.pb.h"
58 #include "sync/util/nigori.h"
59
60 static const int kSaveChangesIntervalSeconds = 10;
61 static const base::FilePath::CharType kSyncDataFolderName[] =
62 FILE_PATH_LITERAL("Sync Data");
63
64 typedef TokenService::TokenAvailableDetails TokenAvailableDetails;
65
66 typedef GoogleServiceAuthError AuthError;
67
68 namespace browser_sync { 7 namespace browser_sync {
69 8
70 using content::BrowserThread; 9 SyncBackendHost::SyncBackendHost() {}
71 using syncer::InternalComponentsFactory;
72 using syncer::InternalComponentsFactoryImpl;
73 using syncer::sessions::SyncSessionSnapshot;
74 using syncer::SyncCredentials;
75 10
76 namespace { 11 SyncBackendHost::~SyncBackendHost() {}
77
78 // Enums for UMAs.
79 enum SyncBackendInitState {
80 SETUP_COMPLETED_FOUND_RESTORED_TYPES = 0,
81 SETUP_COMPLETED_NO_RESTORED_TYPES,
82 FIRST_SETUP_NO_RESTORED_TYPES,
83 FIRST_SETUP_RESTORED_TYPES,
84 SYNC_BACKEND_INIT_STATE_COUNT
85 };
86
87 // Helper struct to handle currying params to
88 // SyncBackendHost::Core::DoConfigureSyncer.
89 struct DoConfigureSyncerTypes {
90 DoConfigureSyncerTypes() {}
91 ~DoConfigureSyncerTypes() {}
92 syncer::ModelTypeSet to_download;
93 syncer::ModelTypeSet to_purge;
94 syncer::ModelTypeSet to_journal;
95 syncer::ModelTypeSet to_unapply;
96 };
97
98 } // namespace
99
100 // Helper macros to log with the syncer thread name; useful when there
101 // are multiple syncers involved.
102
103 #define SLOG(severity) LOG(severity) << name_ << ": "
104
105 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
106
107 class SyncBackendHost::Core
108 : public base::RefCountedThreadSafe<SyncBackendHost::Core>,
109 public syncer::SyncEncryptionHandler::Observer,
110 public syncer::SyncManager::Observer {
111 public:
112 Core(const std::string& name,
113 const base::FilePath& sync_data_folder_path,
114 bool has_sync_setup_completed,
115 const base::WeakPtr<SyncBackendHost>& backend);
116
117 // SyncManager::Observer implementation. The Core just acts like an air
118 // traffic controller here, forwarding incoming messages to appropriate
119 // landing threads.
120 virtual void OnSyncCycleCompleted(
121 const syncer::sessions::SyncSessionSnapshot& snapshot) OVERRIDE;
122 virtual void OnInitializationComplete(
123 const syncer::WeakHandle<syncer::JsBackend>& js_backend,
124 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
125 debug_info_listener,
126 bool success,
127 syncer::ModelTypeSet restored_types) OVERRIDE;
128 virtual void OnConnectionStatusChange(
129 syncer::ConnectionStatus status) OVERRIDE;
130 virtual void OnStopSyncingPermanently() OVERRIDE;
131 virtual void OnActionableError(
132 const syncer::SyncProtocolError& sync_error) OVERRIDE;
133
134 // SyncEncryptionHandler::Observer implementation.
135 virtual void OnPassphraseRequired(
136 syncer::PassphraseRequiredReason reason,
137 const sync_pb::EncryptedData& pending_keys) OVERRIDE;
138 virtual void OnPassphraseAccepted() OVERRIDE;
139 virtual void OnBootstrapTokenUpdated(
140 const std::string& bootstrap_token,
141 syncer::BootstrapTokenType type) OVERRIDE;
142 virtual void OnEncryptedTypesChanged(
143 syncer::ModelTypeSet encrypted_types,
144 bool encrypt_everything) OVERRIDE;
145 virtual void OnEncryptionComplete() OVERRIDE;
146 virtual void OnCryptographerStateChanged(
147 syncer::Cryptographer* cryptographer) OVERRIDE;
148 virtual void OnPassphraseTypeChanged(syncer::PassphraseType type,
149 base::Time passphrase_time) OVERRIDE;
150
151 // Forwards an invalidation state change to the sync manager.
152 void DoOnInvalidatorStateChange(syncer::InvalidatorState state);
153
154 // Forwards an invalidation to the sync manager.
155 void DoOnIncomingInvalidation(
156 syncer::ObjectIdInvalidationMap invalidation_map);
157
158 // Note:
159 //
160 // The Do* methods are the various entry points from our
161 // SyncBackendHost. They are all called on the sync thread to
162 // actually perform synchronous (and potentially blocking) syncapi
163 // operations.
164 //
165 // Called to perform initialization of the syncapi on behalf of
166 // SyncBackendHost::Initialize.
167 void DoInitialize(scoped_ptr<DoInitializeOptions> options);
168
169 // Called to perform credential update on behalf of
170 // SyncBackendHost::UpdateCredentials.
171 void DoUpdateCredentials(const syncer::SyncCredentials& credentials);
172
173 // Called to tell the syncapi to start syncing (generally after
174 // initialization and authentication).
175 void DoStartSyncing(const syncer::ModelSafeRoutingInfo& routing_info);
176
177 // Called to set the passphrase for encryption.
178 void DoSetEncryptionPassphrase(const std::string& passphrase,
179 bool is_explicit);
180
181 // Called to decrypt the pending keys.
182 void DoSetDecryptionPassphrase(const std::string& passphrase);
183
184 // Called to turn on encryption of all sync data as well as
185 // reencrypt everything.
186 void DoEnableEncryptEverything();
187
188 // Ask the syncer to check for updates for the specified types.
189 void DoRefreshTypes(syncer::ModelTypeSet types);
190
191 // Invoked if we failed to download the necessary control types at startup.
192 // Invokes SyncBackendHost::HandleControlTypesDownloadRetry.
193 void OnControlTypesDownloadRetry();
194
195 // Called to perform tasks which require the control data to be downloaded.
196 // This includes refreshing encryption, setting up the device info change
197 // processor, etc.
198 void DoInitialProcessControlTypes();
199
200 // Some parts of DoInitialProcessControlTypes() may be executed on a different
201 // thread. This function asynchronously continues the work started in
202 // DoInitialProcessControlTypes() once that other thread gets back to us.
203 void DoFinishInitialProcessControlTypes();
204
205 // The shutdown order is a bit complicated:
206 // 1) Call ShutdownOnUIThread() from |frontend_loop_| to request sync manager
207 // to stop as soon as possible.
208 // 2) Post DoShutdown() to sync loop to clean up backend state, save
209 // directory and destroy sync manager.
210 void ShutdownOnUIThread();
211 void DoShutdown(bool sync_disabled);
212 void DoDestroySyncManager();
213
214 // Configuration methods that must execute on sync loop.
215 void DoConfigureSyncer(
216 syncer::ConfigureReason reason,
217 const DoConfigureSyncerTypes& config_types,
218 const syncer::ModelSafeRoutingInfo routing_info,
219 const base::Callback<void(syncer::ModelTypeSet,
220 syncer::ModelTypeSet)>& ready_task,
221 const base::Closure& retry_callback);
222 void DoFinishConfigureDataTypes(
223 syncer::ModelTypeSet types_to_config,
224 const base::Callback<void(syncer::ModelTypeSet,
225 syncer::ModelTypeSet)>& ready_task);
226 void DoRetryConfiguration(
227 const base::Closure& retry_callback);
228
229 // Set the base request context to use when making HTTP calls.
230 // This method will add a reference to the context to persist it
231 // on the IO thread. Must be removed from IO thread.
232
233 syncer::SyncManager* sync_manager() { return sync_manager_.get(); }
234
235 SyncedDeviceTracker* synced_device_tracker() {
236 return synced_device_tracker_.get();
237 }
238
239 // Delete the sync data folder to cleanup backend data. Happens the first
240 // time sync is enabled for a user (to prevent accidentally reusing old
241 // sync databases), as well as shutdown when you're no longer syncing.
242 void DeleteSyncDataFolder();
243
244 // We expose this member because it's required in the construction of the
245 // HttpBridgeFactory.
246 syncer::CancelationSignal* GetRequestContextCancelationSignal() {
247 return &release_request_context_signal_;
248 }
249
250 private:
251 friend class base::RefCountedThreadSafe<SyncBackendHost::Core>;
252 friend class SyncBackendHostForProfileSyncTest;
253
254 virtual ~Core();
255
256 // Invoked when initialization of syncapi is complete and we can start
257 // our timer.
258 // This must be called from the thread on which SaveChanges is intended to
259 // be run on; the host's |registrar_->sync_thread()|.
260 void StartSavingChanges();
261
262 // Invoked periodically to tell the syncapi to persist its state
263 // by writing to disk.
264 // This is called from the thread we were created on (which is sync thread),
265 // using a repeating timer that is kicked off as soon as the SyncManager
266 // tells us it completed initialization.
267 void SaveChanges();
268
269 // Name used for debugging.
270 const std::string name_;
271
272 // Path of the folder that stores the sync data files.
273 const base::FilePath sync_data_folder_path_;
274
275 // Our parent SyncBackendHost.
276 syncer::WeakHandle<SyncBackendHost> host_;
277
278 // The loop where all the sync backend operations happen.
279 // Non-NULL only between calls to DoInitialize() and ~Core().
280 base::MessageLoop* sync_loop_;
281
282 // Our parent's registrar (not owned). Non-NULL only between
283 // calls to DoInitialize() and DoShutdown().
284 SyncBackendRegistrar* registrar_;
285
286 // The timer used to periodically call SaveChanges.
287 scoped_ptr<base::RepeatingTimer<Core> > save_changes_timer_;
288
289 // Our encryptor, which uses Chrome's encryption functions.
290 ChromeEncryptor encryptor_;
291
292 // A special ChangeProcessor that tracks the DEVICE_INFO type for us.
293 scoped_ptr<SyncedDeviceTracker> synced_device_tracker_;
294
295 // The top-level syncapi entry point. Lives on the sync thread.
296 scoped_ptr<syncer::SyncManager> sync_manager_;
297
298 // Temporary holder of sync manager's initialization results. Set by
299 // OnInitializeComplete, and consumed when we pass it via OnBackendInitialized
300 // in the final state of HandleInitializationSuccessOnFrontendLoop.
301 syncer::WeakHandle<syncer::JsBackend> js_backend_;
302 syncer::WeakHandle<syncer::DataTypeDebugInfoListener> debug_info_listener_;
303
304 // These signals allow us to send requests to shut down the HttpBridgeFactory
305 // and ServerConnectionManager without having to wait for those classes to
306 // finish initializing first.
307 //
308 // See comments in Core::ShutdownOnUIThread() for more details.
309 syncer::CancelationSignal release_request_context_signal_;
310 syncer::CancelationSignal stop_syncing_signal_;
311
312 // Matches the value of SyncPref's HasSyncSetupCompleted() flag at init time.
313 // Should not be used for anything except for UMAs and logging.
314 const bool has_sync_setup_completed_;
315
316 base::WeakPtrFactory<Core> weak_ptr_factory_;
317
318 DISALLOW_COPY_AND_ASSIGN(Core);
319 };
320
321 SyncBackendHost::SyncBackendHost(
322 const std::string& name,
323 Profile* profile,
324 const base::WeakPtr<SyncPrefs>& sync_prefs)
325 : frontend_loop_(base::MessageLoop::current()),
326 profile_(profile),
327 name_(name),
328 initialized_(false),
329 sync_prefs_(sync_prefs),
330 frontend_(NULL),
331 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
332 invalidator_(
333 invalidation::InvalidationServiceFactory::GetForProfile(profile)),
334 invalidation_handler_registered_(false),
335 weak_ptr_factory_(this) {
336 core_ = new Core(name_, profile_->GetPath().Append(kSyncDataFolderName),
337 sync_prefs_->HasSyncSetupCompleted(),
338 weak_ptr_factory_.GetWeakPtr());
339 }
340
341 SyncBackendHost::SyncBackendHost(Profile* profile)
342 : frontend_loop_(base::MessageLoop::current()),
343 profile_(profile),
344 name_("Unknown"),
345 initialized_(false),
346 frontend_(NULL),
347 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE),
348 invalidation_handler_registered_(false),
349 weak_ptr_factory_(this) {
350 }
351
352 SyncBackendHost::~SyncBackendHost() {
353 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor.";
354 DCHECK(!registrar_.get());
355 }
356
357 void SyncBackendHost::Initialize(
358 SyncFrontend* frontend,
359 scoped_ptr<base::Thread> sync_thread,
360 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
361 const GURL& sync_service_url,
362 const SyncCredentials& credentials,
363 bool delete_sync_data_folder,
364 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
365 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
366 syncer::ReportUnrecoverableErrorFunction
367 report_unrecoverable_error_function) {
368 registrar_.reset(new SyncBackendRegistrar(name_,
369 profile_,
370 sync_thread.Pass()));
371 CHECK(registrar_->sync_thread());
372
373 frontend_ = frontend;
374 DCHECK(frontend);
375
376 syncer::ModelSafeRoutingInfo routing_info;
377 std::vector<syncer::ModelSafeWorker*> workers;
378 registrar_->GetModelSafeRoutingInfo(&routing_info);
379 registrar_->GetWorkers(&workers);
380
381 InternalComponentsFactory::Switches factory_switches = {
382 InternalComponentsFactory::ENCRYPTION_KEYSTORE,
383 InternalComponentsFactory::BACKOFF_NORMAL
384 };
385
386 CommandLine* cl = CommandLine::ForCurrentProcess();
387 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) {
388 factory_switches.backoff_override =
389 InternalComponentsFactoryImpl::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE;
390 }
391 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) {
392 factory_switches.pre_commit_updates_policy =
393 InternalComponentsFactoryImpl::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE;
394 }
395
396 scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions(
397 registrar_->sync_thread()->message_loop(),
398 registrar_.get(),
399 routing_info,
400 workers,
401 extensions_activity_monitor_.GetExtensionsActivity(),
402 event_handler,
403 sync_service_url,
404 scoped_ptr<syncer::HttpPostProviderFactory>(
405 new syncer::HttpBridgeFactory(
406 make_scoped_refptr(profile_->GetRequestContext()),
407 NetworkTimeTracker::BuildNotifierUpdateCallback(),
408 core_->GetRequestContextCancelationSignal())),
409 credentials,
410 invalidator_->GetInvalidatorClientId(),
411 sync_manager_factory.Pass(),
412 delete_sync_data_folder,
413 sync_prefs_->GetEncryptionBootstrapToken(),
414 sync_prefs_->GetKeystoreEncryptionBootstrapToken(),
415 scoped_ptr<InternalComponentsFactory>(
416 new InternalComponentsFactoryImpl(factory_switches)).Pass(),
417 unrecoverable_error_handler.Pass(),
418 report_unrecoverable_error_function));
419 InitCore(init_opts.Pass());
420 }
421
422 void SyncBackendHost::UpdateCredentials(const SyncCredentials& credentials) {
423 DCHECK(registrar_->sync_thread()->IsRunning());
424 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
425 base::Bind(&SyncBackendHost::Core::DoUpdateCredentials,
426 core_.get(),
427 credentials));
428 }
429
430 void SyncBackendHost::StartSyncingWithServer() {
431 SDVLOG(1) << "SyncBackendHost::StartSyncingWithServer called.";
432
433 syncer::ModelSafeRoutingInfo routing_info;
434 registrar_->GetModelSafeRoutingInfo(&routing_info);
435
436 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
437 base::Bind(&SyncBackendHost::Core::DoStartSyncing,
438 core_.get(), routing_info));
439 }
440
441 void SyncBackendHost::SetEncryptionPassphrase(const std::string& passphrase,
442 bool is_explicit) {
443 DCHECK(registrar_->sync_thread()->IsRunning());
444 if (!IsNigoriEnabled()) {
445 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori"
446 " is disabled.";
447 return;
448 }
449
450 // We should never be called with an empty passphrase.
451 DCHECK(!passphrase.empty());
452
453 // This should only be called by the frontend.
454 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
455
456 // SetEncryptionPassphrase should never be called if we are currently
457 // encrypted with an explicit passphrase.
458 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE ||
459 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE);
460
461 // Post an encryption task on the syncer thread.
462 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
463 base::Bind(&SyncBackendHost::Core::DoSetEncryptionPassphrase,
464 core_.get(),
465 passphrase, is_explicit));
466 }
467
468 bool SyncBackendHost::SetDecryptionPassphrase(const std::string& passphrase) {
469 if (!IsNigoriEnabled()) {
470 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori"
471 " is disabled.";
472 return false;
473 }
474
475 // We should never be called with an empty passphrase.
476 DCHECK(!passphrase.empty());
477
478 // This should only be called by the frontend.
479 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
480
481 // This should only be called when we have cached pending keys.
482 DCHECK(cached_pending_keys_.has_blob());
483
484 // Check the passphrase that was provided against our local cache of the
485 // cryptographer's pending keys. If this was unsuccessful, the UI layer can
486 // immediately call OnPassphraseRequired without showing the user a spinner.
487 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase))
488 return false;
489
490 // Post a decryption task on the syncer thread.
491 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
492 base::Bind(&SyncBackendHost::Core::DoSetDecryptionPassphrase,
493 core_.get(),
494 passphrase));
495
496 // Since we were able to decrypt the cached pending keys with the passphrase
497 // provided, we immediately alert the UI layer that the passphrase was
498 // accepted. This will avoid the situation where a user enters a passphrase,
499 // clicks OK, immediately reopens the advanced settings dialog, and gets an
500 // unnecessary prompt for a passphrase.
501 // Note: It is not guaranteed that the passphrase will be accepted by the
502 // syncer thread, since we could receive a new nigori node while the task is
503 // pending. This scenario is a valid race, and SetDecryptionPassphrase can
504 // trigger a new OnPassphraseRequired if it needs to.
505 NotifyPassphraseAccepted();
506 return true;
507 }
508
509 void SyncBackendHost::StopSyncingForShutdown() {
510 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
511
512 // Immediately stop sending messages to the frontend.
513 frontend_ = NULL;
514
515 // Stop listening for and forwarding locally-triggered sync refresh requests.
516 notification_registrar_.RemoveAll();
517
518 DCHECK(registrar_->sync_thread()->IsRunning());
519
520 registrar_->RequestWorkerStopOnUIThread();
521
522 core_->ShutdownOnUIThread();
523 }
524
525 scoped_ptr<base::Thread> SyncBackendHost::Shutdown(ShutdownOption option) {
526 // StopSyncingForShutdown() (which nulls out |frontend_|) should be
527 // called first.
528 DCHECK(!frontend_);
529 DCHECK(registrar_->sync_thread()->IsRunning());
530
531 bool sync_disabled = (option == DISABLE_AND_CLAIM_THREAD);
532 bool sync_thread_claimed =
533 (option == DISABLE_AND_CLAIM_THREAD || option == STOP_AND_CLAIM_THREAD);
534
535 if (invalidation_handler_registered_) {
536 if (sync_disabled) {
537 UnregisterInvalidationIds();
538 }
539 invalidator_->UnregisterInvalidationHandler(this);
540 invalidator_ = NULL;
541 }
542 invalidation_handler_registered_ = false;
543
544 // Shut down and destroy sync manager.
545 registrar_->sync_thread()->message_loop()->PostTask(
546 FROM_HERE,
547 base::Bind(&SyncBackendHost::Core::DoShutdown,
548 core_.get(), sync_disabled));
549 core_ = NULL;
550
551 // Worker cleanup.
552 SyncBackendRegistrar* detached_registrar = registrar_.release();
553 detached_registrar->sync_thread()->message_loop()->PostTask(
554 FROM_HERE,
555 base::Bind(&SyncBackendRegistrar::Shutdown,
556 base::Unretained(detached_registrar)));
557
558 if (sync_thread_claimed)
559 return detached_registrar->ReleaseSyncThread();
560 else
561 return scoped_ptr<base::Thread>();
562 }
563
564 void SyncBackendHost::UnregisterInvalidationIds() {
565 if (invalidation_handler_registered_) {
566 invalidator_->UpdateRegisteredInvalidationIds(
567 this,
568 syncer::ObjectIdSet());
569 }
570 }
571
572 void SyncBackendHost::ConfigureDataTypes(
573 syncer::ConfigureReason reason,
574 const DataTypeConfigStateMap& config_state_map,
575 const base::Callback<void(syncer::ModelTypeSet,
576 syncer::ModelTypeSet)>& ready_task,
577 const base::Callback<void()>& retry_callback) {
578 // Only one configure is allowed at a time. This is guaranteed by our
579 // callers. The SyncBackendHost requests one configure as the backend is
580 // initializing and waits for it to complete. After initialization, all
581 // configurations will pass through the DataTypeManager, which is careful to
582 // never send a new configure request until the current request succeeds.
583
584 // The SyncBackendRegistrar's routing info will be updated by adding the
585 // types_to_add to the list then removing types_to_remove. Any types which
586 // are not in either of those sets will remain untouched.
587 //
588 // Types which were not in the list previously are not fully downloaded, so we
589 // must ask the syncer to download them. Any newly supported datatypes will
590 // not have been in that routing info list, so they will be among the types
591 // downloaded if they are enabled.
592 //
593 // The SyncBackendRegistrar's state was initially derived from the types
594 // detected to have been downloaded in the database. Afterwards it is
595 // modified only by this function. We expect it to remain in sync with the
596 // backend because configuration requests are never aborted; they are retried
597 // until they succeed or the backend is shut down.
598
599 syncer::ModelTypeSet previous_types = registrar_->GetLastConfiguredTypes();
600
601 syncer::ModelTypeSet disabled_types =
602 GetDataTypesInState(DISABLED, config_state_map);
603 syncer::ModelTypeSet fatal_types =
604 GetDataTypesInState(FATAL, config_state_map);
605 syncer::ModelTypeSet crypto_types =
606 GetDataTypesInState(CRYPTO, config_state_map);
607 disabled_types.PutAll(fatal_types);
608 disabled_types.PutAll(crypto_types);
609 syncer::ModelTypeSet active_types =
610 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
611 syncer::ModelTypeSet clean_first_types =
612 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
613 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes(
614 syncer::Union(active_types, clean_first_types),
615 disabled_types);
616 types_to_download.PutAll(clean_first_types);
617 types_to_download.RemoveAll(syncer::ProxyTypes());
618 if (!types_to_download.Empty())
619 types_to_download.Put(syncer::NIGORI);
620
621 // TODO(sync): crbug.com/137550.
622 // It's dangerous to configure types that have progress markers. Types with
623 // progress markers can trigger a MIGRATION_DONE response. We are not
624 // prepared to handle a migration during a configure, so we must ensure that
625 // all our types_to_download actually contain no data before we sync them.
626 //
627 // One common way to end up in this situation used to be types which
628 // downloaded some or all of their data but have not applied it yet. We avoid
629 // problems with those types by purging the data of any such partially synced
630 // types soon after we load the directory.
631 //
632 // Another possible scenario is that we have newly supported or newly enabled
633 // data types being downloaded here but the nigori type, which is always
634 // included in any GetUpdates request, requires migration. The server has
635 // code to detect this scenario based on the configure reason, the fact that
636 // the nigori type is the only requested type which requires migration, and
637 // that the requested types list includes at least one non-nigori type. It
638 // will not send a MIGRATION_DONE response in that case. We still need to be
639 // careful to not send progress markers for non-nigori types, though. If a
640 // non-nigori type in the request requires migration, a MIGRATION_DONE
641 // response will be sent.
642
643 syncer::ModelSafeRoutingInfo routing_info;
644 registrar_->GetModelSafeRoutingInfo(&routing_info);
645
646 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes();
647 syncer::ModelTypeSet types_to_purge =
648 syncer::Difference(previous_types, current_types);
649 syncer::ModelTypeSet inactive_types =
650 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
651 types_to_purge.RemoveAll(inactive_types);
652
653 // If a type has already been disabled and unapplied or journaled, it will
654 // not be part of the |types_to_purge| set, and therefore does not need
655 // to be acted on again.
656 fatal_types.RetainAll(types_to_purge);
657 syncer::ModelTypeSet unapply_types =
658 syncer::Union(crypto_types, clean_first_types);
659 unapply_types.RetainAll(types_to_purge);
660
661 DCHECK(syncer::Intersection(current_types, fatal_types).Empty());
662 DCHECK(syncer::Intersection(current_types, crypto_types).Empty());
663 DCHECK(current_types.HasAll(types_to_download));
664
665 SDVLOG(1) << "Types "
666 << syncer::ModelTypeSetToString(types_to_download)
667 << " added; calling DoConfigureSyncer";
668 // Divide up the types into their corresponding actions (each is mutually
669 // exclusive):
670 // - Types which have just been added to the routing info (types_to_download):
671 // are downloaded.
672 // - Types which have encountered a fatal error (fatal_types) are deleted
673 // from the directory and journaled in the delete journal.
674 // - Types which have encountered a cryptographer error (crypto_types) are
675 // unapplied (local state is purged but sync state is not).
676 // - All other types not in the routing info (types just disabled) are deleted
677 // from the directory.
678 // - Everything else (enabled types and already disabled types) is not
679 // touched.
680 RequestConfigureSyncer(reason,
681 types_to_download,
682 types_to_purge,
683 fatal_types,
684 unapply_types,
685 inactive_types,
686 routing_info,
687 ready_task,
688 retry_callback);
689 }
690
691 void SyncBackendHost::EnableEncryptEverything() {
692 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
693 base::Bind(&SyncBackendHost::Core::DoEnableEncryptEverything,
694 core_.get()));
695 }
696
697 void SyncBackendHost::ActivateDataType(
698 syncer::ModelType type, syncer::ModelSafeGroup group,
699 ChangeProcessor* change_processor) {
700 registrar_->ActivateDataType(type, group, change_processor, GetUserShare());
701 }
702
703 void SyncBackendHost::DeactivateDataType(syncer::ModelType type) {
704 registrar_->DeactivateDataType(type);
705 }
706
707 syncer::UserShare* SyncBackendHost::GetUserShare() const {
708 return core_->sync_manager()->GetUserShare();
709 }
710
711 SyncBackendHost::Status SyncBackendHost::GetDetailedStatus() {
712 DCHECK(initialized());
713 return core_->sync_manager()->GetDetailedStatus();
714 }
715
716 SyncSessionSnapshot SyncBackendHost::GetLastSessionSnapshot() const {
717 return last_snapshot_;
718 }
719
720 bool SyncBackendHost::HasUnsyncedItems() const {
721 DCHECK(initialized());
722 return core_->sync_manager()->HasUnsyncedItems();
723 }
724
725 bool SyncBackendHost::IsNigoriEnabled() const {
726 return registrar_.get() && registrar_->IsNigoriEnabled();
727 }
728
729 syncer::PassphraseType SyncBackendHost::GetPassphraseType() const {
730 return cached_passphrase_type_;
731 }
732
733 base::Time SyncBackendHost::GetExplicitPassphraseTime() const {
734 return cached_explicit_passphrase_time_;
735 }
736
737 bool SyncBackendHost::IsCryptographerReady(
738 const syncer::BaseTransaction* trans) const {
739 return initialized() && trans->GetCryptographer()->is_ready();
740 }
741
742 void SyncBackendHost::GetModelSafeRoutingInfo(
743 syncer::ModelSafeRoutingInfo* out) const {
744 if (initialized()) {
745 CHECK(registrar_.get());
746 registrar_->GetModelSafeRoutingInfo(out);
747 } else {
748 NOTREACHED();
749 }
750 }
751
752 SyncedDeviceTracker* SyncBackendHost::GetSyncedDeviceTracker() const {
753 if (!initialized())
754 return NULL;
755 return core_->synced_device_tracker();
756 }
757
758 void SyncBackendHost::InitCore(scoped_ptr<DoInitializeOptions> options) {
759 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
760 base::Bind(&SyncBackendHost::Core::DoInitialize,
761 core_.get(), base::Passed(&options)));
762 }
763
764 void SyncBackendHost::RequestConfigureSyncer(
765 syncer::ConfigureReason reason,
766 syncer::ModelTypeSet to_download,
767 syncer::ModelTypeSet to_purge,
768 syncer::ModelTypeSet to_journal,
769 syncer::ModelTypeSet to_unapply,
770 syncer::ModelTypeSet to_ignore,
771 const syncer::ModelSafeRoutingInfo& routing_info,
772 const base::Callback<void(syncer::ModelTypeSet,
773 syncer::ModelTypeSet)>& ready_task,
774 const base::Closure& retry_callback) {
775 DoConfigureSyncerTypes config_types;
776 config_types.to_download = to_download;
777 config_types.to_purge = to_purge;
778 config_types.to_journal = to_journal;
779 config_types.to_unapply = to_unapply;
780 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
781 base::Bind(&SyncBackendHost::Core::DoConfigureSyncer,
782 core_.get(),
783 reason,
784 config_types,
785 routing_info,
786 ready_task,
787 retry_callback));
788 }
789
790 void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop(
791 const syncer::ModelTypeSet enabled_types,
792 const syncer::ModelTypeSet succeeded_configuration_types,
793 const syncer::ModelTypeSet failed_configuration_types,
794 const base::Callback<void(syncer::ModelTypeSet,
795 syncer::ModelTypeSet)>& ready_task) {
796 if (!frontend_)
797 return;
798
799 invalidator_->UpdateRegisteredInvalidationIds(
800 this,
801 ModelTypeSetToObjectIdSet(enabled_types));
802
803 if (!ready_task.is_null())
804 ready_task.Run(succeeded_configuration_types, failed_configuration_types);
805 }
806
807 void SyncBackendHost::Observe(
808 int type,
809 const content::NotificationSource& source,
810 const content::NotificationDetails& details) {
811 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
812 DCHECK_EQ(type, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL);
813
814 content::Details<const syncer::ModelTypeSet> state_details(details);
815 const syncer::ModelTypeSet& types = *(state_details.ptr());
816 registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
817 base::Bind(&SyncBackendHost::Core::DoRefreshTypes, core_.get(), types));
818 }
819
820 SyncBackendHost::DoInitializeOptions::DoInitializeOptions(
821 base::MessageLoop* sync_loop,
822 SyncBackendRegistrar* registrar,
823 const syncer::ModelSafeRoutingInfo& routing_info,
824 const std::vector<syncer::ModelSafeWorker*>& workers,
825 const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity,
826 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
827 const GURL& service_url,
828 scoped_ptr<syncer::HttpPostProviderFactory> http_bridge_factory,
829 const syncer::SyncCredentials& credentials,
830 const std::string& invalidator_client_id,
831 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
832 bool delete_sync_data_folder,
833 const std::string& restored_key_for_bootstrapping,
834 const std::string& restored_keystore_key_for_bootstrapping,
835 scoped_ptr<InternalComponentsFactory> internal_components_factory,
836 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
837 syncer::ReportUnrecoverableErrorFunction
838 report_unrecoverable_error_function)
839 : sync_loop(sync_loop),
840 registrar(registrar),
841 routing_info(routing_info),
842 workers(workers),
843 extensions_activity(extensions_activity),
844 event_handler(event_handler),
845 service_url(service_url),
846 http_bridge_factory(http_bridge_factory.Pass()),
847 credentials(credentials),
848 invalidator_client_id(invalidator_client_id),
849 sync_manager_factory(sync_manager_factory.Pass()),
850 delete_sync_data_folder(delete_sync_data_folder),
851 restored_key_for_bootstrapping(restored_key_for_bootstrapping),
852 restored_keystore_key_for_bootstrapping(
853 restored_keystore_key_for_bootstrapping),
854 internal_components_factory(internal_components_factory.Pass()),
855 unrecoverable_error_handler(unrecoverable_error_handler.Pass()),
856 report_unrecoverable_error_function(
857 report_unrecoverable_error_function) {
858 }
859
860 SyncBackendHost::DoInitializeOptions::~DoInitializeOptions() {}
861
862 SyncBackendHost::Core::Core(const std::string& name,
863 const base::FilePath& sync_data_folder_path,
864 bool has_sync_setup_completed,
865 const base::WeakPtr<SyncBackendHost>& backend)
866 : name_(name),
867 sync_data_folder_path_(sync_data_folder_path),
868 host_(backend),
869 sync_loop_(NULL),
870 registrar_(NULL),
871 has_sync_setup_completed_(has_sync_setup_completed),
872 weak_ptr_factory_(this) {
873 DCHECK(backend.get());
874 }
875
876 SyncBackendHost::Core::~Core() {
877 DCHECK(!sync_manager_.get());
878 }
879
880 void SyncBackendHost::Core::OnSyncCycleCompleted(
881 const SyncSessionSnapshot& snapshot) {
882 if (!sync_loop_)
883 return;
884 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
885
886 host_.Call(
887 FROM_HERE,
888 &SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop,
889 snapshot);
890 }
891
892 void SyncBackendHost::Core::DoRefreshTypes(syncer::ModelTypeSet types) {
893 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
894 sync_manager_->RefreshTypes(types);
895 }
896
897 void SyncBackendHost::Core::OnControlTypesDownloadRetry() {
898 host_.Call(FROM_HERE,
899 &SyncBackendHost::HandleControlTypesDownloadRetry);
900 }
901
902 void SyncBackendHost::Core::OnInitializationComplete(
903 const syncer::WeakHandle<syncer::JsBackend>& js_backend,
904 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
905 debug_info_listener,
906 bool success,
907 const syncer::ModelTypeSet restored_types) {
908 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
909
910 if (!success) {
911 DoDestroySyncManager();
912 host_.Call(FROM_HERE,
913 &SyncBackendHost::HandleInitializationFailureOnFrontendLoop);
914 return;
915 }
916
917 // Register for encryption related changes now. We have to do this before
918 // the initializing downloading control types or initializing the encryption
919 // handler in order to receive notifications triggered during encryption
920 // startup.
921 sync_manager_->GetEncryptionHandler()->AddObserver(this);
922
923 // Sync manager initialization is complete, so we can schedule recurring
924 // SaveChanges.
925 sync_loop_->PostTask(FROM_HERE,
926 base::Bind(&Core::StartSavingChanges,
927 weak_ptr_factory_.GetWeakPtr()));
928
929 // Hang on to these for a while longer. We're not ready to hand them back to
930 // the UI thread yet.
931 js_backend_ = js_backend;
932 debug_info_listener_ = debug_info_listener;
933
934 // Track whether or not sync DB and preferences were in sync.
935 SyncBackendInitState backend_init_state;
936 if (has_sync_setup_completed_ && !restored_types.Empty()) {
937 backend_init_state = SETUP_COMPLETED_FOUND_RESTORED_TYPES;
938 } else if (has_sync_setup_completed_ && restored_types.Empty()) {
939 backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES;
940 } else if (!has_sync_setup_completed_ && restored_types.Empty()) {
941 backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES;
942 } else { // (!has_sync_setup_completed_ && !restored_types.Empty())
943 backend_init_state = FIRST_SETUP_RESTORED_TYPES;
944 }
945
946 UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState",
947 backend_init_state,
948 SYNC_BACKEND_INIT_STATE_COUNT);
949
950 // Before proceeding any further, we need to download the control types and
951 // purge any partial data (ie. data downloaded for a type that was on its way
952 // to being initially synced, but didn't quite make it.). The following
953 // configure cycle will take care of this. It depends on the registrar state
954 // which we initialize below to ensure that we don't perform any downloads if
955 // all control types have already completed their initial sync.
956 registrar_->SetInitialTypes(restored_types);
957
958 syncer::ConfigureReason reason =
959 restored_types.Empty() ?
960 syncer::CONFIGURE_REASON_NEW_CLIENT :
961 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
962
963 syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes(
964 syncer::ControlTypes(), syncer::ModelTypeSet());
965 syncer::ModelSafeRoutingInfo routing_info;
966 registrar_->GetModelSafeRoutingInfo(&routing_info);
967 SDVLOG(1) << "Control Types "
968 << syncer::ModelTypeSetToString(new_control_types)
969 << " added; calling ConfigureSyncer";
970
971 syncer::ModelTypeSet types_to_purge =
972 syncer::Difference(syncer::ModelTypeSet::All(),
973 GetRoutingInfoTypes(routing_info));
974
975 sync_manager_->ConfigureSyncer(
976 reason,
977 new_control_types,
978 types_to_purge,
979 syncer::ModelTypeSet(),
980 syncer::ModelTypeSet(),
981 routing_info,
982 base::Bind(&SyncBackendHost::Core::DoInitialProcessControlTypes,
983 weak_ptr_factory_.GetWeakPtr()),
984 base::Bind(&SyncBackendHost::Core::OnControlTypesDownloadRetry,
985 weak_ptr_factory_.GetWeakPtr()));
986 }
987
988 void SyncBackendHost::Core::OnConnectionStatusChange(
989 syncer::ConnectionStatus status) {
990 if (!sync_loop_)
991 return;
992 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
993 host_.Call(
994 FROM_HERE,
995 &SyncBackendHost::HandleConnectionStatusChangeOnFrontendLoop, status);
996 }
997
998 void SyncBackendHost::Core::OnPassphraseRequired(
999 syncer::PassphraseRequiredReason reason,
1000 const sync_pb::EncryptedData& pending_keys) {
1001 if (!sync_loop_)
1002 return;
1003 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1004 host_.Call(
1005 FROM_HERE,
1006 &SyncBackendHost::NotifyPassphraseRequired, reason, pending_keys);
1007 }
1008
1009 void SyncBackendHost::Core::OnPassphraseAccepted() {
1010 if (!sync_loop_)
1011 return;
1012 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1013 host_.Call(
1014 FROM_HERE,
1015 &SyncBackendHost::NotifyPassphraseAccepted);
1016 }
1017
1018 void SyncBackendHost::Core::OnBootstrapTokenUpdated(
1019 const std::string& bootstrap_token,
1020 syncer::BootstrapTokenType type) {
1021 if (!sync_loop_)
1022 return;
1023 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1024 host_.Call(FROM_HERE,
1025 &SyncBackendHost::PersistEncryptionBootstrapToken,
1026 bootstrap_token,
1027 type);
1028 }
1029
1030 void SyncBackendHost::Core::OnStopSyncingPermanently() {
1031 if (!sync_loop_)
1032 return;
1033 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1034 host_.Call(
1035 FROM_HERE,
1036 &SyncBackendHost::HandleStopSyncingPermanentlyOnFrontendLoop);
1037 }
1038
1039 void SyncBackendHost::Core::OnEncryptedTypesChanged(
1040 syncer::ModelTypeSet encrypted_types,
1041 bool encrypt_everything) {
1042 if (!sync_loop_)
1043 return;
1044 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1045 // NOTE: We're in a transaction.
1046 host_.Call(
1047 FROM_HERE,
1048 &SyncBackendHost::NotifyEncryptedTypesChanged,
1049 encrypted_types, encrypt_everything);
1050 }
1051
1052 void SyncBackendHost::Core::OnEncryptionComplete() {
1053 if (!sync_loop_)
1054 return;
1055 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1056 // NOTE: We're in a transaction.
1057 host_.Call(
1058 FROM_HERE,
1059 &SyncBackendHost::NotifyEncryptionComplete);
1060 }
1061
1062 void SyncBackendHost::Core::OnCryptographerStateChanged(
1063 syncer::Cryptographer* cryptographer) {
1064 // Do nothing.
1065 }
1066
1067 void SyncBackendHost::Core::OnPassphraseTypeChanged(
1068 syncer::PassphraseType type, base::Time passphrase_time) {
1069 host_.Call(
1070 FROM_HERE,
1071 &SyncBackendHost::HandlePassphraseTypeChangedOnFrontendLoop,
1072 type, passphrase_time);
1073 }
1074
1075 void SyncBackendHost::Core::OnActionableError(
1076 const syncer::SyncProtocolError& sync_error) {
1077 if (!sync_loop_)
1078 return;
1079 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1080 host_.Call(
1081 FROM_HERE,
1082 &SyncBackendHost::HandleActionableErrorEventOnFrontendLoop,
1083 sync_error);
1084 }
1085
1086 void SyncBackendHost::Core::DoOnInvalidatorStateChange(
1087 syncer::InvalidatorState state) {
1088 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1089 sync_manager_->OnInvalidatorStateChange(state);
1090 }
1091
1092 void SyncBackendHost::Core::DoOnIncomingInvalidation(
1093 syncer::ObjectIdInvalidationMap invalidation_map) {
1094 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1095 sync_manager_->OnIncomingInvalidation(invalidation_map);
1096 }
1097
1098 void SyncBackendHost::Core::DoInitialize(
1099 scoped_ptr<DoInitializeOptions> options) {
1100 DCHECK(!sync_loop_);
1101 sync_loop_ = options->sync_loop;
1102 DCHECK(sync_loop_);
1103
1104 // Finish initializing the HttpBridgeFactory. We do this here because
1105 // building the user agent may block on some platforms.
1106 chrome::VersionInfo version_info;
1107 options->http_bridge_factory->Init(
1108 DeviceInfo::MakeUserAgentForSyncApi(version_info));
1109
1110 // Blow away the partial or corrupt sync data folder before doing any more
1111 // initialization, if necessary.
1112 if (options->delete_sync_data_folder) {
1113 DeleteSyncDataFolder();
1114 }
1115
1116 // Make sure that the directory exists before initializing the backend.
1117 // If it already exists, this will do no harm.
1118 if (!file_util::CreateDirectory(sync_data_folder_path_)) {
1119 DLOG(FATAL) << "Sync Data directory creation failed.";
1120 }
1121
1122 DCHECK(!registrar_);
1123 registrar_ = options->registrar;
1124 DCHECK(registrar_);
1125
1126 sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_);
1127 sync_manager_->AddObserver(this);
1128 sync_manager_->Init(sync_data_folder_path_,
1129 options->event_handler,
1130 options->service_url.host() + options->service_url.path(),
1131 options->service_url.EffectiveIntPort(),
1132 options->service_url.SchemeIsSecure(),
1133 options->http_bridge_factory.Pass(),
1134 options->workers,
1135 options->extensions_activity,
1136 options->registrar /* as SyncManager::ChangeDelegate */,
1137 options->credentials,
1138 options->invalidator_client_id,
1139 options->restored_key_for_bootstrapping,
1140 options->restored_keystore_key_for_bootstrapping,
1141 options->internal_components_factory.get(),
1142 &encryptor_,
1143 options->unrecoverable_error_handler.Pass(),
1144 options->report_unrecoverable_error_function,
1145 &stop_syncing_signal_);
1146
1147 // |sync_manager_| may end up being NULL here in tests (in
1148 // synchronous initialization mode).
1149 //
1150 // TODO(akalin): Fix this behavior (see http://crbug.com/140354).
1151 if (sync_manager_) {
1152 // Now check the command line to see if we need to simulate an
1153 // unrecoverable error for testing purpose. Note the error is thrown
1154 // only if the initialization succeeded. Also it makes sense to use this
1155 // flag only when restarting the browser with an account already setup. If
1156 // you use this before setting up the setup would not succeed as an error
1157 // would be encountered.
1158 if (CommandLine::ForCurrentProcess()->HasSwitch(
1159 switches::kSyncThrowUnrecoverableError)) {
1160 sync_manager_->ThrowUnrecoverableError();
1161 }
1162 }
1163 }
1164
1165 void SyncBackendHost::Core::DoUpdateCredentials(
1166 const SyncCredentials& credentials) {
1167 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1168 // UpdateCredentials can be called during backend initialization, possibly
1169 // when backend initialization has failed but hasn't notified the UI thread
1170 // yet. In that case, the sync manager may have been destroyed on the sync
1171 // thread before this task was executed, so we do nothing.
1172 if (sync_manager_) {
1173 sync_manager_->UpdateCredentials(credentials);
1174 }
1175 }
1176
1177 void SyncBackendHost::Core::DoStartSyncing(
1178 const syncer::ModelSafeRoutingInfo& routing_info) {
1179 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1180 sync_manager_->StartSyncingNormally(routing_info);
1181 }
1182
1183 void SyncBackendHost::Core::DoSetEncryptionPassphrase(
1184 const std::string& passphrase,
1185 bool is_explicit) {
1186 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1187 sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(
1188 passphrase, is_explicit);
1189 }
1190
1191 void SyncBackendHost::Core::DoInitialProcessControlTypes() {
1192 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1193
1194 DVLOG(1) << "Initilalizing Control Types";
1195
1196 // Initialize encryption.
1197 sync_manager_->GetEncryptionHandler()->Init();
1198
1199 // Note: experiments are currently handled via SBH::AddExperimentalTypes,
1200 // which is called at the end of every sync cycle.
1201 // TODO(zea): eventually add an experiment handler and initialize it here.
1202
1203 if (!sync_manager_->GetUserShare()) { // NULL in some tests.
1204 DVLOG(1) << "Skipping initialization of DeviceInfo";
1205 host_.Call(
1206 FROM_HERE,
1207 &SyncBackendHost::HandleInitializationFailureOnFrontendLoop);
1208 return;
1209 }
1210
1211 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
1212 LOG(ERROR) << "Failed to download control types";
1213 host_.Call(
1214 FROM_HERE,
1215 &SyncBackendHost::HandleInitializationFailureOnFrontendLoop);
1216 return;
1217 }
1218
1219 // Initialize device info. This is asynchronous on some platforms, so we
1220 // provide a callback for when it finishes.
1221 synced_device_tracker_.reset(
1222 new SyncedDeviceTracker(sync_manager_->GetUserShare(),
1223 sync_manager_->cache_guid()));
1224 synced_device_tracker_->InitLocalDeviceInfo(
1225 base::Bind(&SyncBackendHost::Core::DoFinishInitialProcessControlTypes,
1226 weak_ptr_factory_.GetWeakPtr()));
1227 }
1228
1229 void SyncBackendHost::Core::DoFinishInitialProcessControlTypes() {
1230 registrar_->ActivateDataType(syncer::DEVICE_INFO,
1231 syncer::GROUP_PASSIVE,
1232 synced_device_tracker_.get(),
1233 sync_manager_->GetUserShare());
1234
1235 host_.Call(
1236 FROM_HERE,
1237 &SyncBackendHost::HandleInitializationSuccessOnFrontendLoop,
1238 js_backend_,
1239 debug_info_listener_);
1240
1241 js_backend_.Reset();
1242 debug_info_listener_.Reset();
1243 }
1244
1245 void SyncBackendHost::Core::DoSetDecryptionPassphrase(
1246 const std::string& passphrase) {
1247 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1248 sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(
1249 passphrase);
1250 }
1251
1252 void SyncBackendHost::Core::DoEnableEncryptEverything() {
1253 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1254 sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
1255 }
1256
1257 void SyncBackendHost::Core::ShutdownOnUIThread() {
1258 // This will cut short any blocking network tasks, cut short any in-progress
1259 // sync cycles, and prevent the creation of new blocking network tasks and new
1260 // sync cycles. If there was an in-progress network request, it would have
1261 // had a reference to the RequestContextGetter. This reference will be
1262 // dropped by the time this function returns.
1263 //
1264 // It is safe to call this even if Sync's backend classes have not been
1265 // initialized yet. Those classes will receive the message when the sync
1266 // thread finally getes around to constructing them.
1267 stop_syncing_signal_.Signal();
1268
1269 // This will drop the HttpBridgeFactory's reference to the
1270 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can
1271 // no longer be used to create new HttpBridge instances. We can get away with
1272 // this because the stop_syncing_signal_ has already been signalled, which
1273 // guarantees that the ServerConnectionManager will no longer attempt to
1274 // create new connections.
1275 release_request_context_signal_.Signal();
1276 }
1277
1278 void SyncBackendHost::Core::DoShutdown(bool sync_disabled) {
1279 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1280
1281 // It's safe to do this even if the type was never activated.
1282 registrar_->DeactivateDataType(syncer::DEVICE_INFO);
1283 synced_device_tracker_.reset();
1284
1285 DoDestroySyncManager();
1286
1287 registrar_ = NULL;
1288
1289 if (sync_disabled)
1290 DeleteSyncDataFolder();
1291
1292 host_.Reset();
1293 weak_ptr_factory_.InvalidateWeakPtrs();
1294 }
1295
1296 void SyncBackendHost::Core::DoDestroySyncManager() {
1297 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1298 if (sync_manager_) {
1299 save_changes_timer_.reset();
1300 sync_manager_->RemoveObserver(this);
1301 sync_manager_->ShutdownOnSyncThread();
1302 sync_manager_.reset();
1303 }
1304 }
1305
1306 void SyncBackendHost::Core::DoConfigureSyncer(
1307 syncer::ConfigureReason reason,
1308 const DoConfigureSyncerTypes& config_types,
1309 const syncer::ModelSafeRoutingInfo routing_info,
1310 const base::Callback<void(syncer::ModelTypeSet,
1311 syncer::ModelTypeSet)>& ready_task,
1312 const base::Closure& retry_callback) {
1313 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1314 sync_manager_->ConfigureSyncer(
1315 reason,
1316 config_types.to_download,
1317 config_types.to_purge,
1318 config_types.to_journal,
1319 config_types.to_unapply,
1320 routing_info,
1321 base::Bind(&SyncBackendHost::Core::DoFinishConfigureDataTypes,
1322 weak_ptr_factory_.GetWeakPtr(),
1323 config_types.to_download,
1324 ready_task),
1325 base::Bind(&SyncBackendHost::Core::DoRetryConfiguration,
1326 weak_ptr_factory_.GetWeakPtr(),
1327 retry_callback));
1328 }
1329
1330 void SyncBackendHost::Core::DoFinishConfigureDataTypes(
1331 syncer::ModelTypeSet types_to_config,
1332 const base::Callback<void(syncer::ModelTypeSet,
1333 syncer::ModelTypeSet)>& ready_task) {
1334 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1335
1336 // Update the enabled types for the bridge and sync manager.
1337 syncer::ModelSafeRoutingInfo routing_info;
1338 registrar_->GetModelSafeRoutingInfo(&routing_info);
1339 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
1340 enabled_types.RemoveAll(syncer::ProxyTypes());
1341
1342 const syncer::ModelTypeSet failed_configuration_types =
1343 Difference(types_to_config, sync_manager_->InitialSyncEndedTypes());
1344 const syncer::ModelTypeSet succeeded_configuration_types =
1345 Difference(types_to_config, failed_configuration_types);
1346 host_.Call(FROM_HERE,
1347 &SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop,
1348 enabled_types,
1349 succeeded_configuration_types,
1350 failed_configuration_types,
1351 ready_task);
1352 }
1353
1354 void SyncBackendHost::Core::DoRetryConfiguration(
1355 const base::Closure& retry_callback) {
1356 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1357 host_.Call(FROM_HERE,
1358 &SyncBackendHost::RetryConfigurationOnFrontendLoop,
1359 retry_callback);
1360 }
1361
1362 void SyncBackendHost::Core::DeleteSyncDataFolder() {
1363 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1364 if (base::DirectoryExists(sync_data_folder_path_)) {
1365 if (!base::DeleteFile(sync_data_folder_path_, true))
1366 SLOG(DFATAL) << "Could not delete the Sync Data folder.";
1367 }
1368 }
1369
1370 void SyncBackendHost::Core::StartSavingChanges() {
1371 // We may already be shut down.
1372 if (!sync_loop_)
1373 return;
1374 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1375 DCHECK(!save_changes_timer_.get());
1376 save_changes_timer_.reset(new base::RepeatingTimer<Core>());
1377 save_changes_timer_->Start(FROM_HERE,
1378 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
1379 this, &Core::SaveChanges);
1380 }
1381
1382 void SyncBackendHost::Core::SaveChanges() {
1383 DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
1384 sync_manager_->SaveChanges();
1385 }
1386
1387 void SyncBackendHost::AddExperimentalTypes() {
1388 CHECK(initialized());
1389 syncer::Experiments experiments;
1390 if (core_->sync_manager()->ReceivedExperiment(&experiments))
1391 frontend_->OnExperimentsChanged(experiments);
1392 }
1393
1394 void SyncBackendHost::HandleControlTypesDownloadRetry() {
1395 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1396 if (!frontend_)
1397 return;
1398
1399 frontend_->OnSyncConfigureRetry();
1400 }
1401
1402 void SyncBackendHost::HandleInitializationSuccessOnFrontendLoop(
1403 const syncer::WeakHandle<syncer::JsBackend> js_backend,
1404 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>
1405 debug_info_listener) {
1406 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1407 if (!frontend_)
1408 return;
1409
1410 initialized_ = true;
1411
1412 invalidator_->RegisterInvalidationHandler(this);
1413 invalidation_handler_registered_ = true;
1414
1415 // Fake a state change to initialize the SyncManager's cached invalidator
1416 // state.
1417 OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
1418
1419 // Start forwarding refresh requests to the SyncManager
1420 notification_registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
1421 content::Source<Profile>(profile_));
1422
1423 // Now that we've downloaded the control types, we can see if there are any
1424 // experimental types to enable. This should be done before we inform
1425 // the frontend to ensure they're visible in the customize screen.
1426 AddExperimentalTypes();
1427 frontend_->OnBackendInitialized(js_backend,
1428 debug_info_listener,
1429 true);
1430 }
1431
1432 void SyncBackendHost::HandleInitializationFailureOnFrontendLoop() {
1433 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1434 if (!frontend_)
1435 return;
1436
1437 frontend_->OnBackendInitialized(
1438 syncer::WeakHandle<syncer::JsBackend>(),
1439 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
1440 false);
1441 }
1442
1443 void SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop(
1444 const SyncSessionSnapshot& snapshot) {
1445 if (!frontend_)
1446 return;
1447 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1448
1449 last_snapshot_ = snapshot;
1450
1451 SDVLOG(1) << "Got snapshot " << snapshot.ToString();
1452
1453 const syncer::ModelTypeSet to_migrate =
1454 snapshot.model_neutral_state().types_needing_local_migration;
1455 if (!to_migrate.Empty())
1456 frontend_->OnMigrationNeededForTypes(to_migrate);
1457
1458 // Process any changes to the datatypes we're syncing.
1459 // TODO(sync): add support for removing types.
1460 if (initialized())
1461 AddExperimentalTypes();
1462
1463 if (initialized())
1464 frontend_->OnSyncCycleCompleted();
1465 }
1466
1467 void SyncBackendHost::RetryConfigurationOnFrontendLoop(
1468 const base::Closure& retry_callback) {
1469 SDVLOG(1) << "Failed to complete configuration, informing of retry.";
1470 retry_callback.Run();
1471 }
1472
1473 void SyncBackendHost::PersistEncryptionBootstrapToken(
1474 const std::string& token,
1475 syncer::BootstrapTokenType token_type) {
1476 CHECK(sync_prefs_.get());
1477 DCHECK(!token.empty());
1478 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN)
1479 sync_prefs_->SetEncryptionBootstrapToken(token);
1480 else
1481 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token);
1482 }
1483
1484 void SyncBackendHost::HandleActionableErrorEventOnFrontendLoop(
1485 const syncer::SyncProtocolError& sync_error) {
1486 if (!frontend_)
1487 return;
1488 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1489 frontend_->OnActionableError(sync_error);
1490 }
1491
1492 void SyncBackendHost::OnInvalidatorStateChange(syncer::InvalidatorState state) {
1493 registrar_->sync_thread()->message_loop()->PostTask(
1494 FROM_HERE,
1495 base::Bind(&SyncBackendHost::Core::DoOnInvalidatorStateChange,
1496 core_.get(),
1497 state));
1498 }
1499
1500 void SyncBackendHost::OnIncomingInvalidation(
1501 const syncer::ObjectIdInvalidationMap& invalidation_map) {
1502 // TODO(rlarocque): Acknowledge these invalidations only after the syncer has
1503 // acted on them and saved the results to disk.
1504 syncer::ObjectIdSet ids = invalidation_map.GetObjectIds();
1505 for (syncer::ObjectIdSet::const_iterator it = ids.begin();
1506 it != ids.end(); ++it) {
1507 const syncer::AckHandle& handle =
1508 invalidation_map.ForObject(*it).back().ack_handle();
1509 invalidator_->AcknowledgeInvalidation(*it, handle);
1510 }
1511
1512 registrar_->sync_thread()->message_loop()->PostTask(
1513 FROM_HERE,
1514 base::Bind(&SyncBackendHost::Core::DoOnIncomingInvalidation,
1515 core_.get(),
1516 invalidation_map));
1517 }
1518
1519 bool SyncBackendHost::CheckPassphraseAgainstCachedPendingKeys(
1520 const std::string& passphrase) const {
1521 DCHECK(cached_pending_keys_.has_blob());
1522 DCHECK(!passphrase.empty());
1523 syncer::Nigori nigori;
1524 nigori.InitByDerivation("localhost", "dummy", passphrase);
1525 std::string plaintext;
1526 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext);
1527 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys.";
1528 return result;
1529 }
1530
1531 void SyncBackendHost::NotifyPassphraseRequired(
1532 syncer::PassphraseRequiredReason reason,
1533 sync_pb::EncryptedData pending_keys) {
1534 if (!frontend_)
1535 return;
1536
1537 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1538
1539 // Update our cache of the cryptographer's pending keys.
1540 cached_pending_keys_ = pending_keys;
1541
1542 frontend_->OnPassphraseRequired(reason, pending_keys);
1543 }
1544
1545 void SyncBackendHost::NotifyPassphraseAccepted() {
1546 if (!frontend_)
1547 return;
1548
1549 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1550
1551 // Clear our cache of the cryptographer's pending keys.
1552 cached_pending_keys_.clear_blob();
1553 frontend_->OnPassphraseAccepted();
1554 }
1555
1556 void SyncBackendHost::NotifyEncryptedTypesChanged(
1557 syncer::ModelTypeSet encrypted_types,
1558 bool encrypt_everything) {
1559 if (!frontend_)
1560 return;
1561
1562 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1563 frontend_->OnEncryptedTypesChanged(
1564 encrypted_types, encrypt_everything);
1565 }
1566
1567 void SyncBackendHost::NotifyEncryptionComplete() {
1568 if (!frontend_)
1569 return;
1570
1571 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1572 frontend_->OnEncryptionComplete();
1573 }
1574
1575 void SyncBackendHost::HandlePassphraseTypeChangedOnFrontendLoop(
1576 syncer::PassphraseType type,
1577 base::Time explicit_passphrase_time) {
1578 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1579 DVLOG(1) << "Passphrase type changed to "
1580 << syncer::PassphraseTypeToString(type);
1581 cached_passphrase_type_ = type;
1582 cached_explicit_passphrase_time_ = explicit_passphrase_time;
1583 }
1584
1585 void SyncBackendHost::HandleStopSyncingPermanentlyOnFrontendLoop() {
1586 if (!frontend_)
1587 return;
1588 frontend_->OnStopSyncingPermanently();
1589 }
1590
1591 void SyncBackendHost::HandleConnectionStatusChangeOnFrontendLoop(
1592 syncer::ConnectionStatus status) {
1593 if (!frontend_)
1594 return;
1595
1596 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_);
1597
1598 DVLOG(1) << "Connection status changed: "
1599 << syncer::ConnectionStatusToString(status);
1600 frontend_->OnConnectionStatusChange(status);
1601 }
1602
1603 base::MessageLoop* SyncBackendHost::GetSyncLoopForTesting() {
1604 return registrar_->sync_thread()->message_loop();
1605 }
1606
1607 #undef SDVLOG
1608
1609 #undef SLOG
1610 12
1611 } // namespace browser_sync 13 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698