1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 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 5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#ifndef CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_ 6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#define CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_ 7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#pragma once 8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <string> 10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <vector> 11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/basictypes.h" 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/sync/profile_sync_service.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/profile_sync_service_observer.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/syncable/model_type.h" 16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass Profile; 18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace browser_sync { 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen namespace sessions { 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct SyncSessionSnapshot; 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// An instance of this class is basically our notion of a "sync client" for 26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// automation purposes. It harnesses the ProfileSyncService member of the 27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// profile passed to it on construction and automates certain things like setup 28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// and authentication. It provides ways to "wait" adequate periods of time for 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// several clients to get to the same state. 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass ProfileSyncServiceHarness : public ProfileSyncServiceObserver { 31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ProfileSyncServiceHarness(Profile* profile, 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& username, 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& password, 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int id); 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual ~ProfileSyncServiceHarness() {} 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Creates a ProfileSyncServiceHarness object and attaches it to |profile|, a 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // profile that is assumed to have been signed into sync in the past. Caller 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // takes ownership. 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch static ProfileSyncServiceHarness* CreateAndAttach(Profile* profile); 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Sets the GAIA credentials with which to sign in to sync. 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void SetCredentials(const std::string& username, const std::string& password); 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Returns true if sync has been enabled on |profile_|. 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool IsSyncAlreadySetup(); 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Creates a ProfileSyncService for the profile passed at construction and 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // enables sync for all available datatypes. Returns true only after sync has 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // been fully initialized and authenticated, and we are ready to process 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // changes. 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool SetupSync(); 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Same as the above method, but enables sync only for the datatypes contained 57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // in |synced_datatypes|. 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool SetupSync(const syncable::ModelTypeSet& synced_datatypes); 59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // ProfileSyncServiceObserver implementation. 61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual void OnStateChanged(); 62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Blocks the caller until this harness has completed a single sync cycle 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // since the previous one. Returns true if a sync cycle has completed. 65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool AwaitSyncCycleCompletion(const std::string& reason); 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Blocks the caller until this harness has observed that the sync engine 683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // has downloaded all the changes seen by the |partner| harness's client. 693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool WaitUntilTimestampMatches( 703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ProfileSyncServiceHarness* partner, const std::string& reason); 71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Calling this acts as a barrier and blocks the caller until |this| and 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // |partner| have both completed a sync cycle. When calling this method, 74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // the |partner| should be the passive responder who responds to the actions 75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // of |this|. This method relies upon the synchronization of callbacks 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // from the message queue. Returns true if two sync cycles have completed. 77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Note: Use this method when exactly one client makes local change(s), and 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // exactly one client is waiting to receive those changes. 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool AwaitMutualSyncCycleCompletion(ProfileSyncServiceHarness* partner); 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Blocks the caller until |this| completes its ongoing sync cycle and every 823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // other client in |partners| have achieved identical download progresses. 833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Note: Use this method when exactly one client makes local change(s), 843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // and more than one client is waiting to receive those changes. 85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool AwaitGroupSyncCycleCompletion( 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<ProfileSyncServiceHarness*>& partners); 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Blocks the caller until every client in |clients| completes its ongoing 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // sync cycle and all the clients' timestamps match. Note: Use this method 90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // when more than one client makes local change(s), and more than one client 91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // is waiting to receive those changes. 92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch static bool AwaitQuiescence( 93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<ProfileSyncServiceHarness*>& clients); 94513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // If a SetPassphrase call has been issued with a valid passphrase, this 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // will wait until the passphrase has been accepted. 97513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool AwaitPassphraseAccepted(); 98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Returns the ProfileSyncService member of the the sync client. 100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ProfileSyncService* service() { return service_; } 101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Returns the status of the ProfileSyncService member of the the sync client. 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ProfileSyncService::Status GetStatus(); 104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // See ProfileSyncService::ShouldPushChanges(). 106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool ServiceIsPushingChanges() { return service_->ShouldPushChanges(); } 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Enables sync for a particular sync datatype. 109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void EnableSyncForDatatype(syncable::ModelType datatype); 110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Disables sync for a particular sync datatype. 112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void DisableSyncForDatatype(syncable::ModelType datatype); 113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Enables sync for all sync datatypes. 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void EnableSyncForAllDatatypes(); 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Disables sync for all sync datatypes. 118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void DisableSyncForAllDatatypes(); 119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Returns a snapshot of the current sync session. 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const browser_sync::sessions::SyncSessionSnapshot* 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetLastSessionSnapshot() const; 123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Encrypt the datatype |type|. This method will block while the sync backend 125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // host performs the encryption or a timeout is reached. Returns false if 126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // encryption failed, else true. 127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Note: this method does not currently support tracking encryption status 128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // while other sync activities are being performed. Sync should be fully 129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // synced when this is called. 130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool EnableEncryptionForType(syncable::ModelType type); 131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Check if |type| is encrypted. 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool IsTypeEncrypted(syncable::ModelType type); 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private: 136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch friend class StateChangeTimeoutEvent; 137513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch enum WaitState { 139513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The sync client has just been initialized. 140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch INITIAL_WAIT_STATE = 0, 141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The sync client awaits the OnBackendInitialized() callback. 143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch WAITING_FOR_ON_BACKEND_INITIALIZED, 144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The sync client is waiting for the first sync cycle to complete. 146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch WAITING_FOR_INITIAL_SYNC, 147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The sync client is waiting for an ongoing sync cycle to complete. 149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch WAITING_FOR_SYNC_TO_FINISH, 150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The sync client anticipates incoming updates leading to a new sync cycle. 152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch WAITING_FOR_UPDATES, 153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The sync client is waiting for its passphrase to be accepted by the 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // cryptographer. 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WAITING_FOR_PASSPHRASE_ACCEPTED, 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // The sync client anticipates encryption of new datatypes. 159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen WAITING_FOR_ENCRYPTION, 160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 161513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The sync client cannot reach the server. 162513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SERVER_UNREACHABLE, 163513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The sync client is fully synced and there are no pending updates. 165513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch FULLY_SYNCED, 166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 167513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Syncing is disabled for the client. 168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SYNC_DISABLED, 169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NUMBER_OF_STATES, 171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch }; 172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Called from the observer when the current wait state has been completed. 174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void SignalStateCompleteWithNextState(WaitState next_state); 175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Indicates that the operation being waited on is complete. 177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void SignalStateComplete(); 178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Finite state machine for controlling state. Returns true only if a state 180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // change has taken place. 181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool RunStateChangeMachine(); 182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Returns true if a status change took place, false on timeout. 184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool AwaitStatusChangeWithTimeout(int timeout_milliseconds, 185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& reason); 186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Returns true if the sync client has no unsynced items. 188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool IsSynced(); 189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Returns true if this client has downloaded all the items that the 1913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // other client has. 1923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool MatchesOtherClient(ProfileSyncServiceHarness* partner); 1933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 194513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Logs message with relevant info about client's sync state (if available). 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void LogClientInfo(const std::string& message); 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Gets the current progress indicator of the current sync session 19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // for a particular datatype. 19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string GetUpdatedTimestamp(syncable::ModelType model_type); 200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // When in WAITING_FOR_ENCRYPTION state, we check to see if this type is now 202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // encrypted to determine if we're done. 203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelType waiting_for_encryption_type_; 204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 205513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch WaitState wait_state_; 206513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Profile* profile_; 208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ProfileSyncService* service_; 209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 2103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // The harness of the client whose update progress marker we're expecting 2113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // eventually match. 2123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ProfileSyncServiceHarness* timestamp_match_partner_; 213513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 214513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Credentials used for GAIA authentication. 215513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string username_; 216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string password_; 217513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Client ID, used for logging purposes. 219513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int id_; 220513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 221513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceHarness); 222513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}; 223513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 224513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif // CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_HARNESS_H_ 225