1d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstddef>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iterator>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ostream>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/prefs/pref_service.h"
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/stringprintf.h"
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/invalidation/p2p_invalidation_service.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service.h"
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/signin_manager_base.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/about_sync_util.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/data_type_controller.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h"
34d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "chrome/browser/sync/test/integration/status_change_checker.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/pref_names.h"
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/notification_service.h"
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/base/progress_marker_map.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/util/sync_string_conversions.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(ENABLE_MANAGED_USERS)
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/managed_mode/managed_user_constants.h"
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::sessions::SyncSessionSnapshot;
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing invalidation::P2PInvalidationService;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// The amount of time for which we wait for a sync operation to complete.
51d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)static const int kSyncOperationTimeoutMs = 45000;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple class to implement a timeout using PostDelayedTask.  If it is not
54d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// aborted before picked up by a message queue, then it asserts.  This class is
55d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// not thread safe.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StateChangeTimeoutEvent
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<StateChangeTimeoutEvent> {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
59d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  explicit StateChangeTimeoutEvent(ProfileSyncServiceHarness* caller);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The entry point to the class from PostDelayedTask.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Callback();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancels the actions of the callback.  Returns true if success, false
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if the callback has already timed out.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Abort();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<StateChangeTimeoutEvent>;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~StateChangeTimeoutEvent();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool aborted_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_timeout_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Due to synchronization of the IO loop, the caller will always be alive
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if the class is not aborted.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileSyncServiceHarness* caller_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(StateChangeTimeoutEvent);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StateChangeTimeoutEvent::StateChangeTimeoutEvent(
84d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    ProfileSyncServiceHarness* caller)
85d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    : aborted_(false), did_timeout_(false), caller_(caller) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StateChangeTimeoutEvent::~StateChangeTimeoutEvent() {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StateChangeTimeoutEvent::Callback() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!aborted_) {
93d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    DCHECK(caller_->status_change_checker_);
94d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // TODO(rsimha): Simply return false on timeout instead of repeating the
95d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // exit condition check.
96d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    if (!caller_->status_change_checker_->IsExitConditionSatisfied()) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      did_timeout_ = true;
98d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      DCHECK(!aborted_);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      caller_->SignalStateComplete();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StateChangeTimeoutEvent::Abort() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aborted_ = true;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  caller_ = NULL;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !did_timeout_;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)namespace {
111d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
112d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// Helper function which returns true if the sync backend has been initialized,
113d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// or if backend initialization was blocked for some reason.
114d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool DoneWaitingForBackendInitialization(
115d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    const ProfileSyncServiceHarness* harness) {
116d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(harness);
117d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Backend is initialized.
118d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (harness->service()->sync_initialized())
119d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return true;
120d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Backend initialization is blocked by an auth error.
121d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (harness->HasAuthError())
122d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return true;
123d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Backend initialization is blocked by a failure to fetch Oauth2 tokens.
124d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (harness->service()->IsRetryingAccessTokenFetchForTest())
125d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return true;
126d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Still waiting on backend initialization.
127d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return false;
128d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
129d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
130d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// Helper function which returns true if initial sync is complete, or if the
131d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// initial sync is blocked for some reason.
132d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool DoneWaitingForInitialSync(const ProfileSyncServiceHarness* harness) {
133d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(harness);
134d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Initial sync is complete.
135d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (harness->IsFullySynced())
136d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return true;
137d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Initial sync is blocked because custom passphrase is required.
138d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (harness->service()->passphrase_required_reason() ==
139d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      syncer::REASON_DECRYPTION) {
140d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return true;
141d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  }
142d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Initial sync is blocked by an auth error.
143d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (harness->HasAuthError())
144d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return true;
145d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Still waiting on initial sync.
146d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return false;
147d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
148d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
149d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// Helper function which returns true if the sync client is fully synced, or if
150d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// sync is blocked for some reason.
151d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool DoneWaitingForFullSync(const ProfileSyncServiceHarness* harness) {
152d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(harness);
153d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Sync is complete.
154d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (harness->IsFullySynced())
155d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return true;
156d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Sync is blocked by an auth error.
157d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (harness->HasAuthError())
158d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return true;
159d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Sync is blocked by a failure to fetch Oauth2 tokens.
160d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (harness->service()->IsRetryingAccessTokenFetchForTest())
161d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return true;
162d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // Still waiting on sync.
163d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return false;
164d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
165d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
166d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// Helper function which returns true if the sync client requires a custom
167d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// passphrase to be entered for decryption.
168d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool IsPassphraseRequired(const ProfileSyncServiceHarness* harness) {
169d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(harness);
170d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return harness->service()->IsPassphraseRequired();
171d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
172d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
173d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// Helper function which returns true if the custom passphrase entered was
174d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// accepted.
175d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool IsPassphraseAccepted(const ProfileSyncServiceHarness* harness) {
176d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(harness);
177d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return (!harness->service()->IsPassphraseRequired() &&
178d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          harness->service()->IsUsingSecondaryPassphrase());
179d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
180d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
181d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// Helper function which returns true if the sync client no longer has a pending
182d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// backend migration.
183d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool NoPendingBackendMigration(const ProfileSyncServiceHarness* harness) {
184d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(harness);
185d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return !harness->HasPendingBackendMigration();
186d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
187d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
188d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// Helper function which returns true if the client has detected an actionable
189d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// error.
190d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool HasActionableError(const ProfileSyncServiceHarness* harness) {
191d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(harness);
192d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  ProfileSyncService::Status status = harness->GetStatus();
193d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return (status.sync_protocol_error.action != syncer::UNKNOWN_ACTION &&
194d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          harness->service()->HasUnrecoverableError() == true);
195d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
196d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
197d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}  // namespace
198d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochProfileSyncServiceHarness* ProfileSyncServiceHarness::Create(
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    Profile* profile,
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& username,
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& password) {
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return new ProfileSyncServiceHarness(profile, username, password, NULL);
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochProfileSyncServiceHarness* ProfileSyncServiceHarness::CreateForIntegrationTest(
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    Profile* profile,
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& username,
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& password,
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    P2PInvalidationService* p2p_invalidation_service) {
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return new ProfileSyncServiceHarness(profile,
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       username,
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       password,
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       p2p_invalidation_service);
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileSyncServiceHarness::ProfileSyncServiceHarness(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& username,
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& password,
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    P2PInvalidationService* p2p_invalidation_service)
224d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    : profile_(profile),
225d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      service_(ProfileSyncServiceFactory::GetForProfile(profile)),
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      p2p_invalidation_service_(p2p_invalidation_service),
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      progress_marker_partner_(NULL),
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      username_(username),
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      password_(password),
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      oauth2_refesh_token_number_(0),
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_debug_name_(profile->GetDebugName()),
232d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      status_change_checker_(NULL) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProfileSyncServiceHarness::~ProfileSyncServiceHarness() {
236d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (service()->HasObserver(this))
237d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    service()->RemoveObserver(this);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceHarness::SetCredentials(const std::string& username,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const std::string& password) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  username_ = username;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  password_ = password;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::SetupSync() {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = SetupSync(syncer::ModelTypeSet::All());
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == false) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string status = GetServiceStatus();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << profile_debug_name_
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << ": SetupSync failed. Syncer status:\n" << status;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << profile_debug_name_ << ": SetupSync successful.";
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::SetupSync(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelTypeSet synced_datatypes) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the sync client's profile sync service object.
261d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (service() == NULL) {
262d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    LOG(ERROR) << "SetupSync(): service() is null.";
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Subscribe sync client to notifications from the profile sync service.
267d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!service()->HasObserver(this))
268d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    service()->AddObserver(this);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell the sync service that setup is in progress so we don't start syncing
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until we've finished configuration.
272d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  service()->SetSetupInProgress(true);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Authenticate sync client using GAIA credentials.
275d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  service()->signin()->SetAuthenticatedUsername(username_);
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  username_);
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GoogleServiceSigninSuccessDetails details(username_, password_);
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content::NotificationService::current()->Notify(
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::Source<Profile>(profile_),
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::Details<const GoogleServiceSigninSuccessDetails>(&details));
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(ENABLE_MANAGED_USERS)
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string account_id = profile_->IsManaged() ?
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      managed_users::kManagedUserPseudoEmail : username_;
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#else
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string account_id = username_;
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!account_id.empty());
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      UpdateCredentials(account_id, GenerateFakeOAuth2RefreshTokenString());
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the OnBackendInitialized() callback.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AwaitBackendInitialized()) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "OnBackendInitialized() not seen after "
297d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)               << kSyncOperationTimeoutMs / 1000
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " seconds.";
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure that initial sync wasn't blocked by a missing passphrase.
303d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (service()->passphrase_required_reason() == syncer::REASON_DECRYPTION) {
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  " until SetDecryptionPassphrase is called.";
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure that initial sync wasn't blocked by rejected credentials.
310d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (HasAuthError()) {
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Credentials were rejected. Sync cannot proceed.";
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Choose the datatypes to be synced. If all datatypes are to be synced,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set sync_everything to true; otherwise, set it to false.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sync_everything =
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      synced_datatypes.Equals(syncer::ModelTypeSet::All());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->OnUserChoseDatatypes(sync_everything, synced_datatypes);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify ProfileSyncService that we are done with configuration.
322d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  FinishSyncSetup();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Subscribe sync client to notifications from the backend migrator
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (possible only after choosing data types).
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!TryListeningToMigrationEvents()) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set an implicit passphrase for encryption if an explicit one hasn't already
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // been set. If an explicit passphrase has been set, immediately return false,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since a decryption passphrase is required.
334d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!service()->IsUsingSecondaryPassphrase()) {
335d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    service()->SetEncryptionPassphrase(password_, ProfileSyncService::IMPLICIT);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  " until SetDecryptionPassphrase is called.";
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for initial sync cycle to be completed.
343d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(service()->sync_initialized());
344d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker initial_sync_checker(
345d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&DoneWaitingForInitialSync, base::Unretained(this)),
346d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "DoneWaitingForInitialSync");
347d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!AwaitStatusChange(&initial_sync_checker, "SetupSync")) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Initial sync cycle did not complete after "
349d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)               << kSyncOperationTimeoutMs / 1000
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " seconds.";
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that initial sync wasn't blocked by a missing passphrase.
355d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (service()->passphrase_required_reason() == syncer::REASON_DECRYPTION) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  " until SetDecryptionPassphrase is called.";
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure that initial sync wasn't blocked by rejected credentials.
362d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (service()->GetAuthError().state() ==
363d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) {
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Credentials were rejected. Sync cannot proceed.";
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::TryListeningToMigrationEvents() {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_sync::BackendMigrator* migrator =
373d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      service()->GetBackendMigratorForTest();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (migrator && !migrator->HasMigrationObserver(this)) {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    migrator->AddMigrationObserver(this);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceHarness::SignalStateComplete() {
382d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  base::MessageLoop::current()->QuitWhenIdle();
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceHarness::OnStateChanged() {
386d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!status_change_checker_)
387d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return;
388d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
389d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DVLOG(1) << GetClientInfoString(status_change_checker_->callback_name());
390d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (status_change_checker_->IsExitConditionSatisfied())
391d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    base::MessageLoop::current()->QuitWhenIdle();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ProfileSyncServiceHarness::OnSyncCycleCompleted() {
395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Integration tests still use p2p notifications.
396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool is_notifiable_commit =
398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (snap.model_neutral_state().num_successful_commits > 0);
399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (is_notifiable_commit && p2p_invalidation_service_) {
400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    syncer::ModelTypeSet model_types =
401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        snap.model_neutral_state().commit_request_types;
402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    syncer::ObjectIdSet ids = ModelTypeSetToObjectIdSet(model_types);
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    p2p_invalidation_service_->SendInvalidation(ids);
404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OnStateChanged();
406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceHarness::OnMigrationStateChange() {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update migration state.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasPendingBackendMigration()) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Merge current pending migration types into
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |pending_migration_types_|.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_migration_types_.PutAll(
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        service()->GetBackendMigratorForTest()->
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GetPendingMigrationTypesForTest());
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << profile_debug_name_ << ": new pending migration types "
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeSetToString(pending_migration_types_);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Merge just-finished pending migration types into
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |migration_types_|.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    migrated_types_.PutAll(pending_migration_types_);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_migration_types_.Clear();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << profile_debug_name_ << ": new migrated types "
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeSetToString(migrated_types_);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
426d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  OnStateChanged();
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitPassphraseRequired() {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitPassphraseRequired");
431d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (IsSyncDisabled()) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service()->IsPassphraseRequired()) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It's already true that a passphrase is required; don't wait.
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
441d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker passphrase_required_checker(
442d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&::IsPassphraseRequired, base::Unretained(this)),
443d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "IsPassphraseRequired");
444d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return AwaitStatusChange(&passphrase_required_checker,
445d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                           "AwaitPassphraseRequired");
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitPassphraseAccepted() {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitPassphraseAccepted");
450d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (IsSyncDisabled()) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!service()->IsPassphraseRequired() &&
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service()->IsUsingSecondaryPassphrase()) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Passphrase is already accepted; don't wait.
458d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    FinishSyncSetup();
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
462d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker passphrase_accepted_checker(
463d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&::IsPassphraseAccepted, base::Unretained(this)),
464d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "IsPassphraseAccepted");
465d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  bool return_value = AwaitStatusChange(&passphrase_accepted_checker,
466d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                                        "AwaitPassphraseAccepted");
467d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (return_value)
468d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    FinishSyncSetup();
469d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return return_value;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitBackendInitialized() {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitBackendInitialized");
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service()->sync_initialized()) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The sync backend host has already been initialized; don't wait.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
479d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker backend_initialized_checker(
480d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&DoneWaitingForBackendInitialization,
481d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
482d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "DoneWaitingForBackendInitialization");
483d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  AwaitStatusChange(&backend_initialized_checker, "AwaitBackendInitialized");
484d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return service()->sync_initialized();
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
487d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitDataSyncCompletion() {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitDataSyncCompletion");
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
490d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(service()->sync_initialized());
491d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(!IsSyncDisabled());
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDataSynced()) {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Client is already synced; don't wait.
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
498d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker data_synced_checker(
499d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&ProfileSyncServiceHarness::IsDataSynced,
500d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
501d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "IsDataSynced");
502d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return AwaitStatusChange(&data_synced_checker, "AwaitDataSyncCompletion");
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitFullSyncCompletion() {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitFullSyncCompletion");
507d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (IsSyncDisabled()) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsFullySynced()) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Client is already synced; don't wait.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(service()->sync_initialized());
518d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker fully_synced_checker(
519d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&DoneWaitingForFullSync, base::Unretained(this)),
520d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "DoneWaitingForFullSync");
521d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  AwaitStatusChange(&fully_synced_checker, "AwaitFullSyncCompletion");
522d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return IsFullySynced();
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitSyncDisabled() {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(service()->HasSyncSetupCompleted());
527d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(!IsSyncDisabled());
528d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker sync_disabled_checker(
529d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&ProfileSyncServiceHarness::IsSyncDisabled,
530d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
531d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "IsSyncDisabled");
532d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return AwaitStatusChange(&sync_disabled_checker, "AwaitSyncDisabled");
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// TODO(rsimha): Move this method from PSSHarness to the class that uses it.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitExponentialBackoffVerification() {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
538d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  retry_verifier_.reset(new RetryVerifier());
539d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  retry_verifier_->Initialize(snap);
540d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker exponential_backoff_checker(
541d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&ProfileSyncServiceHarness::IsExponentialBackoffDone,
542d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
543d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "IsExponentialBackoffDone");
544d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  AwaitStatusChange(&exponential_backoff_checker,
545d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                    "AwaitExponentialBackoffVerification");
546d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return retry_verifier_->Succeeded();
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitActionableError() {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileSyncService::Status status = GetStatus();
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(status.sync_protocol_error.action == syncer::UNKNOWN_ACTION);
552d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker actionable_error_checker(
553d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&HasActionableError, base::Unretained(this)),
554d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "HasActionableError");
555d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return AwaitStatusChange(&actionable_error_checker, "AwaitActionableError");
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitMigration(
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelTypeSet expected_migrated_types) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitMigration");
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << profile_debug_name_ << ": waiting until migration is done for "
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << syncer::ModelTypeSetToString(expected_migrated_types);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool migration_finished = migrated_types_.HasAll(expected_migrated_types);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Migrated types "
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeSetToString(migrated_types_)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << (migration_finished ? " contains " : " does not contain ")
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeSetToString(expected_migrated_types);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (migration_finished) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
573d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    if (!HasPendingBackendMigration()) {
574d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      StatusChangeChecker pending_migration_checker(
575d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          base::Bind(&ProfileSyncServiceHarness::HasPendingBackendMigration,
576d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                     base::Unretained(this)),
577d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          "HasPendingBackendMigration");
578d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      if (!AwaitStatusChange(&pending_migration_checker,
579d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                             "AwaitMigration Start")) {
580d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        DVLOG(1) << profile_debug_name_ << ": Migration did not start";
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
584d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
585d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    StatusChangeChecker migration_finished_checker(
586d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        base::Bind(&::NoPendingBackendMigration, base::Unretained(this)),
587d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        "NoPendingBackendMigration");
588d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    if (!AwaitStatusChange(&migration_finished_checker,
589d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                           "AwaitMigration Finish")) {
590d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      DVLOG(1) << profile_debug_name_ << ": Migration did not finish";
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
593d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We must use AwaitDataSyncCompletion rather than the more common
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // AwaitFullSyncCompletion.  As long as crbug.com/97780 is open, we will
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // rely on self-notifications to ensure that progress markers are updated,
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which allows AwaitFullSyncCompletion to return.  However, in some
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // migration tests these notifications are completely disabled, so the
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // progress markers do not get updated.  This is why we must use the less
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // strict condition, AwaitDataSyncCompletion.
601d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    if (!AwaitDataSyncCompletion())
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitMutualSyncCycleCompletion(
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileSyncServiceHarness* partner) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitMutualSyncCycleCompletion");
609d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!AwaitFullSyncCompletion())
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
611d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return partner->WaitUntilProgressMarkersMatch(this);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitGroupSyncCycleCompletion(
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<ProfileSyncServiceHarness*>& partners) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitGroupSyncCycleCompletion");
617d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!AwaitFullSyncCompletion())
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool return_value = true;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<ProfileSyncServiceHarness*>::iterator it =
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partners.begin(); it != partners.end(); ++it) {
622d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    if ((this != *it) && (!(*it)->IsSyncDisabled())) {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return_value = return_value &&
624d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)          (*it)->WaitUntilProgressMarkersMatch(this);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return return_value;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitQuiescence(
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<ProfileSyncServiceHarness*>& clients) {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "AwaitQuiescence.";
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool return_value = true;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<ProfileSyncServiceHarness*>::iterator it =
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clients.begin(); it != clients.end(); ++it) {
637d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    if (!(*it)->IsSyncDisabled()) {
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return_value = return_value &&
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*it)->AwaitGroupSyncCycleCompletion(clients);
640d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    }
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return return_value;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::WaitUntilProgressMarkersMatch(
646d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    ProfileSyncServiceHarness* partner) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("WaitUntilProgressMarkersMatch");
648d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (IsSyncDisabled()) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
653d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // TODO(rsimha): Replace the mechanism of matching up progress markers with
654d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  // one that doesn't require every client to have the same progress markers.
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!progress_marker_partner_);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  progress_marker_partner_ = partner;
657d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  bool return_value = false;
658d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (MatchesPartnerClient()) {
659d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // Progress markers already match; don't wait.
660d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return_value = true;
661d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  } else {
662d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    partner->service()->AddObserver(this);
663d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    StatusChangeChecker matches_other_client_checker(
664d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        base::Bind(&ProfileSyncServiceHarness::MatchesPartnerClient,
665d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                   base::Unretained(this)),
666d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        "MatchesPartnerClient");
667d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return_value = AwaitStatusChange(&matches_other_client_checker,
668d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                                     "WaitUntilProgressMarkersMatch");
669d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    partner->service()->RemoveObserver(this);
670d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  }
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  progress_marker_partner_ = NULL;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return return_value;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitStatusChange(
676d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    StatusChangeChecker* checker, const std::string& source) {
677d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitStatusChange");
678d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
679d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (IsSyncDisabled()) {
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
683d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
684d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(status_change_checker_ == NULL);
685d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  status_change_checker_ = checker;
686d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<StateChangeTimeoutEvent> timeout_signal(
688d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      new StateChangeTimeoutEvent(this));
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
69090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop* loop = base::MessageLoop::current();
69190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::ScopedNestableTaskAllower allow(loop);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop->PostDelayedTask(
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&StateChangeTimeoutEvent::Callback,
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   timeout_signal.get()),
696d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kSyncOperationTimeoutMs));
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop->Run();
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
700d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  status_change_checker_ = NULL;
701d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (timeout_signal->Abort()) {
703d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    DVLOG(1) << GetClientInfoString("AwaitStatusChange succeeded");
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
706d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    DVLOG(0) << GetClientInfoString(base::StringPrintf(
707d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        "AwaitStatusChange called from %s timed out", source.c_str()));
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
712f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string ProfileSyncServiceHarness::GenerateFakeOAuth2RefreshTokenString() {
713f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return base::StringPrintf("oauth2_refresh_token_%d",
714f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            ++oauth2_refesh_token_number_);
715f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
716f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
717d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)ProfileSyncService::Status ProfileSyncServiceHarness::GetStatus() const {
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(service() != NULL) << "GetStatus(): service() is NULL.";
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileSyncService::Status result;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->QueryDetailedSyncStatus(&result);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
724d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::IsExponentialBackoffDone() const {
725d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
726d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  retry_verifier_->VerifyRetryInterval(snap);
727d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return (retry_verifier_->done());
728d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
729d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
730d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::IsSyncDisabled() const {
731d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return !service()->setup_in_progress() &&
732d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)         !service()->HasSyncSetupCompleted();
733d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
734d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
735d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::HasAuthError() const {
736d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return service()->GetAuthError().state() ==
737d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)             GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
738d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)         service()->GetAuthError().state() ==
739d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)             GoogleServiceAuthError::SERVICE_ERROR ||
740d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)         service()->GetAuthError().state() ==
741d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)             GoogleServiceAuthError::REQUEST_CANCELED;
742d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
743d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
744d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// We use this function to share code between IsFullySynced and IsDataSynced.
745d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::IsDataSyncedImpl() const {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ServiceIsPushingChanges() &&
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         GetStatus().notifications_enabled &&
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !service()->HasUnsyncedItems() &&
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !HasPendingBackendMigration();
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
752d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::IsDataSynced() const {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << GetClientInfoString("IsDataSynced(): false");
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
758d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  bool is_data_synced = IsDataSyncedImpl();
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString(
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_data_synced ? "IsDataSynced: true" : "IsDataSynced: false");
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_data_synced;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::IsFullySynced() const {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << GetClientInfoString("IsFullySynced: false");
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we didn't try to commit anything in the previous cycle, there's a
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // good chance that we're now fully up to date.
772d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_fully_synced =
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      snap.model_neutral_state().num_successful_commits == 0
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && snap.model_neutral_state().commit_result == syncer::SYNCER_OK
776d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      && IsDataSyncedImpl();
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString(
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_fully_synced ? "IsFullySynced: true" : "IsFullySynced: false");
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_fully_synced;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
783d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)void ProfileSyncServiceHarness::FinishSyncSetup() {
784d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  service()->SetSetupInProgress(false);
785d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  service()->SetSyncSetupCompleted();
786d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)}
787d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
788d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::HasPendingBackendMigration() const {
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_sync::BackendMigrator* migrator =
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service()->GetBackendMigratorForTest();
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return migrator && migrator->state() != browser_sync::BackendMigrator::IDLE;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AutoStartEnabled() {
795d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return service()->auto_start_enabled();
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
798d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::MatchesPartnerClient() const {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(akalin): Shouldn't this belong with the intersection check?
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, this function isn't symmetric.
801d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(progress_marker_partner_);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsFullySynced()) {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(2) << profile_debug_name_ << ": not synced, assuming doesn't match";
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only look for a match if we have at least one enabled datatype in
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // common with the partner client.
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::ModelTypeSet common_types =
810868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Intersection(service()->GetActiveDataTypes(),
811d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                   progress_marker_partner_->service()->GetActiveDataTypes());
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
813d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DVLOG(2) << profile_debug_name_ << ", "
814d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)           << progress_marker_partner_->profile_debug_name_
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ": common types are "
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << syncer::ModelTypeSetToString(common_types);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
818d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (!common_types.Empty() && !progress_marker_partner_->IsFullySynced()) {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(2) << "non-empty common types and "
820d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)             << progress_marker_partner_->profile_debug_name_
821d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)             << " isn't synced";
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (syncer::ModelTypeSet::Iterator i = common_types.First();
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i.Good(); i.Inc()) {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string marker = GetSerializedProgressMarker(i.Get());
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string partner_marker =
829d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        progress_marker_partner_->GetSerializedProgressMarker(i.Get());
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (marker != partner_marker) {
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (VLOG_IS_ON(2)) {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string marker_base64, partner_marker_base64;
833a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Base64Encode(marker, &marker_base64);
834a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Base64Encode(partner_marker, &partner_marker_base64);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(2) << syncer::ModelTypeToString(i.Get()) << ": "
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << profile_debug_name_ << " progress marker = "
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << marker_base64 << ", "
838d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 << progress_marker_partner_->profile_debug_name_
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << " partner progress marker = "
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << partner_marker_base64;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncSessionSnapshot ProfileSyncServiceHarness::GetLastSessionSnapshot() const {
849d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DCHECK(service() != NULL) << "Sync service has not yet been set up.";
850d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (service()->sync_initialized()) {
851d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    return service()->GetLastSessionSnapshot();
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SyncSessionSnapshot();
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::EnableSyncForDatatype(
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType datatype) {
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString(
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "EnableSyncForDatatype("
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      + std::string(syncer::ModelTypeToString(datatype)) + ")");
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
862d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (IsSyncDisabled())
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SetupSync(syncer::ModelTypeSet(datatype));
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "EnableSyncForDatatype(): service() is null.";
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::ModelTypeSet synced_datatypes = service()->GetPreferredDataTypes();
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (synced_datatypes.Has(datatype)) {
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "EnableSyncForDatatype(): Sync already enabled for datatype "
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeToString(datatype)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " on " << profile_debug_name_ << ".";
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  synced_datatypes.Put(syncer::ModelTypeFromInt(datatype));
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->OnUserChoseDatatypes(false, synced_datatypes);
880d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (AwaitDataSyncCompletion()) {
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "EnableSyncForDatatype(): Enabled sync for datatype "
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeToString(datatype)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " on " << profile_debug_name_ << ".";
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(0) << GetClientInfoString("EnableSyncForDatatype failed");
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::DisableSyncForDatatype(
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType datatype) {
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString(
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "DisableSyncForDatatype("
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      + std::string(syncer::ModelTypeToString(datatype)) + ")");
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "DisableSyncForDatatype(): service() is null.";
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::ModelTypeSet synced_datatypes = service()->GetPreferredDataTypes();
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!synced_datatypes.Has(datatype)) {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "DisableSyncForDatatype(): Sync already disabled for datatype "
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeToString(datatype)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " on " << profile_debug_name_ << ".";
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  synced_datatypes.RetainAll(syncer::UserSelectableTypes());
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  synced_datatypes.Remove(datatype);
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->OnUserChoseDatatypes(false, synced_datatypes);
913d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (AwaitFullSyncCompletion()) {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "DisableSyncForDatatype(): Disabled sync for datatype "
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeToString(datatype)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " on " << profile_debug_name_ << ".";
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(0) << GetClientInfoString("DisableSyncForDatatype failed");
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::EnableSyncForAllDatatypes() {
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("EnableSyncForAllDatatypes");
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
927d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (IsSyncDisabled())
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SetupSync();
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "EnableSyncForAllDatatypes(): service() is null.";
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->OnUserChoseDatatypes(true, syncer::ModelTypeSet::All());
936d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (AwaitFullSyncCompletion()) {
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "EnableSyncForAllDatatypes(): Enabled sync for all datatypes "
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << "on " << profile_debug_name_ << ".";
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(0) << GetClientInfoString("EnableSyncForAllDatatypes failed");
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::DisableSyncForAllDatatypes() {
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("DisableSyncForAllDatatypes");
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "DisableSyncForAllDatatypes(): service() is null.";
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->DisableForUser();
955d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "DisableSyncForAllDatatypes(): Disabled sync for all "
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << "datatypes on " << profile_debug_name_;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProfileSyncServiceHarness::GetSerializedProgressMarker(
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType model_type) const {
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::ProgressMarkerMap& markers_map =
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      snap.download_progress_markers();
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::ProgressMarkerMap::const_iterator it =
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      markers_map.find(model_type);
969c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (it != markers_map.end()) ? it->second : std::string();
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProfileSyncServiceHarness::GetClientInfoString(
973d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    const std::string& message) const {
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::stringstream os;
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os << profile_debug_name_ << ": " << message << ": ";
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service()) {
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProfileSyncService::Status& status = GetStatus();
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Capture select info from the sync session snapshot and syncer status.
980d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // TODO(rsimha): Audit the list of fields below, and eventually eliminate
981d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // the use of the sync session snapshot. See crbug.com/323380.
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << ", has_unsynced_items: "
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << (service()->sync_initialized() ? service()->HasUnsyncedItems() : 0)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", did_commit: "
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << (snap.model_neutral_state().num_successful_commits == 0 &&
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           snap.model_neutral_state().commit_result == syncer::SYNCER_OK)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", encryption conflicts: "
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << snap.num_encryption_conflicts()
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", hierarchy conflicts: "
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << snap.num_hierarchy_conflicts()
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", server conflicts: "
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << snap.num_server_conflicts()
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", num_updates_downloaded : "
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << snap.model_neutral_state().num_updates_downloaded_total
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", passphrase_required_reason: "
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << syncer::PassphraseRequiredReasonToString(
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           service()->passphrase_required_reason())
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", notifications_enabled: "
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << status.notifications_enabled
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", service_is_pushing_changes: "
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ServiceIsPushingChanges()
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", has_pending_backend_migration: "
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << HasPendingBackendMigration();
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << "Sync service not available";
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return os.str();
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1010d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::EnableEncryption() {
1011d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (IsEncryptionComplete())
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1013d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  service()->EnableEncryptEverything();
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In order to kick off the encryption we have to reconfigure. Just grab the
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // currently synced types and use them.
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::ModelTypeSet synced_datatypes =
1018d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      service()->GetPreferredDataTypes();
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sync_everything =
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      synced_datatypes.Equals(syncer::ModelTypeSet::All());
1021d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  service()->OnUserChoseDatatypes(sync_everything, synced_datatypes);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait some time to let the enryption finish.
1024d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return WaitForEncryption();
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1027d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::WaitForEncryption() {
1028d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (IsEncryptionComplete()) {
1029d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)    // Encryption is already complete; do not wait.
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1033d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  StatusChangeChecker encryption_complete_checker(
1034d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      base::Bind(&ProfileSyncServiceHarness::IsEncryptionComplete,
1035d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
1036d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      "IsEncryptionComplete");
1037d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return AwaitStatusChange(&encryption_complete_checker, "WaitForEncryption");
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1040d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)bool ProfileSyncServiceHarness::IsEncryptionComplete() const {
1041d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  bool is_encryption_complete = service()->EncryptEverythingEnabled() &&
1042d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                                !service()->encryption_pending();
1043d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  DVLOG(2) << "Encryption is "
1044d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)           << (is_encryption_complete ? "" : "not ")
1045d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)           << "complete; Encrypted types = "
1046d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)           << syncer::ModelTypeSetToString(service()->GetEncryptedDataTypes());
1047d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return is_encryption_complete;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::IsTypeRunning(syncer::ModelType type) {
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_sync::DataTypeController::StateMap state_map;
1052d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  service()->GetDataTypeControllerStates(&state_map);
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (state_map.count(type) != 0 &&
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          state_map[type] == browser_sync::DataTypeController::RUNNING);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::IsTypePreferred(syncer::ModelType type) {
1058d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  return service()->GetPreferredDataTypes().Has(type);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ProfileSyncServiceHarness::GetNumEntries() const {
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetLastSessionSnapshot().num_entries();
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ProfileSyncServiceHarness::GetNumDatatypes() const {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_sync::DataTypeController::StateMap state_map;
1067d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  service()->GetDataTypeControllerStates(&state_map);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state_map.size();
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProfileSyncServiceHarness::GetServiceStatus() {
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DictionaryValue> value(
1073d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      sync_ui_util::ConstructAboutInformation(service()));
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string service_status;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::JSONWriter::WriteWithOptions(value.get(),
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::JSONWriter::OPTIONS_PRETTY_PRINT,
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &service_status);
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return service_status;
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1080