// 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 "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_observer.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:
ProfileSyncServiceHarness(Profile* profile,
const std::string& username,
const std::string& password,
int id);
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();
// 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 AwaitSyncCycleCompletion(const std::string& reason);
// 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);
// If a SetPassphrase call has been issued with a valid passphrase, this
// will wait until the passphrase has been accepted.
bool AwaitPassphraseAccepted();
// Returns the ProfileSyncService member of the the sync client.
ProfileSyncService* service() { return service_; }
// Returns the status of the ProfileSyncService member of the the sync client.
ProfileSyncService::Status GetStatus();
// See ProfileSyncService::ShouldPushChanges().
bool ServiceIsPushingChanges() { return service_->ShouldPushChanges(); }
// Enables sync for a particular sync datatype.
void EnableSyncForDatatype(syncable::ModelType datatype);
// Disables sync for a particular sync datatype.
void DisableSyncForDatatype(syncable::ModelType datatype);
// Enables sync for all sync datatypes.
void EnableSyncForAllDatatypes();
// Disables sync for all sync datatypes.
void 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. Returns false if
// encryption failed, else true.
// Note: this method does not currently support tracking encryption status
// while other sync activities are being performed. Sync should be fully
// synced when this is called.
bool EnableEncryptionForType(syncable::ModelType type);
// Check if |type| is encrypted.
bool IsTypeEncrypted(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 an ongoing sync cycle to complete.
WAITING_FOR_SYNC_TO_FINISH,
// The sync client anticipates incoming updates leading to a new sync cycle.
WAITING_FOR_UPDATES,
// 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 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,
};
// 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);
// Returns true if the sync client has no unsynced items.
bool IsSynced();
// Returns true if this client has downloaded all the items that the
// other client has.
bool MatchesOtherClient(ProfileSyncServiceHarness* partner);
// Logs message with relevant info about client's sync state (if available).
void LogClientInfo(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);
// 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_;
WaitState wait_state_;
Profile* 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_;
// Client ID, used for logging purposes.
int id_;
DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceHarness);
};
#endif // CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_