profile_sync_service_harness.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file. 4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 53f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/browser/sync/profile_sync_service_harness.h" 63f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 73f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include <algorithm> 83f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include <vector> 93f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/message_loop.h" 11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/prefs/pref_service.h" 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/net/gaia/token_service.h" 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/sync/glue/sync_backend_host.h" 15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/sync/sessions/session_state.h" 164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/common/net/gaia/gaia_constants.h" 18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/common/net/gaia/google_service_auth_error.h" 194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/notification_source.h" 20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/common/pref_names.h" 21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// The default value for min_timestamp_needed_ when we're not in the 23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// WAITING_FOR_UPDATES state. 24513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstatic const int kMinTimestampNeededNone = -1; 25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// The amount of time for which we wait for a live sync operation to complete. 27513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstatic const int kLiveSyncOperationTimeoutMs = 30000; 28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Simple class to implement a timeout using PostDelayedTask. If it is not 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// aborted before picked up by a message queue, then it asserts with the message 31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// provided. This class is not thread safe. 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass StateChangeTimeoutEvent 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : public base::RefCountedThreadSafe<StateChangeTimeoutEvent> { 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch StateChangeTimeoutEvent(ProfileSyncServiceHarness* caller, 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& message); 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The entry point to the class from PostDelayedTask. 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void Callback(); 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Cancels the actions of the callback. Returns true if success, false 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // if the callback has already timed out. 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool Abort(); 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private: 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch friend class base::RefCountedThreadSafe<StateChangeTimeoutEvent>; 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ~StateChangeTimeoutEvent(); 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool aborted_; 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool did_timeout_; 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Due to synchronization of the IO loop, the caller will always be alive 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // if the class is not aborted. 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ProfileSyncServiceHarness* caller_; 56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Informative message to assert in the case of a timeout. 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string message_; 59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DISALLOW_COPY_AND_ASSIGN(StateChangeTimeoutEvent); 61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}; 62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 63513209b27ff55e2841eac0e4120199c23acce758Ben MurdochStateChangeTimeoutEvent::StateChangeTimeoutEvent( 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ProfileSyncServiceHarness* caller, 65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& message) 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : aborted_(false), did_timeout_(false), caller_(caller), message_(message) { 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 69513209b27ff55e2841eac0e4120199c23acce758Ben MurdochStateChangeTimeoutEvent::~StateChangeTimeoutEvent() { 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid StateChangeTimeoutEvent::Callback() { 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!aborted_) { 74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!caller_->RunStateChangeMachine()) { 75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Report the message. 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch did_timeout_ = true; 77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(!aborted_) << message_; 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch caller_->SignalStateComplete(); 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 83513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool StateChangeTimeoutEvent::Abort() { 84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch aborted_ = true; 85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch caller_ = NULL; 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return !did_timeout_; 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 89513209b27ff55e2841eac0e4120199c23acce758Ben MurdochProfileSyncServiceHarness::ProfileSyncServiceHarness( 90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Profile* profile, 91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& username, 92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& password, 93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int id) 94513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : wait_state_(INITIAL_WAIT_STATE), 95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch profile_(profile), 96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service_(NULL), 973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen timestamp_match_partner_(NULL), 98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch username_(username), 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch password_(password), 100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch id_(id) { 101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (IsSyncAlreadySetup()) { 102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service_ = profile_->GetProfileSyncService(); 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service_->AddObserver(this); 104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = FULLY_SYNCED; 105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 109513209b27ff55e2841eac0e4120199c23acce758Ben MurdochProfileSyncServiceHarness* ProfileSyncServiceHarness::CreateAndAttach( 110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Profile* profile) { 111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!profile->HasProfileSyncService()) { 112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NOTREACHED() << "Profile has never signed into sync."; 113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return NULL; 114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return new ProfileSyncServiceHarness(profile, "", "", 0); 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 118513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ProfileSyncServiceHarness::SetCredentials(const std::string& username, 119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& password) { 120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch username_ = username; 121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch password_ = password; 122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 124513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::IsSyncAlreadySetup() { 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return profile_->HasProfileSyncService(); 126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 128513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::SetupSync() { 129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch syncable::ModelTypeSet synced_datatypes; 130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (int i = syncable::FIRST_REAL_MODEL_TYPE; 131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch i < syncable::MODEL_TYPE_COUNT; ++i) { 132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch synced_datatypes.insert(syncable::ModelTypeFromInt(i)); 133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return SetupSync(synced_datatypes); 135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 137513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::SetupSync( 138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const syncable::ModelTypeSet& synced_datatypes) { 139513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Initialize the sync client's profile sync service object. 140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service_ = profile_->GetProfileSyncService(); 141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (service_ == NULL) { 142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LOG(ERROR) << "SetupSync(): service_ is null."; 143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Subscribe sync client to notifications from the profile sync service. 147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!service_->HasObserver(this)) 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service_->AddObserver(this); 149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Authenticate sync client using GAIA credentials. 151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service_->signin()->StartSignIn(username_, password_, "", ""); 152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Wait for the OnBackendInitialized() callback. 154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = WAITING_FOR_ON_BACKEND_INITIALIZED; 155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, 156513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "Waiting for OnBackendInitialized().")) { 157513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LOG(ERROR) << "OnBackendInitialized() not seen after " 158513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << kLiveSyncOperationTimeoutMs / 1000 159513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << " seconds."; 160513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 161513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 162513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 163513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Choose the datatypes to be synced. If all datatypes are to be synced, 164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // set sync_everything to true; otherwise, set it to false. 165513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool sync_everything = (synced_datatypes.size() == 166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (syncable::MODEL_TYPE_COUNT - syncable::FIRST_REAL_MODEL_TYPE)); 167513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service()->OnUserChoseDatatypes(sync_everything, synced_datatypes); 168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 169201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Wait for a passphrase to be required. 170201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_EQ(wait_state_, WAITING_FOR_PASSPHRASE_REQUIRED); 171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, 172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch "Waiting for Passphrase required.")) { 173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LOG(ERROR) << "Passphrase required not seen after " 174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << kLiveSyncOperationTimeoutMs / 1000 175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << " seconds."; 176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return false; 177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 179201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Wait for initial gaia passphrase to be accepted. 180201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_EQ(wait_state_, WAITING_FOR_PASSPHRASE_ACCEPTED); 181201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, 182201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch "Waiting for Passphrase accept.")) { 183201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LOG(ERROR) << "Passphrase accept not seen after " 184201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << kLiveSyncOperationTimeoutMs / 1000 185201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << " seconds."; 186201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return false; 187201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 188201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK_EQ(wait_state_, WAITING_FOR_INITIAL_SYNC); 190201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Wait for initial sync cycle to be completed. 191513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, 192513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "Waiting for initial sync cycle to complete.")) { 193513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LOG(ERROR) << "Initial sync cycle did not complete after " 194513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << kLiveSyncOperationTimeoutMs / 1000 195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << " seconds."; 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 199513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Indicate to the browser that sync setup is complete. 200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service()->SetSyncSetupCompleted(); 201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 202513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 203513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 204513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 205513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ProfileSyncServiceHarness::SignalStateCompleteWithNextState( 206513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch WaitState next_state) { 207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = next_state; 208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SignalStateComplete(); 209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 210513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 211513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ProfileSyncServiceHarness::SignalStateComplete() { 212513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch MessageLoop::current()->Quit(); 213513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 214513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 215513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::RunStateChangeMachine() { 216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch WaitState original_wait_state = wait_state_; 217513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch switch (wait_state_) { 218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case WAITING_FOR_ON_BACKEND_INITIALIZED: { 219513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("WAITING_FOR_ON_BACKEND_INITIALIZED"); 220513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (service()->sync_initialized()) { 22121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The sync backend is initialized. We now wait for passphrase events. 222201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SignalStateCompleteWithNextState(WAITING_FOR_PASSPHRASE_REQUIRED); 223513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 224513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 225513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch case WAITING_FOR_PASSPHRASE_REQUIRED: { 227201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LogClientInfo("WAITING_FOR_PASSPHRASE_REQUIRED"); 22821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (service()->observed_passphrase_required()) { 22921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Special case when the first client signs in to sync. 23021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (id_ == 0) 23121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(!service()->passphrase_required_for_decryption()); 23221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The SYNC_PASSPHRASE_REQUIRED notification has been seen. 233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SignalStateCompleteWithNextState(WAITING_FOR_PASSPHRASE_ACCEPTED); 23421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch break; 236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch case WAITING_FOR_PASSPHRASE_ACCEPTED: { 238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LogClientInfo("WAITING_FOR_PASSPHRASE_ACCEPTED"); 23921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (service()->ShouldPushChanges()) 24021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The SYNC_PASSPHRASE_ACCEPTED notification has been seen. 241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SignalStateCompleteWithNextState(WAITING_FOR_INITIAL_SYNC); 242201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch break; 243201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 244513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case WAITING_FOR_INITIAL_SYNC: { 245513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("WAITING_FOR_INITIAL_SYNC"); 246513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (IsSynced()) { 247513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The first sync cycle is now complete. We can start running tests. 248513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SignalStateCompleteWithNextState(FULLY_SYNCED); 249513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 250513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 251513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 252513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case WAITING_FOR_SYNC_TO_FINISH: { 253513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("WAITING_FOR_SYNC_TO_FINISH"); 254513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!IsSynced()) { 255513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The client is not yet fully synced. Continue waiting. 256513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!GetStatus().server_reachable) { 257513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The client cannot reach the sync server because the network is 258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // disabled. There is no need to wait anymore. 259513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SignalStateCompleteWithNextState(SERVER_UNREACHABLE); 260513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 261513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 262513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 263513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GetUpdatedTimestamp(); 264513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SignalStateCompleteWithNextState(FULLY_SYNCED); 265513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 266513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 267513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case WAITING_FOR_UPDATES: { 268513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("WAITING_FOR_UPDATES"); 2693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(timestamp_match_partner_); 2703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!MatchesOtherClient(timestamp_match_partner_)) { 2713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // The client is not yet fully synced; keep waiting until we converge. 272513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 273513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 2743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen timestamp_match_partner_->service()->RemoveObserver(this); 2753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen timestamp_match_partner_ = NULL; 2763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 277513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SignalStateCompleteWithNextState(FULLY_SYNCED); 278513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 279513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 280513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case SERVER_UNREACHABLE: { 281513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("SERVER_UNREACHABLE"); 282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (GetStatus().server_reachable) { 283513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The client was offline due to the network being disabled, but is now 284513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // back online. Wait for the pending sync cycle to complete. 285513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SignalStateCompleteWithNextState(WAITING_FOR_SYNC_TO_FINISH); 286513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 287513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 288513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 289513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case FULLY_SYNCED: { 290513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The client is online and fully synced. There is nothing to do. 291513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("FULLY_SYNCED"); 292513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 294513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case SYNC_DISABLED: { 295513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Syncing is disabled for the client. There is nothing to do. 296513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("SYNC_DISABLED"); 297513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 298513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 299513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch default: 300513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Invalid state during observer callback which may be triggered by other 301513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // classes using the the UI message loop. Defer to their handling. 302513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 303513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 304513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return original_wait_state != wait_state_; 305513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 306513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 307513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ProfileSyncServiceHarness::OnStateChanged() { 308513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch RunStateChangeMachine(); 309513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 310513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 311513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::AwaitPassphraseAccepted() { 312513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("AwaitPassphraseAccepted"); 313513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (wait_state_ == SYNC_DISABLED) { 314513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LOG(ERROR) << "Sync disabled for Client " << id_ << "."; 315513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 316513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 317513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = WAITING_FOR_PASSPHRASE_ACCEPTED; 318513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, 319513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "Waiting for passphrase accepted."); 320513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 321513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 322513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::AwaitSyncCycleCompletion( 323513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& reason) { 324513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("AwaitSyncCycleCompletion"); 325513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (wait_state_ == SYNC_DISABLED) { 326513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LOG(ERROR) << "Sync disabled for Client " << id_ << "."; 327513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 328513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 329513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!IsSynced()) { 330513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (wait_state_ == SERVER_UNREACHABLE) { 331513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Client was offline; wait for it to go online, and then wait for sync. 332513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, reason); 333513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK_EQ(wait_state_, WAITING_FOR_SYNC_TO_FINISH); 334513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, reason); 335513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 336513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(service()->sync_initialized()); 337513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = WAITING_FOR_SYNC_TO_FINISH; 338513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, reason); 339513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (wait_state_ == FULLY_SYNCED) { 340513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Client is online; sync was successful. 341513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 34221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } else if (wait_state_ == SERVER_UNREACHABLE) { 343513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Client is offline; sync was unsuccessful. 344513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 345513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 346513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LOG(ERROR) << "Invalid wait state:" << wait_state_; 347513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 348513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 349513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 350513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 351513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Client is already synced; don't wait. 352513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GetUpdatedTimestamp(); 353513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 354513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 355513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 356513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 357513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::AwaitMutualSyncCycleCompletion( 358513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ProfileSyncServiceHarness* partner) { 359513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("AwaitMutualSyncCycleCompletion"); 360513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!AwaitSyncCycleCompletion("Sync cycle completion on active client.")) 361513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 3623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return partner->WaitUntilTimestampMatches(this, 363513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "Sync cycle completion on passive client."); 364513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 365513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 366513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::AwaitGroupSyncCycleCompletion( 367513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<ProfileSyncServiceHarness*>& partners) { 368513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("AwaitGroupSyncCycleCompletion"); 369513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!AwaitSyncCycleCompletion("Sync cycle completion on active client.")) 370513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 371513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool return_value = true; 372513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (std::vector<ProfileSyncServiceHarness*>::iterator it = 373513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch partners.begin(); it != partners.end(); ++it) { 374513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if ((this != *it) && ((*it)->wait_state_ != SYNC_DISABLED)) { 375513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return_value = return_value && 3763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen (*it)->WaitUntilTimestampMatches(this, 377513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "Sync cycle completion on partner client."); 378513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 379513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 380513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return return_value; 381513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 382513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 383513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 384513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::AwaitQuiescence( 385513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<ProfileSyncServiceHarness*>& clients) { 386513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "AwaitQuiescence."; 387513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool return_value = true; 388513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (std::vector<ProfileSyncServiceHarness*>::iterator it = 389513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch clients.begin(); it != clients.end(); ++it) { 390513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if ((*it)->wait_state_ != SYNC_DISABLED) 391513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return_value = return_value && 392513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (*it)->AwaitGroupSyncCycleCompletion(clients); 393513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 394513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return return_value; 395513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 396513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 3973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool ProfileSyncServiceHarness::WaitUntilTimestampMatches( 3983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ProfileSyncServiceHarness* partner, const std::string& reason) { 3993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen LogClientInfo("WaitUntilTimestampMatches"); 400513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (wait_state_ == SYNC_DISABLED) { 401513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LOG(ERROR) << "Sync disabled for Client " << id_ << "."; 402513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 403513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 4043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(!timestamp_match_partner_); 4053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (MatchesOtherClient(partner)) 406513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 4073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 4083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen timestamp_match_partner_ = partner; 4093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen partner->service()->AddObserver(this); 4103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen wait_state_ = WAITING_FOR_UPDATES; 4113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, reason); 412513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 413513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 414513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::AwaitStatusChangeWithTimeout( 415513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int timeout_milliseconds, 416513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& reason) { 417513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("AwaitStatusChangeWithTimeout"); 418513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (wait_state_ == SYNC_DISABLED) { 419513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LOG(ERROR) << "Sync disabled for Client " << id_ << "."; 420513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 421513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 422513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<StateChangeTimeoutEvent> timeout_signal( 423513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new StateChangeTimeoutEvent(this, reason)); 424513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch MessageLoop* loop = MessageLoop::current(); 425513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool did_allow_nestable_tasks = loop->NestableTasksAllowed(); 426513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch loop->SetNestableTasksAllowed(true); 427513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch loop->PostDelayedTask( 428513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch FROM_HERE, 429513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NewRunnableMethod(timeout_signal.get(), 430513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch &StateChangeTimeoutEvent::Callback), 431513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch timeout_milliseconds); 432513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch loop->Run(); 433513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch loop->SetNestableTasksAllowed(did_allow_nestable_tasks); 4343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (timeout_signal->Abort()) { 4353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen LogClientInfo("AwaitStatusChangeWithTimeout succeeded"); 4363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return true; 4373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } else { 4383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen LogClientInfo("AwaitStatusChangeWithTimeout timed out"); 4393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 4403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 441513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 442513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 443513209b27ff55e2841eac0e4120199c23acce758Ben MurdochProfileSyncService::Status ProfileSyncServiceHarness::GetStatus() { 444513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(service() != NULL) << "GetStatus(): service() is NULL."; 445513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return service()->QueryDetailedSyncStatus(); 446513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 447513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 448513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ProfileSyncServiceHarness::IsSynced() { 449201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LogClientInfo("IsSynced"); 450513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (service() == NULL) 451513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 452513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const SyncSessionSnapshot* snap = GetLastSessionSnapshot(); 453513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // TODO(rsimha): Remove additional checks of snap->has_more_to_sync and 454513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // snap->unsynced_count once http://crbug.com/48989 is fixed. 455513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return (snap && 4564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch snap->num_conflicting_updates == 0 && // We can decrypt everything. 457513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ServiceIsPushingChanges() && 458513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GetStatus().notifications_enabled && 459513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch !service()->backend()->HasUnsyncedItems() && 460513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch !snap->has_more_to_sync && 461513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch snap->unsynced_count == 0); 462513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 463513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 4643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool ProfileSyncServiceHarness::MatchesOtherClient( 4653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ProfileSyncServiceHarness* partner) { 4663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!IsSynced()) 4673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 4683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 4693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Only look for a match if we have at least one enabled datatype in 4703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // common with the partner client. 4713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen syncable::ModelTypeSet types, other_types, intersection_types; 4723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen service()->GetPreferredDataTypes(&types); 4733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen partner->service()->GetPreferredDataTypes(&other_types); 4743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen std::set_intersection(types.begin(), types.end(), other_types.begin(), 4753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen other_types.end(), 4763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen inserter(intersection_types, 4773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen intersection_types.begin())); 4783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (intersection_types.empty()) { 4793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return true; 4803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 4813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return partner->IsSynced() && 4823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen partner->GetUpdatedTimestamp() == GetUpdatedTimestamp(); 4833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 4843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 485513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst SyncSessionSnapshot* 486513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ProfileSyncServiceHarness::GetLastSessionSnapshot() const { 487513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(service_ != NULL) << "Sync service has not yet been set up."; 488513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (service_->backend()) { 489513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return service_->backend()->GetLastSessionSnapshot(); 490513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 491513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return NULL; 492513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 493513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 494513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ProfileSyncServiceHarness::EnableSyncForDatatype( 495513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch syncable::ModelType datatype) { 496513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("EnableSyncForDatatype"); 497513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch syncable::ModelTypeSet synced_datatypes; 498513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (wait_state_ == SYNC_DISABLED) { 499513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = WAITING_FOR_ON_BACKEND_INITIALIZED; 500513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch synced_datatypes.insert(datatype); 501513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(SetupSync(synced_datatypes)) << "Reinitialization of Client " << id_ 502513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << " failed."; 503513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 504513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(service() != NULL) << "EnableSyncForDatatype(): service() is null."; 505513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service()->GetPreferredDataTypes(&synced_datatypes); 506513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch syncable::ModelTypeSet::iterator it = synced_datatypes.find( 507513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch syncable::ModelTypeFromInt(datatype)); 508513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (it == synced_datatypes.end()) { 509513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch synced_datatypes.insert(syncable::ModelTypeFromInt(datatype)); 510513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service()->OnUserChoseDatatypes(false, synced_datatypes); 511513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = WAITING_FOR_SYNC_TO_FINISH; 512513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AwaitSyncCycleCompletion("Waiting for datatype configuration."); 513513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "EnableSyncForDatatype(): Enabled sync for datatype " 514513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << syncable::ModelTypeToString(datatype) << " on Client " << id_; 515513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 516513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "EnableSyncForDatatype(): Sync already enabled for datatype " 517513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << syncable::ModelTypeToString(datatype) << " on Client " << id_; 518513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 519513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 520513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 521513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 522513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ProfileSyncServiceHarness::DisableSyncForDatatype( 523513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch syncable::ModelType datatype) { 524513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("DisableSyncForDatatype"); 525513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch syncable::ModelTypeSet synced_datatypes; 526513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(service() != NULL) << "DisableSyncForDatatype(): service() is null."; 527513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service()->GetPreferredDataTypes(&synced_datatypes); 528513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch syncable::ModelTypeSet::iterator it = synced_datatypes.find(datatype); 529513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (it != synced_datatypes.end()) { 530513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch synced_datatypes.erase(it); 531513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service()->OnUserChoseDatatypes(false, synced_datatypes); 532513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AwaitSyncCycleCompletion("Waiting for datatype configuration."); 533513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "DisableSyncForDatatype(): Disabled sync for datatype " 534513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << syncable::ModelTypeToString(datatype) << " on Client " << id_; 535513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 536513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "DisableSyncForDatatype(): Sync already disabled for datatype " 537513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << syncable::ModelTypeToString(datatype) << " on Client " << id_; 538513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 539513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 540513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 541513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ProfileSyncServiceHarness::EnableSyncForAllDatatypes() { 542513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("EnableSyncForAllDatatypes"); 543513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (wait_state_ == SYNC_DISABLED) { 544513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = WAITING_FOR_ON_BACKEND_INITIALIZED; 545513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(SetupSync()) << "Reinitialization of Client " << id_ << " failed."; 546513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 547513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch syncable::ModelTypeSet synced_datatypes; 548513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (int i = syncable::FIRST_REAL_MODEL_TYPE; 549513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch i < syncable::MODEL_TYPE_COUNT; ++i) { 550513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch synced_datatypes.insert(syncable::ModelTypeFromInt(i)); 551513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 552513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(service() != NULL) << "EnableSyncForAllDatatypes(): service() is " 553513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch " null."; 554513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service()->OnUserChoseDatatypes(true, synced_datatypes); 555513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = WAITING_FOR_SYNC_TO_FINISH; 556513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AwaitSyncCycleCompletion("Waiting for datatype configuration."); 557513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "EnableSyncForAllDatatypes(): Enabled sync for all datatypes on " 558513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "Client " << id_; 559513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 560513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 561513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 562513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ProfileSyncServiceHarness::DisableSyncForAllDatatypes() { 563513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch LogClientInfo("DisableSyncForAllDatatypes"); 564513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(service() != NULL) << "EnableSyncForAllDatatypes(): service() is " 565513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "null."; 566513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch service()->DisableForUser(); 567513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch wait_state_ = SYNC_DISABLED; 568513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "DisableSyncForAllDatatypes(): Disabled sync for all datatypes on " 569513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "Client " << id_; 570513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 571513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 572513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint64 ProfileSyncServiceHarness::GetUpdatedTimestamp() { 573513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const SyncSessionSnapshot* snap = GetLastSessionSnapshot(); 574513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(snap != NULL) << "GetUpdatedTimestamp(): Sync snapshot is NULL."; 5753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return snap->max_local_timestamp; 576513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 577513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 578513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid ProfileSyncServiceHarness::LogClientInfo(std::string message) { 579513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (service()) { 580513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const SyncSessionSnapshot* snap = GetLastSessionSnapshot(); 581513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (snap) { 582513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "Client " << id_ << ": " << message 583513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << ": max_local_timestamp: " << snap->max_local_timestamp 584513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << ", has_more_to_sync: " << snap->has_more_to_sync 585513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << ", unsynced_count: " << snap->unsynced_count 586201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << ", num_conflicting_updates: " << snap->num_conflicting_updates 587513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << ", has_unsynced_items: " 588513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << service()->backend()->HasUnsyncedItems() 589201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << ", observed_passphrase_required: " 590201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << service()->observed_passphrase_required() 591513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << ", notifications_enabled: " 592513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << GetStatus().notifications_enabled 593513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << ", service_is_pushing_changes: " << ServiceIsPushingChanges(); 594513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 595513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "Client " << id_ << ": " << message 596513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << ": Sync session snapshot not available."; 597513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 598513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 599513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "Client " << id_ << ": " << message 600513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << ": Sync service not available."; 601513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 602513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 603