blob: 9f7c6127cf73981ce1ab355f23d79f84459d5897 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_IDENTITY_PUBLIC_CPP_IDENTITY_TEST_ENVIRONMENT_H_
#define SERVICES_IDENTITY_PUBLIC_CPP_IDENTITY_TEST_ENVIRONMENT_H_
#include "base/optional.h"
#include "components/signin/core/browser/account_consistency_method.h"
#include "services/identity/public/cpp/identity_manager.h"
#include "services/identity/public/cpp/identity_test_utils.h"
class AccountFetcherService;
class AccountTrackerService;
class FakeProfileOAuth2TokenService;
class IdentityTestEnvironmentChromeBrowserStateAdaptor;
class IdentityTestEnvironmentProfileAdaptor;
class PrefService;
class TestSigninClient;
namespace sync_preferences {
class TestingPrefServiceSyncable;
}
namespace network {
class TestURLLoaderFactory;
}
namespace identity {
class IdentityManagerDependenciesOwner;
class TestIdentityManagerObserver;
// Class that creates an IdentityManager for use in testing contexts and
// provides facilities for driving that IdentityManager. The IdentityManager
// instance is brought up in an environment where the primary account is
// not available; call MakePrimaryAccountAvailable() as needed.
// NOTE: IdentityTestEnvironment requires that tests have a properly set up
// task environment. If your test doesn't already have one, use a
// base::test::ScopedTaskEnvironment instance variable to fulfill this
// requirement.
class IdentityTestEnvironment : public IdentityManager::DiagnosticsObserver {
public:
// Preferred constructor: constructs an IdentityManager object and its
// dependencies internally. Cannot be used if the client of this class
// is still interacting directly with those dependencies (e.g., if
// IdentityTestEnvironment is being introduced to incrementally convert
// a test). In that case, use the below constructor and switch to this
// constructor once the conversion is complete.
//
// This constructor takes an optional parameter |test_url_loader_factory| to
// use for cookie-related network requests.
// Note: the provided |test_url_loader_factory| is expected to outlive
// IdentityTestEnvironment.
//
// This constructor also takes an optional PrefService instance as parameter,
// which allows tests to move away from referencing IdentityManager's
// dependencies directly (namely AccountTrackerService, PO2TS), but still be
// able to tweak preferences on demand.
//
// Last, this constructor can take an optional parameter |account_consistency|
// as parameter, to specify the account consistency policy that will be used.
IdentityTestEnvironment(
network::TestURLLoaderFactory* test_url_loader_factory = nullptr,
sync_preferences::TestingPrefServiceSyncable* pref_service = nullptr,
signin::AccountConsistencyMethod account_consistency =
signin::AccountConsistencyMethod::kDisabled,
TestSigninClient* test_signin_client = nullptr);
~IdentityTestEnvironment() override;
// The IdentityManager instance associated with this instance.
IdentityManager* identity_manager();
// Returns the FakeProfileOAuth2TokenService owned by IdentityManager.
FakeProfileOAuth2TokenService* fake_token_service();
// Returns the |TestIdentityManagerObserver| watching the IdentityManager.
TestIdentityManagerObserver* identity_manager_observer();
// Sets the primary account for the given email address, generating a GAIA ID
// that corresponds uniquely to that email address. On non-ChromeOS, results
// in the firing of the IdentityManager and SigninManager callbacks for signin
// success. Blocks until the primary account is set. Returns the
// CoreAccountInfo of the newly-set account.
CoreAccountInfo SetPrimaryAccount(const std::string& email);
// Sets a refresh token for the primary account (which must already be set).
// Before updating the refresh token, blocks until refresh tokens are loaded.
// After updating the token, blocks until the update is processed by
// |identity_manager|.
void SetRefreshTokenForPrimaryAccount();
// Sets a special invalid refresh token for the primary account (which must
// already be set). Before updating the refresh token, blocks until refresh
// tokens are loaded. After updating the token, blocks until the update is
// processed by |identity_manager|.
void SetInvalidRefreshTokenForPrimaryAccount();
// Removes any refresh token for the primary account, if present. Blocks until
// the refresh token is removed.
void RemoveRefreshTokenForPrimaryAccount();
// Makes the primary account available for the given email address, generating
// a GAIA ID and refresh token that correspond uniquely to that email address.
// On non-ChromeOS platforms, this will also result in the firing of the
// IdentityManager and SigninManager callbacks for signin success. On all
// platforms, this method blocks until the primary account is available.
// Returns the AccountInfo of the newly-available account.
AccountInfo MakePrimaryAccountAvailable(const std::string& email);
// Clears the primary account if present, with |policy| used to determine
// whether to keep or remove all accounts. On non-ChromeOS, results in the
// firing of the IdentityManager and SigninManager callbacks for signout.
// Blocks until the primary account is cleared.
void ClearPrimaryAccount(
ClearPrimaryAccountPolicy policy = ClearPrimaryAccountPolicy::DEFAULT);
// Makes an account available for the given email address, generating a GAIA
// ID and refresh token that correspond uniquely to that email address. Blocks
// until the account is available. Returns the AccountInfo of the
// newly-available account.
AccountInfo MakeAccountAvailable(const std::string& email);
// Sets a refresh token for the given account (which must already be
// available). Before updating the refresh token, blocks until refresh tokens
// are loaded. After updating the token, blocks until the update is processed
// by |identity_manager|. NOTE: See disclaimer at top of file re: direct
// usage.
void SetRefreshTokenForAccount(const std::string& account_id);
// Sets a special invalid refresh token for the given account (which must
// already be available). Before updating the refresh token, blocks until
// refresh tokens are loaded. After updating the token, blocks until the
// update is processed by |identity_manager|. NOTE: See disclaimer at top of
// file re: direct usage.
void SetInvalidRefreshTokenForAccount(const std::string& account_id);
// Removes any refresh token that is present for the given account. Blocks
// until the refresh token is removed.
// NOTE: See disclaimer at top of file re: direct usage.
void RemoveRefreshTokenForAccount(const std::string& account_id);
// Updates the persistent auth error set on |account_id| which must be a known
// account, i.e., an account with a refresh token.
void UpdatePersistentErrorOfRefreshTokenForAccount(
const std::string& account_id,
const GoogleServiceAuthError& auth_error);
// Puts the given accounts into the Gaia cookie, replacing any previous
// accounts. Blocks until the accounts have been set.
void SetCookieAccounts(const std::vector<CookieParams>& cookie_accounts);
// When this is set, access token requests will be automatically granted with
// an access token value of "access_token".
void SetAutomaticIssueOfAccessTokens(bool grant);
// Issues |token| in response to any access token request that either has (a)
// already occurred and has not been matched by a previous call to this or
// other WaitFor... method, or (b) will occur in the future. In the latter
// case, waits until the access token request occurs.
// |id_token| is an uncommonly-needed parameter that contains extra
// information regarding the user's currently-registered services; if this
// means nothing to you, you don't need to concern yourself with it.
// NOTE: This method behaves this way to allow IdentityTestEnvironment to be
// agnostic with respect to whether access token requests are handled
// synchronously or asynchronously in the production code.
// NOTE: This version is suitable for use in the common context where access
// token requests are only being made for one account. If you need to
// disambiguate requests coming for different accounts, see the version below.
void WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
const std::string& token,
const base::Time& expiration,
const std::string& id_token = std::string());
// Issues |token| in response to an access token request for |account_id| that
// either already occurred and has not been matched by a previous call to this
// or other WaitFor... method , or (b) will occur in the future. In the latter
// case, waits until the access token request occurs.
// |id_token| is an uncommonly-needed parameter that contains extra
// information regarding the user's currently-registered services; if this
// means nothing to you, you don't need to concern yourself with it.
// NOTE: This method behaves this way to allow
// IdentityTestEnvironment to be agnostic with respect to whether access token
// requests are handled synchronously or asynchronously in the production
// code.
void WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
const std::string& account_id,
const std::string& token,
const base::Time& expiration,
const std::string& id_token = std::string());
// Similar to WaitForAccessTokenRequestIfNecessaryAndRespondWithToken above
// apart from the fact that it issues tokens for a given set of scopes only,
// instead of issueing all tokens for all requests (the method variant above).
void WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForScopes(
const std::string& token,
const base::Time& expiration,
const std::string& id_token,
const identity::ScopeSet& scopes);
// Issues |error| in response to any access token request that either has (a)
// already occurred and has not been matched by a previous call to this or
// other WaitFor... method, or (b) will occur in the future. In the latter
// case, waits until the access token request occurs.
// NOTE: This method behaves this way to allow IdentityTestEnvironment to be
// agnostic with respect to whether access token requests are handled
// synchronously or asynchronously in the production code.
// NOTE: This version is suitable for use in the common context where access
// token requests are only being made for one account. If you need to
// disambiguate requests coming for different accounts, see the version below.
void WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
const GoogleServiceAuthError& error);
// Issues |error| in response to an access token request for |account_id| that
// either has (a) already occurred and has not been matched by a previous call
// to this or other WaitFor... method, or (b) will occur in the future. In the
// latter case, waits until the access token request occurs.
// NOTE: This method behaves this way to allow
// IdentityTestEnvironment to be agnostic with respect to whether access token
// requests are handled synchronously or asynchronously in the production
// code.
void WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
const std::string& account_id,
const GoogleServiceAuthError& error);
// Sets a callback that will be invoked on the next incoming access token
// request. Note that this can not be combined with the
// WaitForAccessTokenRequestIfNecessaryAndRespondWith* methods - you must
// either wait for the callback to get called, or explicitly reset it by
// passing in a null callback, before the Wait* methods can be used again.
void SetCallbackForNextAccessTokenRequest(base::OnceClosure callback);
// Updates the info for |account_info.account_id|, which must be a known
// account.
void UpdateAccountInfoForAccount(AccountInfo account_info);
// Resets to the state where accounts have not yet been loaded from disk.
void ResetToAccountsNotYetLoadedFromDiskState();
// Simulates the reloading of the accounts from disk.
void ReloadAccountsFromDisk();
// Returns whether there is a access token request pending.
bool IsAccessTokenRequestPending();
// Sets whether the list of accounts in Gaia cookie jar is fresh and does not
// need to be updated.
void SetFreshnessOfAccountsInGaiaCookie(bool accounts_are_fresh);
// By default, extended account info removal is disabled in testing
// contexts. This call enables it for tests that require
// IdentityManager::Observer::OnExtendedAccountInfoRemoved() to fire as
// expected. TODO(https://crbug.com/927687): Enable this unconditionally.
void EnableRemovalOfExtendedAccountInfo();
// Simulate account fetching using AccountTrackerService without sending
// network requests.
void SimulateSuccessfulFetchOfAccountInfo(const std::string& account_id,
const std::string& email,
const std::string& gaia,
const std::string& hosted_domain,
const std::string& full_name,
const std::string& given_name,
const std::string& locale,
const std::string& picture_url);
// Simulates a merge session failure with |auth_error| as the error.
void SimulateMergeSessionFailure(const GoogleServiceAuthError& auth_error);
private:
friend class ::IdentityTestEnvironmentChromeBrowserStateAdaptor;
friend class ::IdentityTestEnvironmentProfileAdaptor;
struct AccessTokenRequestState {
AccessTokenRequestState();
~AccessTokenRequestState();
AccessTokenRequestState(AccessTokenRequestState&& other);
AccessTokenRequestState& operator=(AccessTokenRequestState&& other);
enum {
kPending,
kAvailable,
} state;
base::Optional<std::string> account_id;
base::OnceClosure on_available;
};
// Constructor that takes in an IdentityManager instance as well as instances
// of the dependencies of that IdentityManager. For use only in contexts where
// IdentityManager and its dependencies are all unavoidably created by the
// embedder (e.g., //chrome-level unittests that use the
// ProfileKeyedServiceFactory infrastructure).
// When using this constructor, the invoker is responsible for ensuring the
// following:
// - That all of these objects outlive this object
// - That the dependencies being passed in were in fact the objects used to
// construct |identity_manager|
// - That the passed-in dependencies of |identity_manager| outlive it
// NOTE: This constructor is for usage only in the special case of embedder
// unittests that must use the IdentityManager instance associated with the
// Profile/ChromeBrowserState. If you think you have another use case for it,
// contact blundell@chromium.org.
IdentityTestEnvironment(
PrefService* pref_service,
AccountTrackerService* account_tracker_service,
AccountFetcherService* account_fetcher_service,
FakeProfileOAuth2TokenService* token_service,
IdentityManager* identity_manager,
network::TestURLLoaderFactory* test_url_loader_factory = nullptr,
signin::AccountConsistencyMethod account_consistency =
signin::AccountConsistencyMethod::kDisabled);
// Constructs this object from the supplied
// dependencies of IdentityManager and potentially IdentityManager itself.
// The supplied dependencies must be either:
// (1) non-null instances of the backing classes,
// (2) a non-null instance of |dependencies_owner|.
// In the case of (1), |identity_manager| can be non-null, in which case it
// must point to an object created via these dependencies. In the case of 2,
// |identity_manager| must be null. If |identity_manager| is non-null, it will
// be the IdentityManager instance associated with this object. Otherwise,
// this object will create and own an IdentityManager instance from the
// supplied dependencies.
IdentityTestEnvironment(
PrefService* pref_service,
AccountTrackerService* account_tracker_service,
AccountFetcherService* account_fetcher_service,
FakeProfileOAuth2TokenService* token_service,
network::TestURLLoaderFactory* test_url_loader_factory,
signin::AccountConsistencyMethod account_consistency,
std::unique_ptr<IdentityManagerDependenciesOwner> dependencies_owner,
IdentityManager* identity_manager);
// IdentityManager::DiagnosticsObserver:
void OnAccessTokenRequested(const std::string& account_id,
const std::string& consumer_id,
const identity::ScopeSet& scopes) override;
// Handles the notification that an access token request was received for
// |account_id|. Invokes |on_access_token_request_callback_| if the latter
// is non-null *and* either |*pending_access_token_requester_| equals
// |account_id| or |pending_access_token_requester_| is empty.
void HandleOnAccessTokenRequested(std::string account_id);
// If a token request for |account_id| (or any account if nullopt) has already
// been made and not matched by a different call, returns immediately.
// Otherwise and runs a nested runloop until a matching access token request
// is observed.
void WaitForAccessTokenRequestIfNecessary(
base::Optional<std::string> account_id);
// Owner of all dependencies that don't belong to IdentityManager.
std::unique_ptr<IdentityManagerDependenciesOwner> dependencies_owner_;
// Used to set fake responses for cookie-related requests.
// This can be null if no TestURLLoaderFactory was passed via the constructor.
network::TestURLLoaderFactory* test_url_loader_factory_ = nullptr;
// This will be null if a TestSigninClient was provided to
// IdentityTestEnvironment's constructor.
std::unique_ptr<TestSigninClient> owned_signin_client_;
// This will be null if a AccountTrackerService was provided to
// IdentityTestEnvironment's constructor.
std::unique_ptr<AccountTrackerService> owned_account_tracker_service_;
// This will be null if a AccountFetcherService was provided to
// IdentityTestEnvironment's constructor.
std::unique_ptr<AccountFetcherService> owned_account_fetcher_service_;
// This will be null if a FakeProfileOAuth2TokenService was provided to
// IdentityTestEnvironment's constructor.
std::unique_ptr<FakeProfileOAuth2TokenService> owned_token_service_;
// Depending on which constructor is used, exactly one of these will be
// non-null. See the documentation on the constructor wherein IdentityManager
// is passed in for required lifetime invariants in that case.
std::unique_ptr<IdentityManager> owned_identity_manager_;
IdentityManager* raw_identity_manager_ = nullptr;
std::unique_ptr<TestIdentityManagerObserver> test_identity_manager_observer_;
base::OnceClosure on_access_token_requested_callback_;
std::vector<AccessTokenRequestState> requesters_;
base::WeakPtrFactory<IdentityTestEnvironment> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(IdentityTestEnvironment);
};
} // namespace identity
#endif // SERVICES_IDENTITY_PUBLIC_CPP_IDENTITY_TEST_ENVIRONMENT_H_