Index: chrome/browser/sync/internal_api/sync_manager.h |
diff --git a/chrome/browser/sync/internal_api/sync_manager.h b/chrome/browser/sync/internal_api/sync_manager.h |
index ef997a4c7109d80809feb9df4815cccc67984ae7..6b2a8aec76c130f547cea9dc0457d17e331f2e8c 100644 |
--- a/chrome/browser/sync/internal_api/sync_manager.h |
+++ b/chrome/browser/sync/internal_api/sync_manager.h |
@@ -10,6 +10,7 @@ |
#include "base/basictypes.h" |
#include "base/callback_old.h" |
+#include "base/threading/thread_checker.h" |
#include "chrome/browser/sync/internal_api/change_record.h" |
#include "chrome/browser/sync/internal_api/configure_reason.h" |
#include "chrome/browser/sync/protocol/sync_protocol_error.h" |
@@ -65,12 +66,15 @@ struct SyncCredentials { |
std::string sync_token; |
}; |
-// SyncManager encapsulates syncable::DirectoryManager and serves as the parent |
-// of all other objects in the sync API. SyncManager is thread-safe. If |
-// multiple threads interact with the same local sync repository (i.e. the |
-// same sqlite database), they should share a single SyncManager instance. The |
-// caller should typically create one SyncManager for the lifetime of a user |
-// session. |
+// SyncManager encapsulates syncable::DirectoryManager and serves as |
+// the parent of all other objects in the sync API. If multiple |
+// threads interact with the same local sync repository (i.e. the same |
+// sqlite database), they should share a single SyncManager instance. |
+// The caller should typically create one SyncManager for the lifetime |
+// of a user session. |
+// |
+// Unless stated otherwise, all methods of SyncManager should be |
+// called on the same thread. |
class SyncManager { |
public: |
// SyncInternal contains the implementation of SyncManager, while abstracting |
@@ -163,17 +167,12 @@ class SyncManager { |
bool crypto_has_pending_keys; |
}; |
- // An interface the embedding application implements to receive notifications |
- // from the SyncManager. Register an observer via SyncManager::AddObserver. |
- // This observer is an event driven model as the events may be raised from |
- // different internal threads, and simply providing an "OnStatusChanged" type |
- // notification complicates things such as trying to determine "what changed", |
- // if different members of the Status object are modified from different |
- // threads. This way, the event is explicit, and it is safe for the Observer |
- // to dispatch to a native thread or synchronize accordingly. |
- class Observer { |
+ // An interface the embedding application implements to be notified |
+ // on change events. Note that these methods may be called on *any* |
+ // thread. |
+ class ChangeDelegate { |
public: |
- // Notify the observer that changes have been applied to the sync model. |
+ // Notify the delegate that changes have been applied to the sync model. |
// |
// This will be invoked on the same thread as on which ApplyChanges was |
// called. |changes| is an array of size |change_count|, and contains the |
@@ -216,6 +215,46 @@ class SyncManager { |
// I/O to when it no longer holds any lock). |
virtual void OnChangesComplete(syncable::ModelType model_type) = 0; |
+ protected: |
+ virtual ~ChangeDelegate(); |
+ }; |
+ |
+ // Like ChangeDelegate, except called only on the sync thread and |
+ // not while a transaction is held. For objects that want to know |
+ // when changes happen, but don't need to process them. |
+ class ChangeObserver { |
+ public: |
+ // Ids referred to in |changes| may or may not be in |mutations|. |
+ // If they're not, that means that the node didn't actually |
+ // change, but we marked them as changed for some other reason |
+ // (e.g., siblings of re-ordered nodes). |
+ // |
+ // TODO(sync, long-term): Ideally, ChangeDelegate would also be |
+ // passed |mutations| instead of a transaction that would have to |
+ // be used to look up the changed nodes. That is, |
+ // ChangeDelegate::OnChangesApplied() would still be called under |
+ // the transaction, but all the needed data will be passed down. |
+ // |
+ // Even more ideally, we would have sync semantics such that we'd |
+ // be able to apply changes without being under a transaction. |
+ // But that's a ways off... |
+ virtual void OnChangesApplied( |
+ syncable::ModelType model_type, |
+ const syncable::ImmutableEntryKernelMutationMap& mutations, |
tim (not reviewing)
2011/09/20 16:04:59
We shouldn't add new deps on syncable:: stuff here
akalin
2011/09/20 21:14:42
Introduced the notion of a write transaction ID, a
|
+ const ImmutableChangeRecordList& changes) = 0; |
+ |
+ virtual void OnChangesComplete(syncable::ModelType model_type) = 0; |
+ |
+ protected: |
+ virtual ~ChangeObserver(); |
+ }; |
+ |
+ // An interface the embedding application implements to receive |
+ // notifications from the SyncManager. Register an observer via |
+ // SyncManager::AddObserver. All methods are called only on the |
+ // sync thread. |
+ class Observer { |
+ public: |
// A round-trip sync-cycle took place and the syncer has resolved any |
// conflicts that may have arisen. |
virtual void OnSyncCycleCompleted( |
@@ -340,8 +379,7 @@ class SyncManager { |
const syncable::ModelTypeSet& encrypted_types) = 0; |
virtual void OnActionableError( |
- const browser_sync::SyncProtocolError& sync_protocol_error) |
- = 0; |
+ const browser_sync::SyncProtocolError& sync_protocol_error) = 0; |
protected: |
virtual ~Observer(); |
@@ -376,6 +414,7 @@ class SyncManager { |
bool use_ssl, |
HttpPostProviderFactory* post_factory, |
browser_sync::ModelSafeWorkerRegistrar* registrar, |
+ ChangeDelegate* change_delegate, |
const std::string& user_agent, |
const SyncCredentials& credentials, |
sync_notifier::SyncNotifier* sync_notifier, |
@@ -383,13 +422,14 @@ class SyncManager { |
bool setup_for_test_mode); |
// Returns the username last used for a successful authentication. |
- // Returns empty if there is no such username. |
+ // Returns empty if there is no such username. May be called on any |
+ // thread. |
const std::string& GetAuthenticatedUsername(); |
// Check if the database has been populated with a full "initial" download of |
// sync items for each data type currently present in the routing info. |
// Prerequisite for calling this is that OnInitializationComplete has been |
- // called. |
+ // called. May be called from any thread. |
bool InitialSyncEndedForAllEnabledTypes(); |
// Update tokens that we're using in Sync. Email must stay the same. |
@@ -434,6 +474,10 @@ class SyncManager { |
// Request a clearing of all data on the server |
void RequestClearServerData(); |
+ // Add/remove change observers. |
+ void AddChangeObserver(ChangeObserver* observer); |
+ void RemoveChangeObserver(ChangeObserver* observer); |
+ |
// Adds a listener to be notified of sync events. |
// NOTE: It is OK (in fact, it's probably a good idea) to call this before |
// having received OnInitializationCompleted. |
@@ -446,26 +490,26 @@ class SyncManager { |
// Status-related getters. Typically GetStatusSummary will suffice, but |
// GetDetailedSyncStatus can be useful for gathering debug-level details of |
- // the internals of the sync engine. |
+ // the internals of the sync engine. May be called on any thread. |
Status::Summary GetStatusSummary() const; |
Status GetDetailedStatus() const; |
// Whether or not the Nigori node is encrypted using an explicit passphrase. |
+ // May be called on any thread. |
bool IsUsingExplicitPassphrase(); |
- // Get the internal implementation for use by BaseTransaction, etc. |
- SyncInternal* GetImpl() const; |
- |
// Call periodically from a database-safe thread to persist recent changes |
// to the syncapi model. |
void SaveChanges(); |
+ // Requests the syncer to stop as soon as possible. May be called |
+ // from any thread. |
void RequestEarlyExit(); |
// Issue a final SaveChanges, close sqlite handles, and stop running threads. |
- // Must be called from the same thread that called Init(). |
void Shutdown(); |
+ // May be called from any thread. |
UserShare* GetUserShare() const; |
// Inform the cryptographer of the most recent passphrase and set of encrypted |
@@ -479,25 +523,23 @@ class SyncManager { |
// without clearing the server data. |
void EnableEncryptEverything(); |
- // Returns true if we are currently encrypting all sync data. |
+ // Returns true if we are currently encrypting all sync data. May |
+ // be called on any thread. |
bool EncryptEverythingEnabled() const; |
// Gets the set of encrypted types from the cryptographer |
- // Note: opens a transaction. |
+ // Note: opens a transaction. May be called from any thread. |
syncable::ModelTypeSet GetEncryptedDataTypes() const; |
// Reads the nigori node to determine if any experimental types should be |
// enabled. |
- // Note: opens a transaction. |
+ // Note: opens a transaction. May be called on any thread. |
bool ReceivedExperimentalTypes(syncable::ModelTypeSet* to_add) const; |
// Uses a read-only transaction to determine if the directory being synced has |
- // any remaining unsynced items. |
+ // any remaining unsynced items. May be called on any thread. |
bool HasUnsyncedItems() const; |
- // Logs the list of unsynced meta handles. |
- void LogUnsyncedItems(int level) const; |
- |
// Functions used for testing. |
void TriggerOnNotificationStateChangeForTest( |
@@ -507,6 +549,8 @@ class SyncManager { |
const syncable::ModelTypeBitSet& model_types); |
private: |
+ base::ThreadChecker thread_checker_; |
+ |
// An opaque pointer to the nested private class. |
SyncInternal* data_; |