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