| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_SYNC_SERVICE_IMPL_HARNESS_H_ |
| #define CHROME_BROWSER_SYNC_TEST_INTEGRATION_SYNC_SERVICE_IMPL_HARNESS_H_ |
| |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <vector> |
| |
| #include "base/functional/callback_forward.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/test/test_future.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/sync/test/integration/sync_test_account.h" |
| #include "components/sync/base/user_selectable_type.h" |
| #include "components/sync/engine/cycle/sync_cycle_snapshot.h" |
| #include "components/sync/service/local_data_description.h" |
| #include "components/sync/service/sync_service_impl.h" |
| #include "google_apis/gaia/gaia_id.h" |
| #include "third_party/abseil-cpp/absl/container/flat_hash_map.h" |
| |
| class Profile; |
| |
| namespace signin { |
| class GaiaIdHash; |
| } // namespace signin |
| |
| namespace syncer { |
| class SyncSetupInProgressHandle; |
| class SyncUserSettings; |
| } // namespace syncer |
| |
| class SyncSigninDelegate; |
| |
| // An instance of this class is basically our notion of a "sync client" for |
| // automation purposes. It harnesses the SyncServiceImpl member of the |
| // profile passed to it on construction and automates certain things like setup |
| // and authentication. It provides ways to "wait" adequate periods of time for |
| // several clients to get to the same state. |
| class SyncServiceImplHarness { |
| public: |
| // The type of profile signin method to authenticate a profile. |
| enum class SigninType { |
| // Fakes user signin process. |
| FAKE_SIGNIN, |
| // Uses UI signin flow and connects to GAIA servers for authentication. |
| UI_SIGNIN |
| }; |
| |
| using SetUserSettingsCallback = |
| base::OnceCallback<void(syncer::SyncUserSettings*)>; |
| |
| static std::unique_ptr<SyncServiceImplHarness> Create( |
| Profile* profile, |
| SigninType signin_type); |
| ~SyncServiceImplHarness(); |
| |
| SyncServiceImplHarness(const SyncServiceImplHarness&) = delete; |
| SyncServiceImplHarness& operator=(const SyncServiceImplHarness&) = delete; |
| |
| signin::GaiaIdHash GetGaiaIdHashForPrimaryAccount() const; |
| |
| // Returns GaiaId for `account`. This method can be used when the account is |
| // not signed in. |
| GaiaId GetGaiaIdForAccount(SyncTestAccount account) const; |
| |
| // Returns the email for `account`. This method can be used when the account |
| // is not signed in. |
| std::string GetEmailForAccount(SyncTestAccount account) const; |
| |
| // Signs in to a primary account without enabling sync the feature. |
| [[nodiscard]] bool SignInPrimaryAccount( |
| SyncTestAccount account = SyncTestAccount::kDefaultAccount); |
| |
| // This is similar to click the reset button on chrome.google.com/data. |
| [[nodiscard]] bool ResetSyncForPrimaryAccount(); |
| |
| #if !BUILDFLAG(IS_CHROMEOS) |
| // Signs out of the primary account. ChromeOS doesn't have the concept of |
| // sign-out, so this only exists on other platforms. |
| void SignOutPrimaryAccount(); |
| #endif // !BUILDFLAG(IS_CHROMEOS) |
| |
| // The underlying implementation for mimic-ing persistent auth errors isn't |
| // implemented on Android, see https://crbug.com/1373448. |
| #if !BUILDFLAG(IS_ANDROID) |
| // Enters/exits the "Sync paused" state, which in real life happens if a |
| // syncing user signs out of the content area. |
| // TODO(crbug.com/401470426): Replace the usages with |
| // Enter/ExitSignInPendingStateForPrimaryAccount(). |
| void EnterSyncPausedStateForPrimaryAccount(); |
| bool ExitSyncPausedStateForPrimaryAccount(); |
| |
| // Enters the "Sign-in pending" state and waits until the sync transport |
| // layer is paused. Returns true if successful. |
| bool EnterSignInPendingStateForPrimaryAccount(); |
| // Exits the "Sign-in pending" state and waits until the sync transport layer |
| // is active. Returns true if successful. |
| bool ExitSignInPendingStateForPrimaryAccount(); |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| // Enables and configures sync for all available datatypes. Returns true only |
| // after sync has been fully initialized and authenticated, and we are ready |
| // to process changes. |
| [[nodiscard]] bool SetupSync( |
| SyncTestAccount account = SyncTestAccount::kDefaultAccount); |
| |
| // Same as above but allows the modify sync settings (e.g. selected types) as |
| // part of the sync flow (advanced flow). |
| // `user_settings_callback` will be called once the engine is initialized, but |
| // before actually starting sync. Note that the caller is responsible for |
| // invoking `SetInitialSyncFeatureSetupComplete()`, if appropriate. |
| [[nodiscard]] bool SetupSyncWithCustomSettings( |
| SetUserSettingsCallback user_settings_callback, |
| SyncTestAccount account = SyncTestAccount::kDefaultAccount); |
| |
| // Enables and configures sync. |
| // Does not wait for sync to be ready to process changes -- callers need to |
| // ensure this by calling AwaitSyncSetupCompletion() or |
| // AwaitSyncTransportActive(). |
| [[nodiscard]] bool SetupSyncNoWaitForCompletion( |
| SyncTestAccount account = SyncTestAccount::kDefaultAccount); |
| |
| // Same as above but allows the modify sync settings (e.g. selected types) as |
| // part of the sync flow (advanced flow). |
| // `user_settings_callback` will be called once the engine is initialized, but |
| // before actually starting sync. Note that the caller is responsible for |
| // invoking `SetInitialSyncFeatureSetupComplete()`, if appropriate. |
| [[nodiscard]] bool SetupSyncWithCustomSettingsNoWaitForCompletion( |
| SetUserSettingsCallback user_settings_callback, |
| SyncTestAccount account = SyncTestAccount::kDefaultAccount); |
| |
| // Signals that sync setup is complete, and that PSS may begin syncing. |
| // Typically SetupSync does this automatically, but if that returned false, |
| // then setup may have been left incomplete. |
| void FinishSyncSetup(); |
| |
| // Calling this acts as a barrier and blocks the caller until `this` and |
| // `partner` have both completed a sync cycle. When calling this method, |
| // the `partner` should be the passive responder who responds to the actions |
| // of `this`. This method relies upon the synchronization of callbacks |
| // from the message queue. Returns true if two sync cycles have completed. |
| // Note: Use this method when exactly one client makes local change(s), and |
| // exactly one client is waiting to receive those changes. |
| [[nodiscard]] bool AwaitMutualSyncCycleCompletion( |
| SyncServiceImplHarness* partner); |
| |
| // Blocks the caller until every client in `clients` completes its ongoing |
| // sync cycle and all the clients' progress markers match. Note: Use this |
| // method when more than one client makes local change(s), and more than one |
| // client is waiting to receive those changes. |
| [[nodiscard]] static bool AwaitQuiescence( |
| const std::vector<SyncServiceImplHarness*>& clients); |
| |
| // Blocks the caller until the sync engine is initialized or some end state |
| // (e.g., auth error) is reached. Returns true only if the engine initialized |
| // successfully. See SyncService::IsEngineInitialized() for the definition |
| // of engine initialization. |
| [[nodiscard]] bool AwaitEngineInitialization(); |
| |
| // Blocks the caller until sync setup is complete, and sync-the-feature is |
| // active. Returns true if and only if sync setup completed successfully. Make |
| // sure to actually start sync setup (usually by calling SetupSync() or one of |
| // its variants) before. |
| [[nodiscard]] bool AwaitSyncSetupCompletion(); |
| |
| // Blocks the caller until the sync transport layer is active. Returns true if |
| // successful. |
| [[nodiscard]] bool AwaitSyncTransportActive(); |
| |
| // Blocks the caller until the sync transport layer is paused. Returns true if |
| // successful. |
| [[nodiscard]] bool AwaitSyncTransportPaused(); |
| |
| // Blocks the caller until invalidations are enabled or disabled. |
| [[nodiscard]] bool AwaitInvalidationsStatus(bool expected_status); |
| |
| // Returns the SyncServiceImpl member of the sync client. |
| syncer::SyncServiceImpl* service() { return service_; } |
| const syncer::SyncServiceImpl* service() const { return service_; } |
| |
| // Returns the debug name for this profile. Used for logging. |
| const std::string& profile_debug_name() const { return profile_debug_name_; } |
| |
| // Enables sync for a particular selectable sync type (will enable sync for |
| // all corresponding datatypes). Returns true on success. |
| [[nodiscard]] bool EnableSyncForType(syncer::UserSelectableType type); |
| |
| // Disables sync for a particular selectable sync type (will enable sync for |
| // all corresponding datatypes). Returns true on success. |
| [[nodiscard]] bool DisableSyncForType(syncer::UserSelectableType type); |
| |
| // Enables sync for all registered sync datatypes. Returns true on success. |
| [[nodiscard]] bool EnableSyncForRegisteredDatatypes(); |
| |
| // Disables sync for all sync datatypes. Returns true on success. |
| [[nodiscard]] bool DisableSyncForAllDatatypes(); |
| |
| // Returns a snapshot of the current sync session. |
| syncer::SyncCycleSnapshot GetLastCycleSnapshot() const; |
| |
| // Returns the datatypes which have local changes that have not yet been |
| // synced with the server. |
| absl::flat_hash_map<syncer::DataType, size_t> GetTypesWithUnsyncedDataAndWait( |
| syncer::DataTypeSet requested_types) const; |
| |
| // Retrieves the LocalDataDescription for the specified `data_type`. |
| // it assumes the service will provide a unique description for this specific |
| // type. Returns this description, or default value (empty value) if the |
| // service misbehaves and returns a response that cannot be interpreted. |
| syncer::LocalDataDescription GetLocalDataDescriptionAndWait( |
| syncer::DataType data_type); |
| |
| private: |
| // `profile` must not be null and must outlive `this`. `signin_delegate` must |
| // not be null. |
| SyncServiceImplHarness(Profile* profile, |
| std::unique_ptr<SyncSigninDelegate> signin_delegate); |
| |
| // Gets detailed status from `service_` in pretty-printable form. |
| std::string GetServiceStatus(); |
| |
| // Returns a string with relevant info about client's sync state (if |
| // available), annotated with `message`. Useful for logging. |
| std::string GetClientInfoString(const std::string& message) const; |
| |
| // Returns true if the user has enabled and configured sync for this client. |
| // Note that this does not imply sync is actually running. |
| bool IsSyncEnabledByUser() const; |
| |
| // Profile associated with this sync client. WeakPtr is used to allow |
| // flexibility in tests: this object may outlive `Profile` as long as it isn't |
| // exercised. |
| const base::WeakPtr<Profile> profile_; |
| |
| // SyncServiceImpl object associated with |profile_|. |
| const raw_ptr<syncer::SyncServiceImpl, AcrossTasksDanglingUntriaged> service_; |
| |
| // Prevents Sync from running until configuration is complete. |
| std::unique_ptr<syncer::SyncSetupInProgressHandle> sync_blocker_; |
| |
| // Used for logging. |
| const std::string profile_debug_name_; |
| |
| // Delegate to sign-in the test account across platforms. |
| const std::unique_ptr<SyncSigninDelegate> signin_delegate_; |
| }; |
| |
| #endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_SYNC_SERVICE_IMPL_HARNESS_H_ |