1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
#define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
#pragma once
#include <map>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "base/timer.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/sync/engine/syncapi.h"
#include "chrome/browser/sync/engine/configure_reason.h"
#include "chrome/browser/sync/engine/model_safe_worker.h"
#include "chrome/browser/sync/js_backend.h"
#include "chrome/browser/sync/js_sync_manager_observer.h"
#include "chrome/browser/sync/glue/data_type_controller.h"
#include "chrome/browser/sync/glue/ui_model_worker.h"
#include "chrome/browser/sync/js_event_router.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/common/net/gaia/google_service_auth_error.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request_context_getter.h"
class CancelableTask;
class Profile;
namespace net {
class URLRequestContextGetter;
}
namespace sync_notifier {
class SyncNotifier;
} // namespace sync_notifier
namespace browser_sync {
namespace sessions {
struct SyncSessionSnapshot;
}
class ChangeProcessor;
class DataTypeController;
class JsArgList;
// SyncFrontend is the interface used by SyncBackendHost to communicate with
// the entity that created it and, presumably, is interested in sync-related
// activity.
// NOTE: All methods will be invoked by a SyncBackendHost on the same thread
// used to create that SyncBackendHost.
class SyncFrontend {
public:
SyncFrontend() {}
// The backend has completed initialization and it is now ready to accept and
// process changes.
virtual void OnBackendInitialized() = 0;
// The backend queried the server recently and received some updates.
virtual void OnSyncCycleCompleted() = 0;
// The backend encountered an authentication problem and requests new
// credentials to be provided. See SyncBackendHost::Authenticate for details.
virtual void OnAuthError() = 0;
// We are no longer permitted to communicate with the server. Sync should
// be disabled and state cleaned up at once.
virtual void OnStopSyncingPermanently() = 0;
// Called to handle success/failure of clearing server data
virtual void OnClearServerDataSucceeded() = 0;
virtual void OnClearServerDataFailed() = 0;
// The syncer requires a passphrase to decrypt sensitive updates. This is
// called when the first sensitive data type is setup by the user and anytime
// the passphrase is changed by another synced client. |reason| denotes why
// the passphrase was required.
virtual void OnPassphraseRequired(
sync_api::PassphraseRequiredReason reason) = 0;
// Called when the passphrase provided by the user is
// accepted. After this is called, updates to sensitive nodes are
// encrypted using the accepted passphrase.
virtual void OnPassphraseAccepted() = 0;
virtual void OnEncryptionComplete(
const syncable::ModelTypeSet& encrypted_types) = 0;
// Called to perform migration of |types|.
virtual void OnMigrationNeededForTypes(
const syncable::ModelTypeSet& types) = 0;
protected:
// Don't delete through SyncFrontend interface.
virtual ~SyncFrontend() {
}
private:
DISALLOW_COPY_AND_ASSIGN(SyncFrontend);
};
// A UI-thread safe API into the sync backend that "hosts" the top-level
// syncapi element, the SyncManager, on its own thread. This class handles
// dispatch of potentially blocking calls to appropriate threads and ensures
// that the SyncFrontend is only accessed on the UI loop.
class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
public:
typedef sync_api::SyncManager::Status::Summary StatusSummary;
typedef sync_api::SyncManager::Status Status;
typedef std::map<ModelSafeGroup,
scoped_refptr<browser_sync::ModelSafeWorker> > WorkerMap;
// Create a SyncBackendHost with a reference to the |frontend| that it serves
// and communicates to via the SyncFrontend interface (on the same thread
// it used to call the constructor).
explicit SyncBackendHost(Profile* profile);
// For testing.
// TODO(skrul): Extract an interface so this is not needed.
SyncBackendHost();
virtual ~SyncBackendHost();
// Called on |frontend_loop_| to kick off asynchronous initialization.
// As a fallback when no cached auth information is available, try to
// bootstrap authentication using |lsid|, if it isn't empty.
// Optionally delete the Sync Data folder (if it's corrupt).
void Initialize(SyncFrontend* frontend,
const GURL& service_url,
const syncable::ModelTypeSet& types,
net::URLRequestContextGetter* baseline_context_getter,
const sync_api::SyncCredentials& credentials,
bool delete_sync_data_folder);
// Called from |frontend_loop| to update SyncCredentials.
void UpdateCredentials(const sync_api::SyncCredentials& credentials);
// This starts the SyncerThread running a Syncer object to communicate with
// sync servers. Until this is called, no changes will leave or enter this
// browser from the cloud / sync servers.
// Called on |frontend_loop_|.
virtual void StartSyncingWithServer();
// Called on |frontend_loop_| to asynchronously set the passphrase.
// |is_explicit| is true if the call is in response to the user explicitly
// setting a passphrase as opposed to implicitly (from the users' perspective)
// using their Google Account password. An implicit SetPassphrase will *not*
// *not* override an explicit passphrase set previously.
void SetPassphrase(const std::string& passphrase, bool is_explicit);
// Called on |frontend_loop_| to kick off shutdown.
// |sync_disabled| indicates if syncing is being disabled or not.
// See the implementation and Core::DoShutdown for details.
void Shutdown(bool sync_disabled);
// Changes the set of data types that are currently being synced.
// The ready_task will be run when all of the requested data types
// are up-to-date and ready for activation. The task will cancelled
// upon shutdown. The method takes ownership of the task pointer.
virtual void ConfigureDataTypes(
const DataTypeController::TypeMap& data_type_controllers,
const syncable::ModelTypeSet& types,
sync_api::ConfigureReason reason,
CancelableTask* ready_task,
bool enable_nigori);
// Makes an asynchronous call to syncer to switch to config mode. When done
// syncer will call us back on FinishConfigureDataTypes.
virtual void StartConfiguration(Callback0::Type* callback);
// Encrypts the specified datatypes and marks them as needing encryption on
// other machines. This affects all machines synced to this account and all
// data belonging to the specified types.
// Note: actual work is done on core_thread_'s message loop.
virtual void EncryptDataTypes(
const syncable::ModelTypeSet& encrypted_types);
syncable::ModelTypeSet GetEncryptedDataTypes() const;
syncable::AutofillMigrationState
GetAutofillMigrationState();
void SetAutofillMigrationState(
syncable::AutofillMigrationState state);
syncable::AutofillMigrationDebugInfo
GetAutofillMigrationDebugInfo();
void SetAutofillMigrationDebugInfo(
syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
const syncable::AutofillMigrationDebugInfo& info);
// Activates change processing for the given data type. This must
// be called synchronously with the data type's model association so
// no changes are dropped between model association and change
// processor activation.
void ActivateDataType(DataTypeController* data_type_controller,
ChangeProcessor* change_processor);
// Deactivates change processing for the given data type.
void DeactivateDataType(DataTypeController* data_type_controller,
ChangeProcessor* change_processor);
// Asks the server to clear all data associated with ChromeSync.
virtual bool RequestClearServerData();
// Called on |frontend_loop_| to obtain a handle to the UserShare needed
// for creating transactions.
sync_api::UserShare* GetUserShare() const;
// Called from any thread to obtain current status information in detailed or
// summarized form.
Status GetDetailedStatus();
StatusSummary GetStatusSummary();
const GoogleServiceAuthError& GetAuthError() const;
const sessions::SyncSessionSnapshot* GetLastSessionSnapshot() const;
const FilePath& sync_data_folder_path() const {
return sync_data_folder_path_;
}
// Returns the authenticated username of the sync user, or empty if none
// exists. It will only exist if the authentication service provider (e.g
// GAIA) has confirmed the username is authentic.
string16 GetAuthenticatedUsername() const;
// ModelSafeWorkerRegistrar implementation.
virtual void GetWorkers(std::vector<browser_sync::ModelSafeWorker*>* out);
virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out);
// Determines if the underlying sync engine has made any local changes to
// items that have not yet been synced with the server.
// ONLY CALL THIS IF OnInitializationComplete was called!
bool HasUnsyncedItems() const;
// Logs the unsynced items.
void LogUnsyncedItems(int level) const;
// Whether or not we are syncing encryption keys.
bool IsNigoriEnabled() const;
// Whether or not the Nigori node is encrypted using an explicit passphrase.
bool IsUsingExplicitPassphrase();
// True if the cryptographer has any keys available to attempt decryption.
// Could mean we've downloaded and loaded Nigori objects, or we bootstrapped
// using a token previously received.
bool IsCryptographerReady(const sync_api::BaseTransaction* trans) const;
// Returns a pointer to the JsBackend (which is owned by the
// service). Must be called only after the sync backend has been
// initialized, and never returns NULL if you do so. Overrideable
// for testing purposes.
virtual JsBackend* GetJsBackend();
// TODO(akalin): Write unit tests for the JsBackend, finding a way
// to make this class testable in general.
protected:
// The real guts of SyncBackendHost, to keep the public client API clean.
class Core : public base::RefCountedThreadSafe<SyncBackendHost::Core>,
public sync_api::SyncManager::Observer,
public JsBackend,
public JsEventRouter {
public:
Core(const std::string& name, SyncBackendHost* backend);
// SyncManager::Observer implementation. The Core just acts like an air
// traffic controller here, forwarding incoming messages to appropriate
// landing threads.
virtual void OnChangesApplied(
syncable::ModelType model_type,
const sync_api::BaseTransaction* trans,
const sync_api::SyncManager::ChangeRecord* changes,
int change_count);
virtual void OnChangesComplete(syncable::ModelType model_type);
virtual void OnSyncCycleCompleted(
const sessions::SyncSessionSnapshot* snapshot);
virtual void OnInitializationComplete();
virtual void OnAuthError(const GoogleServiceAuthError& auth_error);
virtual void OnPassphraseRequired(
sync_api::PassphraseRequiredReason reason);
virtual void OnPassphraseAccepted(const std::string& bootstrap_token);
virtual void OnStopSyncingPermanently();
virtual void OnUpdatedToken(const std::string& token);
virtual void OnClearServerDataFailed();
virtual void OnClearServerDataSucceeded();
virtual void OnEncryptionComplete(
const syncable::ModelTypeSet& encrypted_types);
// JsBackend implementation.
virtual void SetParentJsEventRouter(JsEventRouter* router) OVERRIDE;
virtual void RemoveParentJsEventRouter() OVERRIDE;
virtual const JsEventRouter* GetParentJsEventRouter() const OVERRIDE;
virtual void ProcessMessage(const std::string& name, const JsArgList& args,
const JsEventHandler* sender) OVERRIDE;
// JsEventRouter implementation.
virtual void RouteJsEvent(const std::string& event_name,
const JsEventDetails& details) OVERRIDE;
virtual void RouteJsMessageReply(const std::string& event_name,
const JsArgList& args,
const JsEventHandler* target) OVERRIDE;
struct DoInitializeOptions {
DoInitializeOptions(
const GURL& service_url,
sync_api::HttpPostProviderFactory* http_bridge_factory,
const sync_api::SyncCredentials& credentials,
bool delete_sync_data_folder,
const std::string& restored_key_for_bootstrapping,
bool setup_for_test_mode);
~DoInitializeOptions();
GURL service_url;
sync_api::HttpPostProviderFactory* http_bridge_factory;
sync_api::SyncCredentials credentials;
std::string lsid;
bool delete_sync_data_folder;
std::string restored_key_for_bootstrapping;
bool setup_for_test_mode;
};
// Called on |frontend_loop_|.
void CreateSyncNotifier(const scoped_refptr<net::URLRequestContextGetter>&
request_context_getter);
// Note:
//
// The Do* methods are the various entry points from our SyncBackendHost.
// It calls us on a dedicated thread to actually perform synchronous
// (and potentially blocking) syncapi operations.
//
// Called on the SyncBackendHost core_thread_ to perform initialization
// of the syncapi on behalf of SyncBackendHost::Initialize.
void DoInitialize(const DoInitializeOptions& options);
// Called on our SyncBackendHost's core_thread_ to perform credential
// update on behalf of SyncBackendHost::UpdateCredentials
void DoUpdateCredentials(const sync_api::SyncCredentials& credentials);
// Called when the user disables or enables a sync type.
void DoUpdateEnabledTypes();
// Called on the SyncBackendHost core_thread_ to tell the syncapi to start
// syncing (generally after initialization and authentication).
void DoStartSyncing();
// Called on the SyncBackendHost core_thread_ to nudge/pause/resume the
// syncer.
void DoRequestNudge(const tracked_objects::Location& location);
void DoRequestClearServerData();
// Sets |deferred_nudge_for_cleanup_requested_| to true. See comment below.
void DeferNudgeForCleanup();
// Called on our SyncBackendHost's |core_thread_| to set the passphrase
// on behalf of SyncBackendHost::SupplyPassphrase.
void DoSetPassphrase(const std::string& passphrase, bool is_explicit);
// Getter/setter for whether we are waiting on SetPassphrase to process a
// passphrase. Set by SetPassphrase, cleared by OnPassphraseRequired or
// OnPassphraseAccepted.
bool processing_passphrase() const;
void set_processing_passphrase();
// Called on SyncBackendHost's |core_thread_| to set the datatypes we need
// to encrypt as well as encrypt all local data of that type.
void DoEncryptDataTypes(const syncable::ModelTypeSet& encrypted_types);
// The shutdown order is a bit complicated:
// 1) From |core_thread_|, invoke the syncapi Shutdown call to do a final
// SaveChanges, close sqlite handles, and halt the syncer thread (which
// could potentially block for 1 minute).
// 2) Then, from |frontend_loop_|, halt the core_thread_. This causes
// syncapi thread-exit handlers to run and make use of cached pointers to
// various components owned implicitly by us.
// 3) Destroy this Core. That will delete syncapi components in a safe order
// because the thread that was using them has exited (in step 2).
void DoShutdown(bool stopping_sync);
// Posts a config request on the core thread.
virtual void DoRequestConfig(const syncable::ModelTypeBitSet& added_types,
sync_api::ConfigureReason reason);
// Start the configuration mode.
virtual void DoStartConfiguration(Callback0::Type* callback);
// Set the base request context to use when making HTTP calls.
// This method will add a reference to the context to persist it
// on the IO thread. Must be removed from IO thread.
sync_api::SyncManager* syncapi() { return syncapi_.get(); }
// Delete the sync data folder to cleanup backend data. Happens the first
// time sync is enabled for a user (to prevent accidentally reusing old
// sync databases), as well as shutdown when you're no longer syncing.
void DeleteSyncDataFolder();
void ConnectChildJsEventRouter();
void DisconnectChildJsEventRouter();
void DoProcessMessage(
const std::string& name, const JsArgList& args,
const JsEventHandler* sender);
// A callback from the SyncerThread when it is safe to continue config.
void FinishConfigureDataTypes();
#if defined(UNIT_TEST)
// Special form of initialization that does not try and authenticate the
// last known user (since it will fail in test mode) and does some extra
// setup to nudge the syncapi into a usable state.
void DoInitializeForTest(const std::wstring& test_user,
sync_api::HttpPostProviderFactory* factory,
bool delete_sync_data_folder) {
// Construct dummy credentials for test.
sync_api::SyncCredentials credentials;
credentials.email = WideToUTF8(test_user);
credentials.sync_token = "token";
DoInitialize(DoInitializeOptions(GURL(), factory, credentials,
delete_sync_data_folder,
"", true));
}
#endif
private:
friend class base::RefCountedThreadSafe<SyncBackendHost::Core>;
friend class SyncBackendHostForProfileSyncTest;
virtual ~Core();
// Return change processor for a particular model (return NULL on failure).
ChangeProcessor* GetProcessor(syncable::ModelType modeltype);
// Invoked when initialization of syncapi is complete and we can start
// our timer.
// This must be called from the thread on which SaveChanges is intended to
// be run on; the host's |core_thread_|.
void StartSavingChanges();
// Invoked periodically to tell the syncapi to persist its state
// by writing to disk.
// This is called from the thread we were created on (which is the
// SyncBackendHost |core_thread_|), using a repeating timer that is kicked
// off as soon as the SyncManager tells us it completed
// initialization.
void SaveChanges();
// Dispatched to from HandleAuthErrorEventOnCoreLoop to handle updating
// frontend UI components.
void HandleAuthErrorEventOnFrontendLoop(
const GoogleServiceAuthError& new_auth_error);
// Invoked when a passphrase is required to decrypt a set of Nigori keys,
// or for encrypting. |reason| denotes why the passhrase was required.
void NotifyPassphraseRequired(sync_api::PassphraseRequiredReason reason);
// Invoked when the passphrase provided by the user has been accepted.
void NotifyPassphraseAccepted(const std::string& bootstrap_token);
// Invoked when an updated token is available from the sync server.
void NotifyUpdatedToken(const std::string& token);
// Invoked when sync finishes encrypting new datatypes or has become aware
// of new datatypes requiring encryption.
void NotifyEncryptionComplete(const syncable::ModelTypeSet&
encrypted_types);
// Called from Core::OnSyncCycleCompleted to handle updating frontend
// thread components.
void HandleSyncCycleCompletedOnFrontendLoop(
sessions::SyncSessionSnapshot* snapshot);
void HandleStopSyncingPermanentlyOnFrontendLoop();
// Called to handle success/failure of clearing server data
void HandleClearServerDataSucceededOnFrontendLoop();
void HandleClearServerDataFailedOnFrontendLoop();
// Called from Core::OnInitializationComplete to handle updating
// frontend thread components.
void HandleInitalizationCompletedOnFrontendLoop();
void RouteJsEventOnFrontendLoop(
const std::string& name, const JsEventDetails& details);
void RouteJsMessageReplyOnFrontendLoop(
const std::string& name, const JsArgList& args,
const JsEventHandler* target);
void FinishConfigureDataTypesOnFrontendLoop();
// Return true if a model lives on the current thread.
bool IsCurrentThreadSafeForModel(syncable::ModelType model_type);
// Our parent SyncBackendHost
SyncBackendHost* host_;
// The timer used to periodically call SaveChanges.
base::RepeatingTimer<Core> save_changes_timer_;
// The top-level syncapi entry point.
scoped_ptr<sync_api::SyncManager> syncapi_;
scoped_ptr<sync_notifier::SyncNotifier> sync_notifier_;
JsSyncManagerObserver sync_manager_observer_;
JsEventRouter* parent_router_;
// Denotes if the core is currently attempting to set a passphrase. While
// this is true, OnPassphraseRequired calls are dropped.
// Note: after initialization, this variable should only ever be accessed or
// modified from within the frontend_loop_ (UI thread).
bool processing_passphrase_;
// True when a datatype has been disabled so that we nudge once sync is
// resumed (after configuration is finished).
bool deferred_nudge_for_cleanup_requested_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
// InitializationComplete passes through the SyncBackendHost to forward
// on to |frontend_|, and so that tests can intercept here if they need to
// set up initial conditions.
virtual void HandleInitializationCompletedOnFrontendLoop();
// Posts a nudge request on the core thread.
virtual void RequestNudge(const tracked_objects::Location& location);
// Called to finish the job of ConfigureDataTypes once the syncer is in
// configuration mode.
void FinishConfigureDataTypes();
void FinishConfigureDataTypesOnFrontendLoop();
// Allows tests to perform alternate core initialization work.
virtual void InitCore(const Core::DoInitializeOptions& options);
// Factory method for HttpPostProviderFactories.
virtual sync_api::HttpPostProviderFactory* MakeHttpBridgeFactory(
net::URLRequestContextGetter* getter);
MessageLoop* core_loop() { return core_thread_.message_loop(); }
void set_syncapi_initialized() { syncapi_initialized_ = true; }
// Helpers to persist a token that can be used to bootstrap sync encryption
// across browser restart to avoid requiring the user to re-enter their
// passphrase. |token| must be valid UTF-8 as we use the PrefService for
// storage.
void PersistEncryptionBootstrapToken(const std::string& token);
std::string RestoreEncryptionBootstrapToken();
// Our core, which communicates directly to the syncapi.
scoped_refptr<Core> core_;
private:
FRIEND_TEST_ALL_PREFIXES(SyncBackendHostTest, MakePendingConfigModeState);
struct PendingConfigureDataTypesState {
PendingConfigureDataTypesState();
~PendingConfigureDataTypesState();
// A task that should be called once data type configuration is
// complete.
scoped_ptr<CancelableTask> ready_task;
// The set of types that we are waiting to be initially synced in a
// configuration cycle.
syncable::ModelTypeSet initial_types;
// Additional details about which types were added / removed.
bool deleted_type;
syncable::ModelTypeBitSet added_types;
sync_api::ConfigureReason reason;
};
UIModelWorker* ui_worker();
void ConfigureAutofillMigration();
// Helper function for ConfigureDataTypes(). Caller owns return
// value. Takes ownership of |ready_task| (but not |routing_info|).
static PendingConfigureDataTypesState* MakePendingConfigModeState(
const DataTypeController::TypeMap& data_type_controllers,
const syncable::ModelTypeSet& types,
CancelableTask* ready_task,
ModelSafeRoutingInfo* routing_info,
sync_api::ConfigureReason reason,
bool nigori_enabled);
// A thread we dedicate for use by our Core to perform initialization,
// authentication, handle messages from the syncapi, and periodically tell
// the syncapi to persist itself.
base::Thread core_thread_;
// A reference to the MessageLoop used to construct |this|, so we know how
// to safely talk back to the SyncFrontend.
MessageLoop* const frontend_loop_;
Profile* profile_;
// This is state required to implement ModelSafeWorkerRegistrar.
struct {
// We maintain ownership of all workers. In some cases, we need to ensure
// shutdown occurs in an expected sequence by Stop()ing certain workers.
// They are guaranteed to be valid because we only destroy elements of
// |workers_| after the syncapi has been destroyed. Unless a worker is no
// longer needed because all types that get routed to it have been disabled
// (from syncing). In that case, we'll destroy on demand *after* routing
// any dependent types to GROUP_PASSIVE, so that the syncapi doesn't call
// into garbage. If a key is present, it means at least one ModelType that
// routes to that model safe group is being synced.
WorkerMap workers;
browser_sync::ModelSafeRoutingInfo routing_info;
} registrar_;
// The user can incur changes to registrar_ at any time from the UI thread.
// The syncapi needs to periodically get a consistent snapshot of the state,
// and it does so from a different thread. Therefore, we protect creation,
// destruction, and re-routing events by acquiring this lock. Note that the
// SyncBackendHost may read (on the UI thread or core thread) from registrar_
// without acquiring the lock (which is typically "read ModelSafeWorker
// pointer value", and then invoke methods), because lifetimes are managed on
// the UI thread. Of course, this comment only applies to ModelSafeWorker
// impls that are themselves thread-safe, such as UIModelWorker.
mutable base::Lock registrar_lock_;
// The frontend which we serve (and are owned by).
SyncFrontend* frontend_;
// The change processors that handle the different data types.
std::map<syncable::ModelType, ChangeProcessor*> processors_;
// Path of the folder that stores the sync data files.
FilePath sync_data_folder_path_;
scoped_ptr<PendingConfigureDataTypesState> pending_download_state_;
scoped_ptr<PendingConfigureDataTypesState> pending_config_mode_state_;
// UI-thread cache of the last AuthErrorState received from syncapi.
GoogleServiceAuthError last_auth_error_;
// UI-thread cache of the last SyncSessionSnapshot received from syncapi.
scoped_ptr<sessions::SyncSessionSnapshot> last_snapshot_;
// Whether we've processed the initialization complete callback.
bool syncapi_initialized_;
DISALLOW_COPY_AND_ASSIGN(SyncBackendHost);
};
} // namespace browser_sync
#endif // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_HOST_H_
|