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