1// Copyright (c) 2012 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
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/compiler_specific.h"
13#include "chrome/browser/sync/backend_migrator.h"
14#include "chrome/browser/sync/profile_sync_service.h"
15#include "chrome/browser/sync/profile_sync_service_observer.h"
16#include "chrome/browser/sync/retry_verifier.h"
17#include "sync/internal_api/public/base/model_type.h"
18
19class Profile;
20
21namespace invalidation {
22class P2PInvalidationService;
23}
24
25namespace browser_sync {
26namespace sessions {
27class SyncSessionSnapshot;
28}
29}
30
31// An instance of this class is basically our notion of a "sync client" for
32// automation purposes. It harnesses the ProfileSyncService member of the
33// profile passed to it on construction and automates certain things like setup
34// and authentication. It provides ways to "wait" adequate periods of time for
35// several clients to get to the same state.
36class ProfileSyncServiceHarness
37    : public ProfileSyncServiceObserver,
38      public browser_sync::MigrationObserver {
39 public:
40  static ProfileSyncServiceHarness* Create(
41      Profile* profile,
42      const std::string& username,
43      const std::string& password);
44
45  static ProfileSyncServiceHarness* CreateForIntegrationTest(
46      Profile* profile,
47      const std::string& username,
48      const std::string& password,
49      invalidation::P2PInvalidationService* invalidation_service);
50
51  virtual ~ProfileSyncServiceHarness();
52
53  // Sets the GAIA credentials with which to sign in to sync.
54  void SetCredentials(const std::string& username, const std::string& password);
55
56  // Returns true if sync has been enabled on |profile_|.
57  bool IsSyncAlreadySetup();
58
59  // Creates a ProfileSyncService for the profile passed at construction and
60  // enables sync for all available datatypes. Returns true only after sync has
61  // been fully initialized and authenticated, and we are ready to process
62  // changes.
63  bool SetupSync();
64
65  // Same as the above method, but enables sync only for the datatypes contained
66  // in |synced_datatypes|.
67  bool SetupSync(syncer::ModelTypeSet synced_datatypes);
68
69  // ProfileSyncServiceObserver implementation.
70  virtual void OnStateChanged() OVERRIDE;
71  virtual void OnSyncCycleCompleted() OVERRIDE;
72
73  // MigrationObserver implementation.
74  virtual void OnMigrationStateChange() OVERRIDE;
75
76  // Blocks the caller until the sync backend host associated with this harness
77  // has been initialized.  Returns true if the wait was successful.
78  bool AwaitBackendInitialized();
79
80  // Blocks the caller until this harness has completed a single sync cycle
81  // since the previous one.  Returns true if a sync cycle has completed.
82  bool AwaitDataSyncCompletion(const std::string& reason);
83
84  // Blocks the caller until this harness has completed as many sync cycles as
85  // are required to ensure its progress marker matches the latest available on
86  // the server.
87  //
88  // Note: When other clients are committing changes this will not be reliable.
89  // If your test involves changes to multiple clients, you should use one of
90  // the other Await* functions, such as AwaitMutualSyncCycleComplete.  Refer to
91  // the documentation of those functions for more details.
92  bool AwaitFullSyncCompletion(const std::string& reason);
93
94  // Blocks the caller until sync has been disabled for this client. Returns
95  // true if sync is disabled.
96  bool AwaitSyncDisabled(const std::string& reason);
97
98  // Blocks the caller until exponential backoff has been verified to happen.
99  bool AwaitExponentialBackoffVerification();
100
101  // Blocks the caller until the syncer receives an actionable error.
102  // Returns true if the sync client received an actionable error.
103  bool AwaitActionableError();
104
105  // Blocks until the given set of data types are migrated.
106  bool AwaitMigration(syncer::ModelTypeSet expected_migrated_types);
107
108  // Blocks the caller until this harness has observed that the sync engine
109  // has downloaded all the changes seen by the |partner| harness's client.
110  bool WaitUntilProgressMarkersMatch(
111      ProfileSyncServiceHarness* partner, const std::string& reason);
112
113  // Calling this acts as a barrier and blocks the caller until |this| and
114  // |partner| have both completed a sync cycle.  When calling this method,
115  // the |partner| should be the passive responder who responds to the actions
116  // of |this|.  This method relies upon the synchronization of callbacks
117  // from the message queue. Returns true if two sync cycles have completed.
118  // Note: Use this method when exactly one client makes local change(s), and
119  // exactly one client is waiting to receive those changes.
120  bool AwaitMutualSyncCycleCompletion(ProfileSyncServiceHarness* partner);
121
122  // Blocks the caller until |this| completes its ongoing sync cycle and every
123  // other client in |partners| have achieved identical download progresses.
124  // Note: Use this method when exactly one client makes local change(s),
125  // and more than one client is waiting to receive those changes.
126  bool AwaitGroupSyncCycleCompletion(
127      std::vector<ProfileSyncServiceHarness*>& partners);
128
129  // Blocks the caller until every client in |clients| completes its ongoing
130  // sync cycle and all the clients' progress markers match.  Note: Use this
131  // method when more than one client makes local change(s), and more than one
132  // client is waiting to receive those changes.
133  static bool AwaitQuiescence(
134      std::vector<ProfileSyncServiceHarness*>& clients);
135
136  // Blocks the caller until |service_| indicates that a passphrase is required.
137  bool AwaitPassphraseRequired();
138
139  // Blocks the caller until |service_| indicates that the passphrase set by
140  // calling SetDecryptionPassphrase has been accepted.
141  bool AwaitPassphraseAccepted();
142
143  // Returns the ProfileSyncService member of the sync client.
144  ProfileSyncService* service() { return service_; }
145
146  // Returns the status of the ProfileSyncService member of the sync client.
147  ProfileSyncService::Status GetStatus();
148
149  // See ProfileSyncService::ShouldPushChanges().
150  bool ServiceIsPushingChanges() { return service_->ShouldPushChanges(); }
151
152  // Enables sync for a particular sync datatype. Returns true on success.
153  bool EnableSyncForDatatype(syncer::ModelType datatype);
154
155  // Disables sync for a particular sync datatype. Returns true on success.
156  bool DisableSyncForDatatype(syncer::ModelType datatype);
157
158  // Enables sync for all sync datatypes. Returns true on success.
159  bool EnableSyncForAllDatatypes();
160
161  // Disables sync for all sync datatypes. Returns true on success.
162  bool DisableSyncForAllDatatypes();
163
164  // Returns a snapshot of the current sync session.
165  syncer::sessions::SyncSessionSnapshot GetLastSessionSnapshot() const;
166
167  // Encrypt the datatype |type|. This method will block while the sync backend
168  // host performs the encryption or a timeout is reached.
169  // PostCondition:
170  //   returns: True if |type| was encrypted and we are fully synced.
171  //            False if we timed out.
172  bool EnableEncryptionForType(syncer::ModelType type);
173
174  // Wait until |type| is encrypted or we time out.
175  // PostCondition:
176  //   returns: True if |type| is currently encrypted and we are fully synced.
177  //            False if we timed out.
178  bool WaitForTypeEncryption(syncer::ModelType type);
179
180  // Check if |type| is encrypted.
181  bool IsTypeEncrypted(syncer::ModelType type);
182
183  // Check if |type| is registered and the controller is running.
184  bool IsTypeRunning(syncer::ModelType type);
185
186  // Check if |type| is being synced.
187  bool IsTypePreferred(syncer::ModelType type);
188
189  // Get the number of sync entries this client has. This includes all top
190  // level or permanent items, and can include recently deleted entries.
191  size_t GetNumEntries() const;
192
193  // Get the number of sync datatypes registered (ignoring whatever state
194  // they're in).
195  size_t GetNumDatatypes() const;
196
197  // Gets the |auto_start_enabled_| variable from the |service_|.
198  bool AutoStartEnabled();
199
200  // Returns true if a status change took place, false on timeout.
201  bool AwaitStatusChangeWithTimeout(int timeout_milliseconds,
202                                    const std::string& reason);
203
204 private:
205  friend class StateChangeTimeoutEvent;
206
207  enum WaitState {
208    // The sync client has just been initialized.
209    INITIAL_WAIT_STATE = 0,
210
211    // The sync client awaits the OnBackendInitialized() callback.
212    WAITING_FOR_ON_BACKEND_INITIALIZED,
213
214    // The sync client is waiting for the first sync cycle to complete.
215    WAITING_FOR_INITIAL_SYNC,
216
217    // The sync client is waiting for data to be synced.
218    WAITING_FOR_DATA_SYNC,
219
220    // The sync client is waiting for data and progress markers to be synced.
221    WAITING_FOR_FULL_SYNC,
222
223    // The sync client anticipates incoming updates leading to a new sync cycle.
224    WAITING_FOR_UPDATES,
225
226    // The sync client is waiting for a passphrase to be required by the
227    // cryptographer.
228    WAITING_FOR_PASSPHRASE_REQUIRED,
229
230    // The sync client is waiting for its passphrase to be accepted by the
231    // cryptographer.
232    WAITING_FOR_PASSPHRASE_ACCEPTED,
233
234    // The sync client anticipates encryption of new datatypes.
235    WAITING_FOR_ENCRYPTION,
236
237    // The sync client is waiting for the datatype manager to be configured and
238    // for sync to be fully initialized. Used after a browser restart, where a
239    // full sync cycle is not expected to occur.
240    WAITING_FOR_SYNC_CONFIGURATION,
241
242    // The sync client is waiting for sync to be disabled for this client.
243    WAITING_FOR_SYNC_DISABLED,
244
245    // The sync client is in the exponential backoff mode. Verify that
246    // backoffs are triggered correctly.
247    WAITING_FOR_EXPONENTIAL_BACKOFF_VERIFICATION,
248
249    // The sync client is waiting for migration to start.
250    WAITING_FOR_MIGRATION_TO_START,
251
252    // The sync client is waiting for migration to finish.
253    WAITING_FOR_MIGRATION_TO_FINISH,
254
255    // The sync client is waiting for an actionable error from the server.
256    WAITING_FOR_ACTIONABLE_ERROR,
257
258    // The client verification is complete. We don't care about the state of
259    // the syncer any more.
260    WAITING_FOR_NOTHING,
261
262    // The sync client needs a passphrase in order to decrypt data.
263    SET_PASSPHRASE_FAILED,
264
265    // The sync client's credentials were rejected.
266    CREDENTIALS_REJECTED,
267
268    // The sync client cannot reach the server.
269    SERVER_UNREACHABLE,
270
271    // The sync client is fully synced and there are no pending updates.
272    FULLY_SYNCED,
273
274    // Syncing is disabled for the client.
275    SYNC_DISABLED,
276
277    NUMBER_OF_STATES,
278  };
279
280  ProfileSyncServiceHarness(
281      Profile* profile,
282      const std::string& username,
283      const std::string& password,
284      invalidation::P2PInvalidationService* invalidation_service);
285
286  // Listen to migration events if the migrator has been initialized
287  // and we're not already listening.  Returns true if we started
288  // listening.
289  bool TryListeningToMigrationEvents();
290
291  // Called from the observer when the current wait state has been completed.
292  void SignalStateCompleteWithNextState(WaitState next_state);
293
294  // Indicates that the operation being waited on is complete.
295  void SignalStateComplete();
296
297  // Finite state machine for controlling state.  Returns true only if a state
298  // change has taken place.
299  bool RunStateChangeMachine();
300
301  // A helper for implementing IsDataSynced() and IsFullySynced().
302  bool IsDataSyncedImpl(
303      const syncer::sessions::SyncSessionSnapshot& snapshot);
304
305  // Returns true if the sync client has no unsynced items.
306  bool IsDataSynced();
307
308  // Returns true if the sync client has no unsynced items and its progress
309  // markers are believed to be up to date.
310  //
311  // Although we can't detect when commits from other clients invalidate our
312  // local progress markers, we do know when our own commits have invalidated
313  // our timestmaps.  This check returns true when this client has, to the best
314  // of its knowledge, downloaded the latest progress markers.
315  bool IsFullySynced();
316
317  // Returns true if there is a backend migration in progress.
318  bool HasPendingBackendMigration();
319
320  // Returns true if this client has downloaded all the items that the
321  // other client has.
322  bool MatchesOtherClient(ProfileSyncServiceHarness* partner);
323
324  // Returns a string with relevant info about client's sync state (if
325  // available), annotated with |message|. Useful for logging.
326  std::string GetClientInfoString(const std::string& message);
327
328  // Gets the current progress marker of the current sync session for a
329  // particular datatype. Returns an empty string if the progress marker isn't
330  // found.
331  std::string GetSerializedProgressMarker(syncer::ModelType model_type) const;
332
333  // Gets detailed status from |service_| in pretty-printable form.
334  std::string GetServiceStatus();
335
336  // When in WAITING_FOR_ENCRYPTION state, we check to see if this type is now
337  // encrypted to determine if we're done.
338  syncer::ModelType waiting_for_encryption_type_;
339
340  // The WaitState in which the sync client currently is. Helps determine what
341  // action to take when RunStateChangeMachine() is called.
342  WaitState wait_state_;
343
344  // Sync profile associated with this sync client.
345  Profile* profile_;
346
347  // ProfileSyncService object associated with |profile_|.
348  ProfileSyncService* service_;
349
350  // P2PInvalidationService associated with |profile_|.
351  invalidation::P2PInvalidationService* p2p_invalidation_service_;
352
353  // The harness of the client whose update progress marker we're expecting
354  // eventually match.
355  ProfileSyncServiceHarness* progress_marker_partner_;
356
357  // Credentials used for GAIA authentication.
358  std::string username_;
359  std::string password_;
360
361  // The current set of data types pending migration.  Used by
362  // AwaitMigration().
363  syncer::ModelTypeSet pending_migration_types_;
364
365  // The set of data types that have undergone migration.  Used by
366  // AwaitMigration().
367  syncer::ModelTypeSet migrated_types_;
368
369  // Used for logging.
370  const std::string profile_debug_name_;
371
372  // Keeps track of the number of attempts at exponential backoff and its
373  // related bookkeeping information for verification.
374  browser_sync::RetryVerifier retry_verifier_;
375
376  // Flag set to true when we're waiting for a status change to happen. Used to
377  // avoid triggering internal state machine logic on unexpected sync observer
378  // callbacks.
379  bool waiting_for_status_change_;
380
381  DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceHarness);
382};
383
384#endif  // CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_
385