1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_
6#define CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_
7#pragma once
8
9#include <string>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "chrome/browser/sync/profile_sync_service.h"
14#include "chrome/browser/sync/profile_sync_service_observer.h"
15#include "chrome/browser/sync/syncable/model_type.h"
16
17class Profile;
18
19namespace browser_sync {
20  namespace sessions {
21    struct SyncSessionSnapshot;
22  }
23}
24
25// An instance of this class is basically our notion of a "sync client" for
26// automation purposes. It harnesses the ProfileSyncService member of the
27// profile passed to it on construction and automates certain things like setup
28// and authentication. It provides ways to "wait" adequate periods of time for
29// several clients to get to the same state.
30class ProfileSyncServiceHarness : public ProfileSyncServiceObserver {
31 public:
32  ProfileSyncServiceHarness(Profile* profile,
33                            const std::string& username,
34                            const std::string& password,
35                            int id);
36
37  virtual ~ProfileSyncServiceHarness() {}
38
39  // Creates a ProfileSyncServiceHarness object and attaches it to |profile|, a
40  // profile that is assumed to have been signed into sync in the past. Caller
41  // takes ownership.
42  static ProfileSyncServiceHarness* CreateAndAttach(Profile* profile);
43
44  // Sets the GAIA credentials with which to sign in to sync.
45  void SetCredentials(const std::string& username, const std::string& password);
46
47  // Returns true if sync has been enabled on |profile_|.
48  bool IsSyncAlreadySetup();
49
50  // Creates a ProfileSyncService for the profile passed at construction and
51  // enables sync for all available datatypes. Returns true only after sync has
52  // been fully initialized and authenticated, and we are ready to process
53  // changes.
54  bool SetupSync();
55
56  // Same as the above method, but enables sync only for the datatypes contained
57  // in |synced_datatypes|.
58  bool SetupSync(const syncable::ModelTypeSet& synced_datatypes);
59
60  // ProfileSyncServiceObserver implementation.
61  virtual void OnStateChanged();
62
63  // Blocks the caller until this harness has completed a single sync cycle
64  // since the previous one.  Returns true if a sync cycle has completed.
65  bool AwaitSyncCycleCompletion(const std::string& reason);
66
67  // Blocks the caller until this harness has observed that the sync engine
68  // has downloaded all the changes seen by the |partner| harness's client.
69  bool WaitUntilTimestampMatches(
70      ProfileSyncServiceHarness* partner, const std::string& reason);
71
72  // Calling this acts as a barrier and blocks the caller until |this| and
73  // |partner| have both completed a sync cycle.  When calling this method,
74  // the |partner| should be the passive responder who responds to the actions
75  // of |this|.  This method relies upon the synchronization of callbacks
76  // from the message queue. Returns true if two sync cycles have completed.
77  // Note: Use this method when exactly one client makes local change(s), and
78  // exactly one client is waiting to receive those changes.
79  bool AwaitMutualSyncCycleCompletion(ProfileSyncServiceHarness* partner);
80
81  // Blocks the caller until |this| completes its ongoing sync cycle and every
82  // other client in |partners| have achieved identical download progresses.
83  // Note: Use this method when exactly one client makes local change(s),
84  // and more than one client is waiting to receive those changes.
85  bool AwaitGroupSyncCycleCompletion(
86      std::vector<ProfileSyncServiceHarness*>& partners);
87
88  // Blocks the caller until every client in |clients| completes its ongoing
89  // sync cycle and all the clients' timestamps match.  Note: Use this method
90  // when more than one client makes local change(s), and more than one client
91  // is waiting to receive those changes.
92  static bool AwaitQuiescence(
93      std::vector<ProfileSyncServiceHarness*>& clients);
94
95  // If a SetPassphrase call has been issued with a valid passphrase, this
96  // will wait until the passphrase has been accepted.
97  bool AwaitPassphraseAccepted();
98
99  // Returns the ProfileSyncService member of the the sync client.
100  ProfileSyncService* service() { return service_; }
101
102  // Returns the status of the ProfileSyncService member of the the sync client.
103  ProfileSyncService::Status GetStatus();
104
105  // See ProfileSyncService::ShouldPushChanges().
106  bool ServiceIsPushingChanges() { return service_->ShouldPushChanges(); }
107
108  // Enables sync for a particular sync datatype.
109  void EnableSyncForDatatype(syncable::ModelType datatype);
110
111  // Disables sync for a particular sync datatype.
112  void DisableSyncForDatatype(syncable::ModelType datatype);
113
114  // Enables sync for all sync datatypes.
115  void EnableSyncForAllDatatypes();
116
117  // Disables sync for all sync datatypes.
118  void DisableSyncForAllDatatypes();
119
120  // Returns a snapshot of the current sync session.
121  const browser_sync::sessions::SyncSessionSnapshot*
122      GetLastSessionSnapshot() const;
123
124  // Encrypt the datatype |type|. This method will block while the sync backend
125  // host performs the encryption or a timeout is reached. Returns false if
126  // encryption failed, else true.
127  // Note: this method does not currently support tracking encryption status
128  // while other sync activities are being performed. Sync should be fully
129  // synced when this is called.
130  bool EnableEncryptionForType(syncable::ModelType type);
131
132  // Check if |type| is encrypted.
133  bool IsTypeEncrypted(syncable::ModelType type);
134
135 private:
136  friend class StateChangeTimeoutEvent;
137
138  enum WaitState {
139    // The sync client has just been initialized.
140    INITIAL_WAIT_STATE = 0,
141
142    // The sync client awaits the OnBackendInitialized() callback.
143    WAITING_FOR_ON_BACKEND_INITIALIZED,
144
145    // The sync client is waiting for the first sync cycle to complete.
146    WAITING_FOR_INITIAL_SYNC,
147
148    // The sync client is waiting for an ongoing sync cycle to complete.
149    WAITING_FOR_SYNC_TO_FINISH,
150
151    // The sync client anticipates incoming updates leading to a new sync cycle.
152    WAITING_FOR_UPDATES,
153
154    // The sync client is waiting for its passphrase to be accepted by the
155    // cryptographer.
156    WAITING_FOR_PASSPHRASE_ACCEPTED,
157
158    // The sync client anticipates encryption of new datatypes.
159    WAITING_FOR_ENCRYPTION,
160
161    // The sync client cannot reach the server.
162    SERVER_UNREACHABLE,
163
164    // The sync client is fully synced and there are no pending updates.
165    FULLY_SYNCED,
166
167    // Syncing is disabled for the client.
168    SYNC_DISABLED,
169
170    NUMBER_OF_STATES,
171  };
172
173  // Called from the observer when the current wait state has been completed.
174  void SignalStateCompleteWithNextState(WaitState next_state);
175
176  // Indicates that the operation being waited on is complete.
177  void SignalStateComplete();
178
179  // Finite state machine for controlling state.  Returns true only if a state
180  // change has taken place.
181  bool RunStateChangeMachine();
182
183  // Returns true if a status change took place, false on timeout.
184  bool AwaitStatusChangeWithTimeout(int timeout_milliseconds,
185                                    const std::string& reason);
186
187  // Returns true if the sync client has no unsynced items.
188  bool IsSynced();
189
190  // Returns true if this client has downloaded all the items that the
191  // other client has.
192  bool MatchesOtherClient(ProfileSyncServiceHarness* partner);
193
194  // Logs message with relevant info about client's sync state (if available).
195  void LogClientInfo(const std::string& message);
196
197  // Gets the current progress indicator of the current sync session
198  // for a particular datatype.
199  std::string GetUpdatedTimestamp(syncable::ModelType model_type);
200
201  // When in WAITING_FOR_ENCRYPTION state, we check to see if this type is now
202  // encrypted to determine if we're done.
203  syncable::ModelType waiting_for_encryption_type_;
204
205  WaitState wait_state_;
206
207  Profile* profile_;
208  ProfileSyncService* service_;
209
210  // The harness of the client whose update progress marker we're expecting
211  // eventually match.
212  ProfileSyncServiceHarness* timestamp_match_partner_;
213
214  // Credentials used for GAIA authentication.
215  std::string username_;
216  std::string password_;
217
218  // Client ID, used for logging purposes.
219  int id_;
220
221  DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceHarness);
222};
223
224#endif  // CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_
225