15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/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"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/invalidation/p2p_invalidation_service.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/signin_manager_base.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/token_service.h"
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/token_service_factory.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/about_sync_util.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/data_type_controller.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/pref_names.h"
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/notification_service.h"
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/base/progress_marker_map.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/util/sync_string_conversions.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::sessions::SyncSessionSnapshot;
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing invalidation::P2PInvalidationService;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(rsimha): Remove the following lines once crbug.com/91863 is fixed.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of time for which we wait for a live sync operation to complete.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kLiveSyncOperationTimeoutMs = 45000;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of time we wait for test cases that verify exponential backoff.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kExponentialBackoffVerificationTimeoutMs = 60000;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple class to implement a timeout using PostDelayedTask.  If it is not
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// aborted before picked up by a message queue, then it asserts with the message
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// provided.  This class is not thread safe.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StateChangeTimeoutEvent
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<StateChangeTimeoutEvent> {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StateChangeTimeoutEvent(ProfileSyncServiceHarness* caller,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const std::string& message);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The entry point to the class from PostDelayedTask.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Callback();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancels the actions of the callback.  Returns true if success, false
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if the callback has already timed out.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Abort();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<StateChangeTimeoutEvent>;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~StateChangeTimeoutEvent();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool aborted_;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_timeout_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Due to synchronization of the IO loop, the caller will always be alive
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if the class is not aborted.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileSyncServiceHarness* caller_;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Informative message to assert in the case of a timeout.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string message_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(StateChangeTimeoutEvent);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StateChangeTimeoutEvent::StateChangeTimeoutEvent(
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileSyncServiceHarness* caller,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& message)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : aborted_(false), did_timeout_(false), caller_(caller), message_(message) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StateChangeTimeoutEvent::~StateChangeTimeoutEvent() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StateChangeTimeoutEvent::Callback() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!aborted_) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!caller_->RunStateChangeMachine()) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Report the message.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      did_timeout_ = true;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!aborted_) << message_;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      caller_->SignalStateComplete();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StateChangeTimeoutEvent::Abort() {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aborted_ = true;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  caller_ = NULL;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !did_timeout_;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochProfileSyncServiceHarness* ProfileSyncServiceHarness::Create(
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    Profile* profile,
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& username,
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& password) {
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return new ProfileSyncServiceHarness(profile, username, password, NULL);
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochProfileSyncServiceHarness* ProfileSyncServiceHarness::CreateForIntegrationTest(
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    Profile* profile,
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& username,
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& password,
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    P2PInvalidationService* p2p_invalidation_service) {
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return new ProfileSyncServiceHarness(profile,
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       username,
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       password,
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       p2p_invalidation_service);
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileSyncServiceHarness::ProfileSyncServiceHarness(
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& username,
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& password,
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    P2PInvalidationService* p2p_invalidation_service)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : waiting_for_encryption_type_(syncer::UNSPECIFIED),
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_state_(INITIAL_WAIT_STATE),
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(profile),
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_(NULL),
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      p2p_invalidation_service_(p2p_invalidation_service),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      progress_marker_partner_(NULL),
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      username_(username),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      password_(password),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_debug_name_(profile->GetDebugName()),
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_for_status_change_(false) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsSyncAlreadySetup()) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_ = ProfileSyncServiceFactory::GetInstance()->GetForProfile(
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        profile_);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->AddObserver(this);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ignore_result(TryListeningToMigrationEvents());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wait_state_ = FULLY_SYNCED;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProfileSyncServiceHarness::~ProfileSyncServiceHarness() {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (service_->HasObserver(this))
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    service_->RemoveObserver(this);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceHarness::SetCredentials(const std::string& username,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const std::string& password) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  username_ = username;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  password_ = password;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::IsSyncAlreadySetup() {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::SetupSync() {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = SetupSync(syncer::ModelTypeSet::All());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == false) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string status = GetServiceStatus();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << profile_debug_name_
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << ": SetupSync failed. Syncer status:\n" << status;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << profile_debug_name_ << ": SetupSync successful.";
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::SetupSync(
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelTypeSet synced_datatypes) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the sync client's profile sync service object.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_ =
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service_ == NULL) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "SetupSync(): service_ is null.";
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Subscribe sync client to notifications from the profile sync service.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!service_->HasObserver(this))
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->AddObserver(this);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell the sync service that setup is in progress so we don't start syncing
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until we've finished configuration.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_->SetSetupInProgress(true);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Authenticate sync client using GAIA credentials.
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  service_->signin()->SetAuthenticatedUsername(username_);
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  username_);
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GoogleServiceSigninSuccessDetails details(username_, password_);
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content::NotificationService::current()->Notify(
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::Source<Profile>(profile_),
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::Details<const GoogleServiceSigninSuccessDetails>(&details));
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenServiceFactory::GetForProfile(profile_)->IssueAuthTokenForTest(
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token");
2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TokenServiceFactory::GetForProfile(profile_)->IssueAuthTokenForTest(
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GaiaConstants::kSyncService, "sync_token");
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the OnBackendInitialized() callback.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AwaitBackendInitialized()) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "OnBackendInitialized() not seen after "
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << kLiveSyncOperationTimeoutMs / 1000
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " seconds.";
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure that initial sync wasn't blocked by a missing passphrase.
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (wait_state_ == SET_PASSPHRASE_FAILED) {
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  " until SetDecryptionPassphrase is called.";
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure that initial sync wasn't blocked by rejected credentials.
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (wait_state_ == CREDENTIALS_REJECTED) {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Credentials were rejected. Sync cannot proceed.";
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Choose the datatypes to be synced. If all datatypes are to be synced,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set sync_everything to true; otherwise, set it to false.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sync_everything =
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      synced_datatypes.Equals(syncer::ModelTypeSet::All());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->OnUserChoseDatatypes(sync_everything, synced_datatypes);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify ProfileSyncService that we are done with configuration.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_->SetSetupInProgress(false);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Subscribe sync client to notifications from the backend migrator
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (possible only after choosing data types).
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!TryListeningToMigrationEvents()) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set an implicit passphrase for encryption if an explicit one hasn't already
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // been set. If an explicit passphrase has been set, immediately return false,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since a decryption passphrase is required.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!service_->IsUsingSecondaryPassphrase()) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->SetEncryptionPassphrase(password_, ProfileSyncService::IMPLICIT);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  " until SetDecryptionPassphrase is called.";
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for initial sync cycle to be completed.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(wait_state_, WAITING_FOR_INITIAL_SYNC);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Waiting for initial sync cycle to complete.")) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Initial sync cycle did not complete after "
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << kLiveSyncOperationTimeoutMs / 1000
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " seconds.";
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that initial sync wasn't blocked by a missing passphrase.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == SET_PASSPHRASE_FAILED) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  " until SetDecryptionPassphrase is called.";
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure that initial sync wasn't blocked by rejected credentials.
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (wait_state_ == CREDENTIALS_REJECTED) {
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Credentials were rejected. Sync cannot proceed.";
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicate to the browser that sync setup is complete.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->SetSyncSetupCompleted();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::TryListeningToMigrationEvents() {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_sync::BackendMigrator* migrator =
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->GetBackendMigratorForTest();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (migrator && !migrator->HasMigrationObserver(this)) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    migrator->AddMigrationObserver(this);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceHarness::SignalStateCompleteWithNextState(
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitState next_state) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = next_state;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignalStateComplete();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceHarness::SignalStateComplete() {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (waiting_for_status_change_)
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->QuitWhenIdle();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::RunStateChangeMachine() {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitState original_wait_state = wait_state_;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (wait_state_) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_ON_BACKEND_INITIALIZED: {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_ON_BACKEND_INITIALIZED");
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (service()->GetAuthError().state() ==
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) {
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Our credentials were rejected. Do not wait any more.
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SignalStateCompleteWithNextState(CREDENTIALS_REJECTED);
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (service()->sync_initialized()) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The sync backend is initialized.
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(WAITING_FOR_INITIAL_SYNC);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_INITIAL_SYNC: {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_INITIAL_SYNC");
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsFullySynced()) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The first sync cycle is now complete. We can start running tests.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(FULLY_SYNCED);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (service()->passphrase_required_reason() ==
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              syncer::REASON_DECRYPTION) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A passphrase is required for decryption and we don't have it. Do not
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // wait any more.
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(SET_PASSPHRASE_FAILED);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (service()->GetAuthError().state() ==
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) {
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Our credentials were rejected. Do not wait any more.
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SignalStateCompleteWithNextState(CREDENTIALS_REJECTED);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_FULL_SYNC: {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_FULL_SYNC");
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsFullySynced()) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The sync cycle we were waiting for is complete.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(FULLY_SYNCED);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_DATA_SYNC: {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsDataSynced()) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(FULLY_SYNCED);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_UPDATES: {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_UPDATES");
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(progress_marker_partner_);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!MatchesOtherClient(progress_marker_partner_)) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The client is not yet fully synced; keep waiting until we converge.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SignalStateCompleteWithNextState(FULLY_SYNCED);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_PASSPHRASE_REQUIRED: {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_PASSPHRASE_REQUIRED");
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (service()->IsPassphraseRequired()) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A passphrase is now required. Wait for it to be accepted.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(WAITING_FOR_PASSPHRASE_ACCEPTED);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_PASSPHRASE_ACCEPTED: {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_PASSPHRASE_ACCEPTED");
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (service()->ShouldPushChanges() &&
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !service()->IsPassphraseRequired() &&
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          service()->IsUsingSecondaryPassphrase()) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The passphrase has been accepted, and sync has been restarted.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(FULLY_SYNCED);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_ENCRYPTION: {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_ENCRYPTION");
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The correctness of this if condition may depend on the ordering of its
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // sub-expressions.  See crbug.com/98607, crbug.com/95619.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(rlarocque): Figure out a less brittle way of detecting this.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsTypeEncrypted(waiting_for_encryption_type_) &&
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          IsFullySynced() &&
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetLastSessionSnapshot().num_encryption_conflicts() == 0) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Encryption is now complete for the the type in which we were waiting.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(FULLY_SYNCED);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_SYNC_CONFIGURATION: {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_SYNC_CONFIGURATION");
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (service()->ShouldPushChanges()) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The Datatype manager is configured and sync is fully initialized.
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(FULLY_SYNCED);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_SYNC_DISABLED: {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_SYNC_DISABLED");
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (service()->HasSyncSetupCompleted() == false) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Sync has been disabled.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(SYNC_DISABLED);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_EXPONENTIAL_BACKOFF_VERIFICATION: {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString(
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "WAITING_FOR_EXPONENTIAL_BACKOFF_VERIFICATION");
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      retry_verifier_.VerifyRetryInterval(snap);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (retry_verifier_.done()) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Retry verifier is done verifying exponential backoff.
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(WAITING_FOR_NOTHING);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_MIGRATION_TO_START: {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_MIGRATION_TO_START");
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (HasPendingBackendMigration()) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // There are pending migrations. Wait for them.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(WAITING_FOR_MIGRATION_TO_FINISH);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_MIGRATION_TO_FINISH: {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_MIGRATION_TO_FINISH");
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!HasPendingBackendMigration()) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Done migrating.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(WAITING_FOR_NOTHING);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_ACTIONABLE_ERROR: {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_ACTIONABLE_ERROR");
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProfileSyncService::Status status = GetStatus();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (status.sync_protocol_error.action != syncer::UNKNOWN_ACTION &&
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          service_->HasUnrecoverableError() == true) {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // An actionable error has been detected.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SignalStateCompleteWithNextState(WAITING_FOR_NOTHING);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SET_PASSPHRASE_FAILED: {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A passphrase is required for decryption. There is nothing the sync
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // client can do until SetDecryptionPassphrase() is called.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("SET_PASSPHRASE_FAILED");
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FULLY_SYNCED: {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The client is online and fully synced. There is nothing to do.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("FULLY_SYNCED");
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYNC_DISABLED: {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Syncing is disabled for the client. There is nothing to do.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("SYNC_DISABLED");
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING_FOR_NOTHING: {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We don't care about the state of the syncer for the rest of the test
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // case.
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << GetClientInfoString("WAITING_FOR_NOTHING");
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Invalid state during observer callback which may be triggered by other
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // classes using the the UI message loop.  Defer to their handling.
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_wait_state != wait_state_;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceHarness::OnStateChanged() {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunStateChangeMachine();
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ProfileSyncServiceHarness::OnSyncCycleCompleted() {
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Integration tests still use p2p notifications.
500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool is_notifiable_commit =
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (snap.model_neutral_state().num_successful_commits > 0);
503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (is_notifiable_commit && p2p_invalidation_service_) {
504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    syncer::ModelTypeSet model_types =
505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        snap.model_neutral_state().commit_request_types;
506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    syncer::ObjectIdSet ids = ModelTypeSetToObjectIdSet(model_types);
507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    syncer::ObjectIdInvalidationMap invalidation_map =
508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        syncer::ObjectIdSetToInvalidationMap(
509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            ids,
510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            syncer::Invalidation::kUnknownVersion,
511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            "");
512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    p2p_invalidation_service_->SendInvalidation(invalidation_map);
513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OnStateChanged();
516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileSyncServiceHarness::OnMigrationStateChange() {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update migration state.
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasPendingBackendMigration()) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Merge current pending migration types into
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |pending_migration_types_|.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_migration_types_.PutAll(
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        service()->GetBackendMigratorForTest()->
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GetPendingMigrationTypesForTest());
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << profile_debug_name_ << ": new pending migration types "
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeSetToString(pending_migration_types_);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Merge just-finished pending migration types into
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |migration_types_|.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    migrated_types_.PutAll(pending_migration_types_);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_migration_types_.Clear();
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << profile_debug_name_ << ": new migrated types "
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeSetToString(migrated_types_);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunStateChangeMachine();
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitPassphraseRequired() {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitPassphraseRequired");
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == SYNC_DISABLED) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service()->IsPassphraseRequired()) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It's already true that a passphrase is required; don't wait.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_PASSPHRASE_REQUIRED;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs,
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      "Waiting for passphrase to be required.");
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitPassphraseAccepted() {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitPassphraseAccepted");
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == SYNC_DISABLED) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service()->ShouldPushChanges() &&
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !service()->IsPassphraseRequired() &&
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service()->IsUsingSecondaryPassphrase()) {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Passphrase is already accepted; don't wait.
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_PASSPHRASE_ACCEPTED;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs,
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      "Waiting for passphrase to be accepted.");
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitBackendInitialized() {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitBackendInitialized");
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service()->sync_initialized()) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The sync backend host has already been initialized; don't wait.
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_ON_BACKEND_INITIALIZED;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs,
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      "Waiting for OnBackendInitialized().");
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitDataSyncCompletion(
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& reason) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitDataSyncCompletion");
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(service()->sync_initialized());
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_NE(wait_state_, SYNC_DISABLED);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDataSynced()) {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Client is already synced; don't wait.
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_DATA_SYNC;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, reason);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == FULLY_SYNCED) {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "AwaitDataSyncCompletion failed, state is now: "
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << wait_state_;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitFullSyncCompletion(
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& reason) {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitFullSyncCompletion");
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == SYNC_DISABLED) {
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsFullySynced()) {
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Client is already synced; don't wait.
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(service()->sync_initialized());
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_FULL_SYNC;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, reason);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == FULLY_SYNCED) {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Client is online; sync was successful.
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Invalid wait state: " << wait_state_;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitSyncDisabled(const std::string& reason) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(service()->HasSyncSetupCompleted());
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(wait_state_, SYNC_DISABLED);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_SYNC_DISABLED;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, reason);
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return wait_state_ == SYNC_DISABLED;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitExponentialBackoffVerification() {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retry_verifier_.Initialize(snap);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_EXPONENTIAL_BACKOFF_VERIFICATION;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AwaitStatusChangeWithTimeout(kExponentialBackoffVerificationTimeoutMs,
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Verify Exponential backoff");
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (retry_verifier_.Succeeded());
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitActionableError() {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileSyncService::Status status = GetStatus();
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(status.sync_protocol_error.action == syncer::UNKNOWN_ACTION);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_ACTIONABLE_ERROR;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs,
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Waiting for actionable error");
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status = GetStatus();
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (status.sync_protocol_error.action != syncer::UNKNOWN_ACTION &&
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          service_->HasUnrecoverableError());
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitMigration(
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelTypeSet expected_migrated_types) {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitMigration");
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << profile_debug_name_ << ": waiting until migration is done for "
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << syncer::ModelTypeSetToString(expected_migrated_types);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool migration_finished = migrated_types_.HasAll(expected_migrated_types);
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Migrated types "
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeSetToString(migrated_types_)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << (migration_finished ? " contains " : " does not contain ")
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeSetToString(expected_migrated_types);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (migration_finished) {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasPendingBackendMigration()) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_state_ = WAITING_FOR_MIGRATION_TO_FINISH;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_state_ = WAITING_FOR_MIGRATION_TO_START;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs,
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   "Wait for migration to start");
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (wait_state_ != WAITING_FOR_MIGRATION_TO_FINISH) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(1) << profile_debug_name_
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << ": wait state = " << wait_state_
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << " after migration start is not "
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << "WAITING_FOR_MIGRATION_TO_FINISH";
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs,
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 "Wait for migration to finish");
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (wait_state_ != WAITING_FOR_NOTHING) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << profile_debug_name_
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << ": wait state = " << wait_state_
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " after migration finish is not WAITING_FOR_NOTHING";
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We must use AwaitDataSyncCompletion rather than the more common
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // AwaitFullSyncCompletion.  As long as crbug.com/97780 is open, we will
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // rely on self-notifications to ensure that progress markers are updated,
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which allows AwaitFullSyncCompletion to return.  However, in some
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // migration tests these notifications are completely disabled, so the
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // progress markers do not get updated.  This is why we must use the less
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // strict condition, AwaitDataSyncCompletion.
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!AwaitDataSyncCompletion(
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "Config sync cycle after migration cycle")) {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitMutualSyncCycleCompletion(
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileSyncServiceHarness* partner) {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitMutualSyncCycleCompletion");
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AwaitFullSyncCompletion("Sync cycle completion on active client."))
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return partner->WaitUntilProgressMarkersMatch(this,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sync cycle completion on passive client.");
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitGroupSyncCycleCompletion(
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<ProfileSyncServiceHarness*>& partners) {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitGroupSyncCycleCompletion");
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AwaitFullSyncCompletion("Sync cycle completion on active client."))
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool return_value = true;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<ProfileSyncServiceHarness*>::iterator it =
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      partners.begin(); it != partners.end(); ++it) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((this != *it) && ((*it)->wait_state_ != SYNC_DISABLED)) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return_value = return_value &&
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*it)->WaitUntilProgressMarkersMatch(this,
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "Sync cycle completion on partner client.");
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return return_value;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitQuiescence(
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<ProfileSyncServiceHarness*>& clients) {
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "AwaitQuiescence.";
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool return_value = true;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<ProfileSyncServiceHarness*>::iterator it =
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clients.begin(); it != clients.end(); ++it) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->wait_state_ != SYNC_DISABLED)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return_value = return_value &&
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*it)->AwaitGroupSyncCycleCompletion(clients);
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return return_value;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::WaitUntilProgressMarkersMatch(
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileSyncServiceHarness* partner, const std::string& reason) {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("WaitUntilProgressMarkersMatch");
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == SYNC_DISABLED) {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (MatchesOtherClient(partner)) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Progress markers already match; don't wait.
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!progress_marker_partner_);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  progress_marker_partner_ = partner;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partner->service()->AddObserver(this);
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_UPDATES;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool return_value =
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, reason);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partner->service()->RemoveObserver(this);
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  progress_marker_partner_ = NULL;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return return_value;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AwaitStatusChangeWithTimeout(
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int timeout_milliseconds,
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& reason) {
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("AwaitStatusChangeWithTimeout");
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == SYNC_DISABLED) {
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync disabled for " << profile_debug_name_ << ".";
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<StateChangeTimeoutEvent> timeout_signal(
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new StateChangeTimeoutEvent(this, reason));
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set the flag to tell SignalStateComplete() that it's OK to quit out of
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the MessageLoop if we hit a state transition.
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    waiting_for_status_change_ = true;
79290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop* loop = base::MessageLoop::current();
79390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::ScopedNestableTaskAllower allow(loop);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop->PostDelayedTask(
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&StateChangeTimeoutEvent::Callback,
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   timeout_signal.get()),
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(timeout_milliseconds));
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop->Run();
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    waiting_for_status_change_ = false;
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (timeout_signal->Abort()) {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << GetClientInfoString("AwaitStatusChangeWithTimeout succeeded");
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(0) << GetClientInfoString("AwaitStatusChangeWithTimeout timed out");
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileSyncService::Status ProfileSyncServiceHarness::GetStatus() {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(service() != NULL) << "GetStatus(): service() is NULL.";
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileSyncService::Status result;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->QueryDetailedSyncStatus(&result);
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use this function to share code between IsFullySynced and IsDataSynced
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// while ensuring that all conditions are evaluated using on the same snapshot.
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::IsDataSyncedImpl(
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SyncSessionSnapshot& snap) {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ServiceIsPushingChanges() &&
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         GetStatus().notifications_enabled &&
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !service()->HasUnsyncedItems() &&
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !HasPendingBackendMigration();
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::IsDataSynced() {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << GetClientInfoString("IsDataSynced(): false");
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_data_synced = IsDataSyncedImpl(snap);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString(
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_data_synced ? "IsDataSynced: true" : "IsDataSynced: false");
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_data_synced;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::IsFullySynced() {
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << GetClientInfoString("IsFullySynced: false");
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we didn't try to commit anything in the previous cycle, there's a
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // good chance that we're now fully up to date.
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_fully_synced =
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      snap.model_neutral_state().num_successful_commits == 0
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && snap.model_neutral_state().commit_result == syncer::SYNCER_OK
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && IsDataSyncedImpl(snap);
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString(
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_fully_synced ? "IsFullySynced: true" : "IsFullySynced: false");
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_fully_synced;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::HasPendingBackendMigration() {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_sync::BackendMigrator* migrator =
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service()->GetBackendMigratorForTest();
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return migrator && migrator->state() != browser_sync::BackendMigrator::IDLE;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::AutoStartEnabled() {
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return service_->auto_start_enabled();
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::MatchesOtherClient(
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileSyncServiceHarness* partner) {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(akalin): Shouldn't this belong with the intersection check?
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, this function isn't symmetric.
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsFullySynced()) {
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(2) << profile_debug_name_ << ": not synced, assuming doesn't match";
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only look for a match if we have at least one enabled datatype in
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // common with the partner client.
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::ModelTypeSet common_types =
883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Intersection(service()->GetActiveDataTypes(),
884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   partner->service()->GetActiveDataTypes());
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(2) << profile_debug_name_ << ", " << partner->profile_debug_name_
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ": common types are "
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << syncer::ModelTypeSetToString(common_types);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!common_types.Empty() && !partner->IsFullySynced()) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(2) << "non-empty common types and "
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << partner->profile_debug_name_ << " isn't synced";
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (syncer::ModelTypeSet::Iterator i = common_types.First();
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i.Good(); i.Inc()) {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string marker = GetSerializedProgressMarker(i.Get());
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string partner_marker =
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        partner->GetSerializedProgressMarker(i.Get());
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (marker != partner_marker) {
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (VLOG_IS_ON(2)) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string marker_base64, partner_marker_base64;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!base::Base64Encode(marker, &marker_base64)) {
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED();
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!base::Base64Encode(
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                partner_marker, &partner_marker_base64)) {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED();
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(2) << syncer::ModelTypeToString(i.Get()) << ": "
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << profile_debug_name_ << " progress marker = "
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << marker_base64 << ", "
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << partner->profile_debug_name_
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << " partner progress marker = "
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << partner_marker_base64;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncSessionSnapshot ProfileSyncServiceHarness::GetLastSessionSnapshot() const {
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(service_ != NULL) << "Sync service has not yet been set up.";
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service_->sync_initialized()) {
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return service_->GetLastSessionSnapshot();
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SyncSessionSnapshot();
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::EnableSyncForDatatype(
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType datatype) {
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString(
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "EnableSyncForDatatype("
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      + std::string(syncer::ModelTypeToString(datatype)) + ")");
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == SYNC_DISABLED) {
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SetupSync(syncer::ModelTypeSet(datatype));
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "EnableSyncForDatatype(): service() is null.";
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::ModelTypeSet synced_datatypes = service()->GetPreferredDataTypes();
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (synced_datatypes.Has(datatype)) {
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "EnableSyncForDatatype(): Sync already enabled for datatype "
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeToString(datatype)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " on " << profile_debug_name_ << ".";
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  synced_datatypes.Put(syncer::ModelTypeFromInt(datatype));
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->OnUserChoseDatatypes(false, synced_datatypes);
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (AwaitDataSyncCompletion("Datatype configuration.")) {
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "EnableSyncForDatatype(): Enabled sync for datatype "
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeToString(datatype)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " on " << profile_debug_name_ << ".";
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(0) << GetClientInfoString("EnableSyncForDatatype failed");
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::DisableSyncForDatatype(
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType datatype) {
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString(
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "DisableSyncForDatatype("
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      + std::string(syncer::ModelTypeToString(datatype)) + ")");
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "DisableSyncForDatatype(): service() is null.";
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::ModelTypeSet synced_datatypes = service()->GetPreferredDataTypes();
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!synced_datatypes.Has(datatype)) {
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "DisableSyncForDatatype(): Sync already disabled for datatype "
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeToString(datatype)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " on " << profile_debug_name_ << ".";
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  synced_datatypes.RetainAll(syncer::UserSelectableTypes());
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  synced_datatypes.Remove(datatype);
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->OnUserChoseDatatypes(false, synced_datatypes);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (AwaitFullSyncCompletion("Datatype reconfiguration.")) {
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "DisableSyncForDatatype(): Disabled sync for datatype "
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << syncer::ModelTypeToString(datatype)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " on " << profile_debug_name_ << ".";
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(0) << GetClientInfoString("DisableSyncForDatatype failed");
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::EnableSyncForAllDatatypes() {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("EnableSyncForAllDatatypes");
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_state_ == SYNC_DISABLED) {
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SetupSync();
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "EnableSyncForAllDatatypes(): service() is null.";
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->OnUserChoseDatatypes(true, syncer::ModelTypeSet::All());
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (AwaitFullSyncCompletion("Datatype reconfiguration.")) {
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "EnableSyncForAllDatatypes(): Enabled sync for all datatypes "
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << "on " << profile_debug_name_ << ".";
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(0) << GetClientInfoString("EnableSyncForAllDatatypes failed");
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::DisableSyncForAllDatatypes() {
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << GetClientInfoString("DisableSyncForAllDatatypes");
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service() == NULL) {
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "DisableSyncForAllDatatypes(): service() is null.";
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service()->DisableForUser();
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = SYNC_DISABLED;
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "DisableSyncForAllDatatypes(): Disabled sync for all "
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << "datatypes on " << profile_debug_name_;
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProfileSyncServiceHarness::GetSerializedProgressMarker(
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType model_type) const {
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::ProgressMarkerMap& markers_map =
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      snap.download_progress_markers();
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::ProgressMarkerMap::const_iterator it =
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      markers_map.find(model_type);
1047c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (it != markers_map.end()) ? it->second : std::string();
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProfileSyncServiceHarness::GetClientInfoString(
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& message) {
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::stringstream os;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os << profile_debug_name_ << ": " << message << ": ";
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service()) {
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProfileSyncService::Status& status = GetStatus();
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Capture select info from the sync session snapshot and syncer status.
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << ", has_unsynced_items: "
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << (service()->sync_initialized() ? service()->HasUnsyncedItems() : 0)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", did_commit: "
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << (snap.model_neutral_state().num_successful_commits == 0 &&
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           snap.model_neutral_state().commit_result == syncer::SYNCER_OK)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", encryption conflicts: "
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << snap.num_encryption_conflicts()
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", hierarchy conflicts: "
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << snap.num_hierarchy_conflicts()
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", server conflicts: "
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << snap.num_server_conflicts()
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", num_updates_downloaded : "
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << snap.model_neutral_state().num_updates_downloaded_total
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", passphrase_required_reason: "
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << syncer::PassphraseRequiredReasonToString(
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           service()->passphrase_required_reason())
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", notifications_enabled: "
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << status.notifications_enabled
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", service_is_pushing_changes: "
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ServiceIsPushingChanges()
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", has_pending_backend_migration: "
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << HasPendingBackendMigration();
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << "Sync service not available";
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return os.str();
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(zea): Rename this EnableEncryption, since we no longer turn on
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// encryption for individual types but for all.
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::EnableEncryptionForType(
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType type) {
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::ModelTypeSet encrypted_types =
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->GetEncryptedDataTypes();
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (encrypted_types.Has(type))
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_->EnableEncryptEverything();
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In order to kick off the encryption we have to reconfigure. Just grab the
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // currently synced types and use them.
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::ModelTypeSet synced_datatypes =
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->GetPreferredDataTypes();
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sync_everything =
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      synced_datatypes.Equals(syncer::ModelTypeSet::All());
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_->OnUserChoseDatatypes(sync_everything, synced_datatypes);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait some time to let the enryption finish.
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return WaitForTypeEncryption(type);
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::WaitForTypeEncryption(syncer::ModelType type) {
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The correctness of this if condition depends on the ordering of its
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sub-expressions.  See crbug.com/95619.
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(rlarocque): Figure out a less brittle way of detecting this.
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsTypeEncrypted(type) &&
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IsFullySynced() &&
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetLastSessionSnapshot().num_encryption_conflicts() == 0) {
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Encryption is already complete for |type|; do not wait.
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string reason = "Waiting for encryption.";
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_state_ = WAITING_FOR_ENCRYPTION;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  waiting_for_encryption_type_ = type;
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, reason)) {
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Did not receive EncryptionComplete notification after"
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << kLiveSyncOperationTimeoutMs / 1000
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " seconds.";
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsTypeEncrypted(type);
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::IsTypeEncrypted(syncer::ModelType type) {
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::ModelTypeSet encrypted_types =
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->GetEncryptedDataTypes();
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_type_encrypted = service_->GetEncryptedDataTypes().Has(type);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(2) << syncer::ModelTypeToString(type) << " is "
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << (is_type_encrypted ? "" : "not ") << "encrypted; "
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << "encrypted types = "
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << syncer::ModelTypeSetToString(encrypted_types);
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_type_encrypted;
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::IsTypeRunning(syncer::ModelType type) {
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_sync::DataTypeController::StateMap state_map;
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_->GetDataTypeControllerStates(&state_map);
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (state_map.count(type) != 0 &&
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          state_map[type] == browser_sync::DataTypeController::RUNNING);
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileSyncServiceHarness::IsTypePreferred(syncer::ModelType type) {
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return service_->GetPreferredDataTypes().Has(type);
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ProfileSyncServiceHarness::GetNumEntries() const {
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetLastSessionSnapshot().num_entries();
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ProfileSyncServiceHarness::GetNumDatatypes() const {
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_sync::DataTypeController::StateMap state_map;
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service_->GetDataTypeControllerStates(&state_map);
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state_map.size();
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ProfileSyncServiceHarness::GetServiceStatus() {
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DictionaryValue> value(
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_ui_util::ConstructAboutInformation(service_));
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string service_status;
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::JSONWriter::WriteWithOptions(value.get(),
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::JSONWriter::OPTIONS_PRETTY_PRINT,
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &service_status);
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return service_status;
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1172