| // 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_PROFILE_SYNC_SERVICE_HARNESS_H_ |
| #define CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_ |
| #pragma once |
| |
| #include <string> |
| #include <vector> |
| |
| #include "base/basictypes.h" |
| #include "base/compiler_specific.h" |
| #include "chrome/browser/sync/backend_migrator.h" |
| #include "chrome/browser/sync/profile_sync_service.h" |
| #include "chrome/browser/sync/profile_sync_service_observer.h" |
| #include "chrome/browser/sync/retry_verifier.h" |
| #include "chrome/browser/sync/syncable/model_type.h" |
| |
| class Profile; |
| |
| namespace browser_sync { |
| namespace sessions { |
| struct SyncSessionSnapshot; |
| } |
| } |
| |
| // An instance of this class is basically our notion of a "sync client" for |
| // automation purposes. It harnesses the ProfileSyncService member of the |
| // profile passed to it on construction and automates certain things like setup |
| // and authentication. It provides ways to "wait" adequate periods of time for |
| // several clients to get to the same state. |
| class ProfileSyncServiceHarness |
| : public ProfileSyncServiceObserver, |
| public browser_sync::MigrationObserver { |
| public: |
| ProfileSyncServiceHarness(Profile* profile, |
| const std::string& username, |
| const std::string& password); |
| |
| virtual ~ProfileSyncServiceHarness(); |
| |
| // Creates a ProfileSyncServiceHarness object and attaches it to |profile|, a |
| // profile that is assumed to have been signed into sync in the past. Caller |
| // takes ownership. |
| static ProfileSyncServiceHarness* CreateAndAttach(Profile* profile); |
| |
| // Sets the GAIA credentials with which to sign in to sync. |
| void SetCredentials(const std::string& username, const std::string& password); |
| |
| // Returns true if sync has been enabled on |profile_|. |
| bool IsSyncAlreadySetup(); |
| |
| // Creates a ProfileSyncService for the profile passed at construction and |
| // enables sync for all available datatypes. Returns true only after sync has |
| // been fully initialized and authenticated, and we are ready to process |
| // changes. |
| bool SetupSync(); |
| |
| // Same as the above method, but enables sync only for the datatypes contained |
| // in |synced_datatypes|. |
| bool SetupSync(const syncable::ModelTypeSet& synced_datatypes); |
| |
| // ProfileSyncServiceObserver implementation. |
| virtual void OnStateChanged() OVERRIDE; |
| |
| // MigrationObserver implementation. |
| virtual void OnMigrationStateChange() OVERRIDE; |
| |
| // Blocks the caller until the sync backend host associated with this harness |
| // has been initialized. Returns true if the wait was successful. |
| bool AwaitBackendInitialized(); |
| |
| // Blocks the caller until the datatype manager is configured and sync has |
| // been initialized (for example, after a browser restart). Returns true if |
| // the wait was successful. |
| bool AwaitSyncRestart(); |
| |
| // Blocks the caller until this harness has completed a single sync cycle |
| // since the previous one. Returns true if a sync cycle has completed. |
| bool AwaitDataSyncCompletion(const std::string& reason); |
| |
| // Blocks the caller until this harness has completed as many sync cycles as |
| // are required to ensure its progress marker matches the latest available on |
| // the server. |
| // |
| // Note: When other clients are committing changes this will not be reliable. |
| // If your test involves changes to multiple clients, you should use one of |
| // the other Await* functions, such as AwaitMutualSyncCycleComplete. Refer to |
| // the documentation of those functions for more details. |
| bool AwaitFullSyncCompletion(const std::string& reason); |
| |
| // Blocks the caller until sync has been disabled for this client. Returns |
| // true if sync is disabled. |
| bool AwaitSyncDisabled(const std::string& reason); |
| |
| // Blocks the caller until exponential backoff has been verified to happen. |
| bool AwaitExponentialBackoffVerification(); |
| |
| // Blocks the caller until the syncer receives an actionable error. |
| // Returns true if the sync client received an actionable error. |
| bool AwaitActionableError(); |
| |
| // Blocks until the given set of data types are migrated. |
| bool AwaitMigration(const syncable::ModelTypeSet& expected_migrated_types); |
| |
| // Blocks the caller until this harness has observed that the sync engine |
| // has downloaded all the changes seen by the |partner| harness's client. |
| bool WaitUntilTimestampMatches( |
| ProfileSyncServiceHarness* partner, const std::string& reason); |
| |
| // Calling this acts as a barrier and blocks the caller until |this| and |
| // |partner| have both completed a sync cycle. When calling this method, |
| // the |partner| should be the passive responder who responds to the actions |
| // of |this|. This method relies upon the synchronization of callbacks |
| // from the message queue. Returns true if two sync cycles have completed. |
| // Note: Use this method when exactly one client makes local change(s), and |
| // exactly one client is waiting to receive those changes. |
| bool AwaitMutualSyncCycleCompletion(ProfileSyncServiceHarness* partner); |
| |
| // Blocks the caller until |this| completes its ongoing sync cycle and every |
| // other client in |partners| have achieved identical download progresses. |
| // Note: Use this method when exactly one client makes local change(s), |
| // and more than one client is waiting to receive those changes. |
| bool AwaitGroupSyncCycleCompletion( |
| std::vector<ProfileSyncServiceHarness*>& partners); |
| |
| // Blocks the caller until every client in |clients| completes its ongoing |
| // sync cycle and all the clients' timestamps match. Note: Use this method |
| // when more than one client makes local change(s), and more than one client |
| // is waiting to receive those changes. |
| static bool AwaitQuiescence( |
| std::vector<ProfileSyncServiceHarness*>& clients); |
| |
| // Blocks the caller until |service_| indicates that a passphrase is required. |
| bool AwaitPassphraseRequired(); |
| |
| // Blocks the caller until |service_| indicates that the passphrase set by |
| // calling SetPassphrase has been accepted. |
| bool AwaitPassphraseAccepted(); |
| |
| // Returns the ProfileSyncService member of the sync client. |
| ProfileSyncService* service() { return service_; } |
| |
| // Returns the status of the ProfileSyncService member of the sync client. |
| ProfileSyncService::Status GetStatus(); |
| |
| // See ProfileSyncService::ShouldPushChanges(). |
| bool ServiceIsPushingChanges() { return service_->ShouldPushChanges(); } |
| |
| // Enables sync for a particular sync datatype. Returns true on success. |
| bool EnableSyncForDatatype(syncable::ModelType datatype); |
| |
| // Disables sync for a particular sync datatype. Returns true on success. |
| bool DisableSyncForDatatype(syncable::ModelType datatype); |
| |
| // Enables sync for all sync datatypes. Returns true on success. |
| bool EnableSyncForAllDatatypes(); |
| |
| // Disables sync for all sync datatypes. Returns true on success. |
| bool DisableSyncForAllDatatypes(); |
| |
| // Returns a snapshot of the current sync session. |
| const browser_sync::sessions::SyncSessionSnapshot* |
| GetLastSessionSnapshot() const; |
| |
| // Encrypt the datatype |type|. This method will block while the sync backend |
| // host performs the encryption or a timeout is reached. |
| // PostCondition: |
| // returns: True if |type| was encrypted and we are fully synced. |
| // False if we timed out. |
| bool EnableEncryptionForType(syncable::ModelType type); |
| |
| // Wait until |type| is encrypted or we time out. |
| // PostCondition: |
| // returns: True if |type| is currently encrypted and we are fully synced. |
| // False if we timed out. |
| bool WaitForTypeEncryption(syncable::ModelType type); |
| |
| // Check if |type| is encrypted. |
| bool IsTypeEncrypted(syncable::ModelType type); |
| |
| // Check if |type| is registered and the controller is running. |
| bool IsTypeRunning(syncable::ModelType type); |
| |
| // Check if |type| is being synced. |
| bool IsTypePreferred(syncable::ModelType type); |
| |
| private: |
| friend class StateChangeTimeoutEvent; |
| |
| enum WaitState { |
| // The sync client has just been initialized. |
| INITIAL_WAIT_STATE = 0, |
| |
| // The sync client awaits the OnBackendInitialized() callback. |
| WAITING_FOR_ON_BACKEND_INITIALIZED, |
| |
| // The sync client is waiting for the first sync cycle to complete. |
| WAITING_FOR_INITIAL_SYNC, |
| |
| // The sync client is waiting for data to be synced. |
| WAITING_FOR_DATA_SYNC, |
| |
| // The sync client is waiting for data and progress markers to be synced. |
| WAITING_FOR_FULL_SYNC, |
| |
| // The sync client anticipates incoming updates leading to a new sync cycle. |
| WAITING_FOR_UPDATES, |
| |
| // The sync client is waiting for a passphrase to be required by the |
| // cryptographer. |
| WAITING_FOR_PASSPHRASE_REQUIRED, |
| |
| // The sync client is waiting for its passphrase to be accepted by the |
| // cryptographer. |
| WAITING_FOR_PASSPHRASE_ACCEPTED, |
| |
| // The sync client anticipates encryption of new datatypes. |
| WAITING_FOR_ENCRYPTION, |
| |
| // The sync client is waiting for the datatype manager to be configured and |
| // for sync to be fully initialized. Used after a browser restart, where a |
| // full sync cycle is not expected to occur. |
| WAITING_FOR_SYNC_CONFIGURATION, |
| |
| // The sync client is waiting for sync to be disabled for this client. |
| WAITING_FOR_SYNC_DISABLED, |
| |
| // The sync client is in the exponential backoff mode. Verify that |
| // backoffs are triggered correctly. |
| WAITING_FOR_EXPONENTIAL_BACKOFF_VERIFICATION, |
| |
| // The sync client is waiting for migration to start. |
| WAITING_FOR_MIGRATION_TO_START, |
| |
| // The sync client is waiting for migration to finish. |
| WAITING_FOR_MIGRATION_TO_FINISH, |
| |
| // The sync client is waiting for an actionable error from the server. |
| WAITING_FOR_ACTIONABLE_ERROR, |
| |
| // The client verification is complete. We don't care about the state of |
| // the syncer any more. |
| WAITING_FOR_NOTHING, |
| |
| // The sync client needs a passphrase in order to decrypt data. |
| SET_PASSPHRASE_FAILED, |
| |
| // The sync client cannot reach the server. |
| SERVER_UNREACHABLE, |
| |
| // The sync client is fully synced and there are no pending updates. |
| FULLY_SYNCED, |
| |
| // Syncing is disabled for the client. |
| SYNC_DISABLED, |
| |
| NUMBER_OF_STATES, |
| }; |
| |
| // Listen to migration events if the migrator has been initialized |
| // and we're not already listening. Returns true if we started |
| // listening. |
| bool TryListeningToMigrationEvents(); |
| |
| // Called from the observer when the current wait state has been completed. |
| void SignalStateCompleteWithNextState(WaitState next_state); |
| |
| // Indicates that the operation being waited on is complete. |
| void SignalStateComplete(); |
| |
| // Finite state machine for controlling state. Returns true only if a state |
| // change has taken place. |
| bool RunStateChangeMachine(); |
| |
| // Returns true if a status change took place, false on timeout. |
| bool AwaitStatusChangeWithTimeout(int timeout_milliseconds, |
| const std::string& reason); |
| |
| // A helper for implementing IsDataSynced() and IsFullySynced(). |
| bool IsDataSyncedImpl(const browser_sync::sessions::SyncSessionSnapshot*); |
| |
| // Returns true if the sync client has no unsynced items. |
| bool IsDataSynced(); |
| |
| // Returns true if the sync client has no unsynced items and its progress |
| // markers are believed to be up to date. |
| // |
| // Although we can't detect when commits from other clients invalidate our |
| // local progress markers, we do know when our own commits have invalidated |
| // our timestmaps. This check returns true when this client has, to the best |
| // of its knowledge, downloaded the latest progress markers. |
| bool IsFullySynced(); |
| |
| // Returns true if there is a backend migration in progress. |
| bool HasPendingBackendMigration(); |
| |
| // Returns true if this client has downloaded all the items that the |
| // other client has. |
| bool MatchesOtherClient(ProfileSyncServiceHarness* partner); |
| |
| // Returns a string with relevant info about client's sync state (if |
| // available), annotated with |message|. Useful for logging. |
| std::string GetClientInfoString(const std::string& message); |
| |
| // Gets the current progress indicator of the current sync session |
| // for a particular datatype. |
| std::string GetUpdatedTimestamp(syncable::ModelType model_type); |
| |
| // Gets detailed status from |service_| in pretty-printable form. |
| std::string GetServiceStatus(); |
| |
| // When in WAITING_FOR_ENCRYPTION state, we check to see if this type is now |
| // encrypted to determine if we're done. |
| syncable::ModelType waiting_for_encryption_type_; |
| |
| // The WaitState in which the sync client currently is. Helps determine what |
| // action to take when RunStateChangeMachine() is called. |
| WaitState wait_state_; |
| |
| // Sync profile associated with this sync client. |
| Profile* profile_; |
| |
| // ProfileSyncService object associated with |profile_|. |
| ProfileSyncService* service_; |
| |
| // The harness of the client whose update progress marker we're expecting |
| // eventually match. |
| ProfileSyncServiceHarness* timestamp_match_partner_; |
| |
| // Credentials used for GAIA authentication. |
| std::string username_; |
| std::string password_; |
| |
| // The current set of data types pending migration. Used by |
| // AwaitMigration(). |
| syncable::ModelTypeSet pending_migration_types_; |
| |
| // The set of data types that have undergone migration. Used by |
| // AwaitMigration(). |
| syncable::ModelTypeSet migrated_types_; |
| |
| // Used for logging. |
| const std::string profile_debug_name_; |
| |
| // Keeps track of the number of attempts at exponential backoff and its |
| // related bookkeeping information for verification. |
| browser_sync::RetryVerifier retry_verifier_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceHarness); |
| }; |
| |
| #endif // CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_ |