blob: 161e0a312beee1e6e4ece7126424a02e70c227c5 [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_MANAGER_H_
#define SERVICES_IDENTITY_PUBLIC_CPP_IDENTITY_MANAGER_H_
#include "base/observer_list.h"
#include "components/signin/core/browser/account_info.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/gaia_cookie_manager_service.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_internals_util.h"
#include "components/signin/core/browser/signin_manager_base.h"
#include "components/signin/core/browser/signin_metrics.h"
#include "services/identity/public/cpp/access_token_fetcher.h"
#include "services/identity/public/cpp/accounts_mutator.h"
#include "services/identity/public/cpp/scope_set.h"
#if !defined(OS_CHROMEOS)
#include "components/signin/core/browser/signin_manager.h"
#endif
// Necessary to declare this class as a friend.
namespace arc {
class ArcTermsOfServiceDefaultNegotiatorTest;
}
// Necessary to declare these classes as friends.
namespace chromeos {
class ChromeSessionManager;
class UserSessionManager;
}
// Necessary to declare this class as a friend.
namespace file_manager {
class MultiProfileFilesAppBrowserTest;
}
namespace network {
class SharedURLLoaderFactory;
}
// Necessary to declare these classes as friends.
class ArcSupportHostTest;
class MultiProfileDownloadNotificationTest;
namespace identity {
class PrimaryAccountMutator;
enum class ClearPrimaryAccountPolicy;
// Gives access to information about the user's Google identities. See
// ./README.md for detailed documentation.
class IdentityManager : public SigninManagerBase::Observer,
public OAuth2TokenService::DiagnosticsObserver,
public OAuth2TokenService::Observer,
public GaiaCookieManagerService::Observer {
public:
class Observer {
public:
Observer() = default;
virtual ~Observer() = default;
Observer(const Observer&) = delete;
Observer& operator=(const Observer&) = delete;
// Called when an account becomes the user's primary account.
// This method is not called during a reauth.
virtual void OnPrimaryAccountSet(const AccountInfo& primary_account_info) {}
// Called when an account becomes the user's primary account using the
// legacy workflow (non-DICE). If access to the password is not required,
// it is preferred to instead override OnPrimaryAccountSet() which will
// also be called at the same time.
virtual void OnPrimaryAccountSetWithPassword(
const AccountInfo& primary_account_info,
const std::string& password) {}
// Called when when the user moves from having a primary account to no
// longer having a primary account.
virtual void OnPrimaryAccountCleared(
const AccountInfo& previous_primary_account_info) {}
// Called when the user attempts but fails to set their primary
// account. |error| gives the reason for the failure.
virtual void OnPrimaryAccountSigninFailed(
const GoogleServiceAuthError& error) {}
// Called when a new refresh token is associated with |account_info|.
// NOTE: On a signin event, the ordering of this callback wrt the
// OnPrimaryAccountSet() callback is undefined. If you as a client are
// interested in both callbacks, PrimaryAccountAccessTokenFetcher will
// likely meet your needs. Otherwise, if this lack of ordering is
// problematic for your use case, please contact blundell@chromium.org.
virtual void OnRefreshTokenUpdatedForAccount(
const AccountInfo& account_info) {}
// Called when the refresh token previously associated with |account_id|
// has been removed. At the time that this callback is invoked, there is
// no longer guaranteed to be any AccountInfo associated with
// |account_id|.
// NOTE: It is not guaranteed that a call to
// OnRefreshTokenUpdatedForAccount() has previously occurred for this
// account due to corner cases.
// TODO(https://crbug.com/884731): Eliminate these corner cases.
// NOTE: On a signout event, the ordering of this callback wrt the
// OnPrimaryAccountCleared() callback is undefined.If this lack of ordering
// is problematic for your use case, please contact blundell@chromium.org.
virtual void OnRefreshTokenRemovedForAccount(
const std::string& account_id) {}
// Called after refresh tokens are loaded.
// CAVEAT: On ChromeOS, this callback is not invoked during
// startup in all cases. See https://crbug.com/749535, which
// details the cases where it's not invoked.
virtual void OnRefreshTokensLoaded() {}
// Called whenever the list of Gaia accounts in the cookie jar has changed.
// |accounts| is ordered by the order of the accounts in the cookie.
virtual void OnAccountsInCookieUpdated(
const std::vector<AccountInfo>& accounts) {}
// Called whenever an attempt to add |account_id| to the list of Gaia
// accounts in the cookie jar has finished. If |error| is equal to
// GoogleServiceAuthError::AuthErrorNone() then the addittion succeeded.
virtual void OnAddAccountToCookieCompleted(
const std::string& account_id,
const GoogleServiceAuthError& error) {}
// Called before a batch of refresh token state changes is started.
virtual void OnStartBatchOfRefreshTokenStateChanges() {}
// Called after a batch of refresh token state chagnes is completed.
virtual void OnEndBatchOfRefreshTokenStateChanges() {}
};
// Observer interface for classes that want to monitor status of various
// requests. Mostly useful in tests and debugging contexts (e.g., WebUI).
class DiagnosticsObserver {
public:
DiagnosticsObserver() = default;
virtual ~DiagnosticsObserver() = default;
DiagnosticsObserver(const DiagnosticsObserver&) = delete;
DiagnosticsObserver& operator=(const DiagnosticsObserver&) = delete;
// Called when receiving request for access token.
virtual void OnAccessTokenRequested(const std::string& account_id,
const std::string& consumer_id,
const identity::ScopeSet& scopes) {}
};
IdentityManager(
SigninManagerBase* signin_manager,
ProfileOAuth2TokenService* token_service,
AccountTrackerService* account_tracker_service,
GaiaCookieManagerService* gaia_cookie_manager_service,
std::unique_ptr<PrimaryAccountMutator> primary_account_mutator);
~IdentityManager() override;
// Provides access to the extended information of the user's primary account.
// Returns an empty struct if no such info is available, either because there
// is no primary account or because the extended information for the primary
// account has been removed (this happens when the refresh token is revoked,
// for example).
AccountInfo GetPrimaryAccountInfo() const;
// Provides access to the account ID of the user's primary account. Note that
// this may return a valid string even in cases where GetPrimaryAccountInfo()
// returns an empty struct, as the extended information for the primary
// account is removed on certain events (e.g., when its refresh token is
// revoked).
const std::string& GetPrimaryAccountId() const;
// Returns whether the primary account is available. Simple convenience
// wrapper over checking whether GetPrimaryAccountId() returns a non-empty
// string.
bool HasPrimaryAccount() const;
// Provides access to the latest cached information of all accounts that have
// refresh tokens.
// NOTE: The accounts should not be assumed to be in any particular order; in
// particular, they are not guaranteed to be in the order in which the
// refresh tokens were added.
std::vector<AccountInfo> GetAccountsWithRefreshTokens() const;
// Provides access to the latest cached information of all accounts that are
// present in the Gaia cookie in the cookie jar, ordered by their order in
// the cookie. If the cached state is known to be stale by the underlying
// implementation, a call to this method will trigger an internal update and
// subsequent invocation of
// IdentityManager::Observer::OnAccountsInCookieJarChanged().
// NOTE: The information of whether the cached state is known to be stale by
// the underlying implementation is not currently exposed. The design for
// exposing it if necessary is tracked by https://crbug.com/859882. If the
// lack of this exposure is a blocker for you in using this API, contact
// blundell@chromium.org.
std::vector<AccountInfo> GetAccountsInCookieJar() const;
// Returns true if a refresh token exists for |account_id|.
bool HasAccountWithRefreshToken(const std::string& account_id) const;
// Returns true if (a) a refresh token exists for |account_id|, and (b) the
// refresh token is in a persistent error state (defined as
// GoogleServiceAuthError::IsPersistentError() returning true for the error
// returned by GetErrorStateOfRefreshTokenForAccount(account_id)).
bool HasAccountWithRefreshTokenInPersistentErrorState(
const std::string& account_id) const;
// Returns the error state of the refresh token associated with |account_id|.
// In particular: Returns GoogleServiceAuthError::AuthErrorNone() if either
// (a) no refresh token exists for |account_id|, or (b) the refresh token is
// not in a persistent error state. Otherwise, returns the last persistent
// error that was detected when using the refresh token.
GoogleServiceAuthError GetErrorStateOfRefreshTokenForAccount(
const std::string& account_id) const;
// Returns true if (a) the primary account exists, and (b) a refresh token
// exists for the primary account.
bool HasPrimaryAccountWithRefreshToken() const;
// Looks up and returns information for account with given |account_id|. If
// the account cannot be found, return an empty optional. This is equivalent
// to searching on the vector returned by GetAccountsWithRefreshTokens() but
// without allocating memory for the vector.
base::Optional<AccountInfo>
FindAccountInfoForAccountWithRefreshTokenByAccountId(
const std::string& account_id) const;
// Looks up and returns information for account with given |email_address|. If
// the account cannot be found, return an empty optional. This is equivalent
// to searching on the vector returned by GetAccountsWithRefreshTokens() but
// without allocating memory for the vector.
base::Optional<AccountInfo>
FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
const std::string& email_address) const;
// Looks up and returns information for account with given |gaia_id|. If the
// account cannot be found, return an empty optional. This is equivalent to
// searching on the vector returned by GetAccountsWithRefreshTokens() but
// without allocating memory for the vector.
base::Optional<AccountInfo> FindAccountInfoForAccountWithRefreshTokenByGaiaId(
const std::string& gaia_id) const;
// Creates an AccessTokenFetcher given the passed-in information.
std::unique_ptr<AccessTokenFetcher> CreateAccessTokenFetcherForAccount(
const std::string& account_id,
const std::string& oauth_consumer_name,
const identity::ScopeSet& scopes,
AccessTokenFetcher::TokenCallback callback,
AccessTokenFetcher::Mode mode);
// Creates an AccessTokenFetcher given the passed-in information, allowing
// to specify a custom |url_loader_factory| as well.
std::unique_ptr<AccessTokenFetcher> CreateAccessTokenFetcherForAccount(
const std::string& account_id,
const std::string& oauth_consumer_name,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const identity::ScopeSet& scopes,
AccessTokenFetcher::TokenCallback callback,
AccessTokenFetcher::Mode mode);
// If an entry exists in the Identity Service's cache corresponding to the
// given information, removes that entry; in this case, the next access token
// request for |account_id| and |scopes| will fetch a new token from the
// network. Otherwise, is a no-op.
void RemoveAccessTokenFromCache(const std::string& account_id,
const identity::ScopeSet& scopes,
const std::string& access_token);
// Returns pointer to the object used to change the signed-in state of the
// primary account, if supported on the current platform. Otherwise, returns
// null.
PrimaryAccountMutator* GetPrimaryAccountMutator();
// Returns pointer to the object used to seed accounts and mutate state of
// accounts' refresh tokens. Guaranteed to be non-null.
AccountsMutator* GetAccountsMutator();
// Methods to register or remove observers.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
void AddDiagnosticsObserver(DiagnosticsObserver* observer);
void RemoveDiagnosticsObserver(DiagnosticsObserver* observer);
private:
// These test helpers need to use some of the private methods below.
friend AccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
const std::string& email);
friend void SetRefreshTokenForPrimaryAccount(
IdentityManager* identity_manager,
const std::string& token_value);
friend void SetInvalidRefreshTokenForPrimaryAccount(
IdentityManager* identity_manager);
friend void RemoveRefreshTokenForPrimaryAccount(
IdentityManager* identity_manager);
friend AccountInfo MakePrimaryAccountAvailable(
IdentityManager* identity_manager,
const std::string& email);
friend void ClearPrimaryAccount(IdentityManager* identity_manager,
ClearPrimaryAccountPolicy policy);
friend AccountInfo MakeAccountAvailable(IdentityManager* identity_manager,
const std::string& email);
friend void SetRefreshTokenForAccount(IdentityManager* identity_manager,
const std::string& account_id,
const std::string& token_value);
friend void SetInvalidRefreshTokenForAccount(
IdentityManager* identity_manager,
const std::string& account_id);
friend void RemoveRefreshTokenForAccount(IdentityManager* identity_manager,
const std::string& account_id);
friend void UpdateAccountInfoForAccount(IdentityManager* identity_manager,
AccountInfo account_info);
friend void UpdatePersistentErrorOfRefreshTokenForAccount(
IdentityManager* identity_manager,
const std::string& account_id,
const GoogleServiceAuthError& auth_error);
friend MultiProfileDownloadNotificationTest;
friend file_manager::MultiProfileFilesAppBrowserTest;
// These clients needs to call SetPrimaryAccountSynchronously().
friend ArcSupportHostTest;
friend arc::ArcTermsOfServiceDefaultNegotiatorTest;
friend chromeos::ChromeSessionManager;
friend chromeos::UserSessionManager;
// Private getters used for testing only (i.e. see identity_test_utils.h).
SigninManagerBase* GetSigninManager();
ProfileOAuth2TokenService* GetTokenService();
AccountTrackerService* GetAccountTrackerService();
// Sets the primary account info synchronously with both the IdentityManager
// and its backing SigninManager/ProfileOAuth2TokenService instances.
// Prefer using the methods in identity_test_{environment, utils}.h to using
// this method directly.
void SetPrimaryAccountSynchronouslyForTests(const std::string& gaia_id,
const std::string& email_address,
const std::string& refresh_token);
// Sets the primary account info synchronously with both the IdentityManager
// and its backing SigninManager instance. If |refresh_token| is not empty,
// sets the refresh token with the backing ProfileOAuth2TokenService
// instance. This method should not be used directly; it exists only to serve
// one legacy use case at this point.
// TODO(https://crbug.com/814787): Eliminate the need for this method.
void SetPrimaryAccountSynchronously(const std::string& gaia_id,
const std::string& email_address,
const std::string& refresh_token);
// Populates and returns an AccountInfo object corresponding to |account_id|,
// which must be an account with a refresh token.
AccountInfo GetAccountInfoForAccountWithRefreshToken(
const std::string& account_id) const;
// SigninManagerBase::Observer:
void GoogleSigninSucceeded(const AccountInfo& account_info) override;
void GoogleSigninSucceededWithPassword(const AccountInfo& account_info,
const std::string& password) override;
void GoogleSignedOut(const AccountInfo& account_info) override;
void GoogleSigninFailed(const GoogleServiceAuthError& error) override;
// OAuth2TokenService::Observer:
void OnRefreshTokenAvailable(const std::string& account_id) override;
void OnRefreshTokenRevoked(const std::string& account_id) override;
void OnRefreshTokensLoaded() override;
void OnStartBatchChanges() override;
void OnEndBatchChanges() override;
// GaiaCookieManagerService::Observer:
void OnGaiaAccountsInCookieUpdated(
const std::vector<gaia::ListedAccount>& accounts,
const std::vector<gaia::ListedAccount>& signed_out_accounts,
const GoogleServiceAuthError& error) override;
void OnAddAccountToCookieCompleted(
const std::string& account_id,
const GoogleServiceAuthError& error) override;
// OAuth2TokenService::DiagnosticsObserver:
void OnAccessTokenRequested(
const std::string& account_id,
const std::string& consumer_id,
const OAuth2TokenService::ScopeSet& scopes) override;
// Backing signin classes. NOTE: We strive to limit synchronous access to
// these classes in the IdentityManager implementation, as all such
// synchronous access will become impossible when IdentityManager is
// backed by the Identity Service.
SigninManagerBase* signin_manager_;
ProfileOAuth2TokenService* token_service_;
AccountTrackerService* account_tracker_service_;
GaiaCookieManagerService* gaia_cookie_manager_service_;
// PrimaryAccountMutator instance. May be null if mutation of the primary
// account state is not supported on the current platform.
std::unique_ptr<PrimaryAccountMutator> primary_account_mutator_;
// AccountsMutator instance. Guaranteed to be non-null, as this
// functionality is supported on all platforms.
AccountsMutator accounts_mutator_;
// Lists of observers.
// Makes sure lists are empty on destruction.
base::ObserverList<Observer, true>::Unchecked observer_list_;
base::ObserverList<DiagnosticsObserver, true>::Unchecked
diagnostics_observer_list_;
DISALLOW_COPY_AND_ASSIGN(IdentityManager);
};
} // namespace identity
#endif // SERVICES_IDENTITY_PUBLIC_CPP_IDENTITY_MANAGER_H_