| // 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. |
| |
| #include "components/signin/public/identity_manager/identity_manager.h" |
| |
| #include <string> |
| |
| #include "base/bind.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| #include "components/signin/internal/identity_manager/account_fetcher_service.h" |
| #include "components/signin/internal/identity_manager/account_tracker_service.h" |
| #include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h" |
| #include "components/signin/internal/identity_manager/ubertoken_fetcher_impl.h" |
| #include "components/signin/public/base/signin_buildflags.h" |
| #include "components/signin/public/base/signin_client.h" |
| #include "components/signin/public/identity_manager/accounts_cookie_mutator.h" |
| #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h" |
| #include "components/signin/public/identity_manager/accounts_mutator.h" |
| #include "components/signin/public/identity_manager/device_accounts_synchronizer.h" |
| #include "components/signin/public/identity_manager/diagnostics_provider.h" |
| #include "components/signin/public/identity_manager/primary_account_mutator.h" |
| #include "services/network/public/cpp/shared_url_loader_factory.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| #if defined(OS_ANDROID) |
| #include "base/android/jni_string.h" |
| #include "base/metrics/histogram_functions.h" |
| #include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h" |
| #include "components/signin/public/android/jni_headers/IdentityManager_jni.h" |
| #endif |
| |
| #if BUILDFLAG(ENABLE_DICE_SUPPORT) |
| #include "components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h" |
| #endif |
| |
| #if BUILDFLAG(IS_CHROMEOS_LACROS) |
| #include "components/account_manager_core/account.h" |
| #include "components/signin/public/base/signin_switches.h" |
| #endif |
| |
| namespace signin { |
| |
| namespace { |
| |
| #if BUILDFLAG(IS_CHROMEOS_LACROS) |
| void SetPrimaryAccount(IdentityManager* identity_manager, |
| AccountTrackerService* account_tracker_service, |
| SigninClient* signin_client, |
| const account_manager::Account& device_account) { |
| if (device_account.key.account_type != account_manager::AccountType::kGaia) |
| return; |
| |
| // An account can be set as the Primary Account only if it exists in |
| // `AccountTrackerService`. However, for the first run, when accounts have not |
| // yet been received from `AccountManagerFacade`, entities can ask about the |
| // Primary Account and expect it to be available pretty early. Manually seed |
| // the account in `AccountTrackerService` to get around this issue. |
| const CoreAccountId account_id = account_tracker_service->SeedAccountInfo( |
| /*gaia=*/device_account.key.id, device_account.raw_email); |
| // TODO(https://crbug.com/1194983): Figure out how split sync settings will |
| // work here. For now, we will mimic Ash's behaviour of having sync turned on |
| // by default. |
| identity_manager->GetPrimaryAccountMutator()->SetPrimaryAccount( |
| account_id, ConsentLevel::kSync); |
| |
| CHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSync)); |
| CHECK_EQ(identity_manager->GetPrimaryAccountInfo(ConsentLevel::kSync).gaia, |
| device_account.key.id); |
| } |
| #endif |
| |
| } // namespace |
| |
| IdentityManager::InitParameters::InitParameters() = default; |
| |
| IdentityManager::InitParameters::InitParameters(InitParameters&&) = default; |
| |
| IdentityManager::InitParameters::~InitParameters() = default; |
| |
| IdentityManager::IdentityManager(IdentityManager::InitParameters&& parameters) |
| : account_tracker_service_(std::move(parameters.account_tracker_service)), |
| token_service_(std::move(parameters.token_service)), |
| gaia_cookie_manager_service_( |
| std::move(parameters.gaia_cookie_manager_service)), |
| primary_account_manager_(std::move(parameters.primary_account_manager)), |
| account_fetcher_service_(std::move(parameters.account_fetcher_service)), |
| #if BUILDFLAG(IS_CHROMEOS_LACROS) |
| signin_client_(parameters.signin_client), |
| #endif |
| identity_mutator_(std::move(parameters.primary_account_mutator), |
| std::move(parameters.accounts_mutator), |
| std::move(parameters.accounts_cookie_mutator), |
| std::move(parameters.device_accounts_synchronizer)), |
| diagnostics_provider_(std::move(parameters.diagnostics_provider)) { |
| DCHECK(account_fetcher_service_); |
| DCHECK(diagnostics_provider_); |
| |
| primary_account_manager_observation_.Observe(primary_account_manager_.get()); |
| token_service_observation_.Observe(token_service_.get()); |
| token_service_->AddAccessTokenDiagnosticsObserver(this); |
| |
| // IdentityManager owns the ATS, GCMS and PO2TS instances and will outlive |
| // them, so base::Unretained is safe. |
| account_tracker_service_->SetOnAccountUpdatedCallback(base::BindRepeating( |
| &IdentityManager::OnAccountUpdated, base::Unretained(this))); |
| account_tracker_service_->SetOnAccountRemovedCallback(base::BindRepeating( |
| &IdentityManager::OnAccountRemoved, base::Unretained(this))); |
| gaia_cookie_manager_service_->SetGaiaAccountsInCookieUpdatedCallback( |
| base::BindRepeating(&IdentityManager::OnGaiaAccountsInCookieUpdated, |
| base::Unretained(this))); |
| gaia_cookie_manager_service_->SetGaiaCookieDeletedByUserActionCallback( |
| base::BindRepeating(&IdentityManager::OnGaiaCookieDeletedByUserAction, |
| base::Unretained(this))); |
| token_service_->SetRefreshTokenAvailableFromSourceCallback( |
| base::BindRepeating(&IdentityManager::OnRefreshTokenAvailableFromSource, |
| base::Unretained(this))); |
| token_service_->SetRefreshTokenRevokedFromSourceCallback( |
| base::BindRepeating(&IdentityManager::OnRefreshTokenRevokedFromSource, |
| base::Unretained(this))); |
| |
| #if defined(OS_ANDROID) |
| java_identity_manager_ = Java_IdentityManager_create( |
| base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this), |
| token_service_->GetDelegate()->GetJavaObject()); |
| #endif |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| ash_account_manager_ = parameters.ash_account_manager; |
| #endif |
| |
| #if BUILDFLAG(IS_CHROMEOS_LACROS) |
| // We need to set the Primary Account in Lacros. In Ash, this happens in |
| // `UserSessionManager::InitProfilePreferences`, before anyone starts using |
| // Profile / KeyedServices - but with the availability of IdentityManager. We |
| // don't have such a place in Lacros - which guarantees that the Primary |
| // Account will be available on startup - just like Ash. |
| absl::optional<account_manager::Account> initial_account = |
| signin_client_->GetInitialPrimaryAccount(); |
| if (initial_account.has_value()) { |
| SetPrimaryAccount(this, account_tracker_service_.get(), signin_client_, |
| initial_account.value()); |
| } |
| #endif |
| } |
| |
| IdentityManager::~IdentityManager() { |
| #if defined(OS_ANDROID) |
| if (java_identity_manager_) |
| Java_IdentityManager_destroy(base::android::AttachCurrentThread(), |
| java_identity_manager_); |
| #endif |
| } |
| |
| void IdentityManager::Shutdown() { |
| for (auto& observer : observer_list_) |
| observer.OnIdentityManagerShutdown(this); |
| |
| // It is no longer safe to use the SigninClient beyond this point, everything |
| // depending on it must be destroyed. |
| token_service_->RemoveAccessTokenDiagnosticsObserver(this); |
| token_service_observation_.Reset(); |
| primary_account_manager_observation_.Reset(); |
| |
| account_fetcher_service_.reset(); |
| gaia_cookie_manager_service_.reset(); |
| primary_account_manager_.reset(); |
| token_service_.reset(); |
| account_tracker_service_.reset(); |
| } |
| |
| void IdentityManager::AddObserver(Observer* observer) { |
| observer_list_.AddObserver(observer); |
| } |
| |
| void IdentityManager::RemoveObserver(Observer* observer) { |
| observer_list_.RemoveObserver(observer); |
| } |
| |
| // TODO(862619) change return type to absl::optional<CoreAccountInfo> |
| CoreAccountInfo IdentityManager::GetPrimaryAccountInfo( |
| ConsentLevel consent) const { |
| return primary_account_manager_->GetPrimaryAccountInfo(consent); |
| } |
| |
| CoreAccountId IdentityManager::GetPrimaryAccountId(ConsentLevel consent) const { |
| return GetPrimaryAccountInfo(consent).account_id; |
| } |
| |
| bool IdentityManager::HasPrimaryAccount(ConsentLevel consent) const { |
| return primary_account_manager_->HasPrimaryAccount(consent); |
| } |
| |
| std::unique_ptr<AccessTokenFetcher> |
| IdentityManager::CreateAccessTokenFetcherForAccount( |
| const CoreAccountId& account_id, |
| const std::string& oauth_consumer_name, |
| const ScopeSet& scopes, |
| AccessTokenFetcher::TokenCallback callback, |
| AccessTokenFetcher::Mode mode) { |
| return std::make_unique<AccessTokenFetcher>( |
| account_id, oauth_consumer_name, token_service_.get(), |
| primary_account_manager_.get(), scopes, std::move(callback), mode); |
| } |
| |
| std::unique_ptr<AccessTokenFetcher> |
| IdentityManager::CreateAccessTokenFetcherForAccount( |
| const CoreAccountId& account_id, |
| const std::string& oauth_consumer_name, |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| const ScopeSet& scopes, |
| AccessTokenFetcher::TokenCallback callback, |
| AccessTokenFetcher::Mode mode) { |
| return std::make_unique<AccessTokenFetcher>( |
| account_id, oauth_consumer_name, token_service_.get(), |
| primary_account_manager_.get(), url_loader_factory, scopes, |
| std::move(callback), mode); |
| } |
| |
| std::unique_ptr<AccessTokenFetcher> |
| IdentityManager::CreateAccessTokenFetcherForClient( |
| const CoreAccountId& account_id, |
| const std::string& client_id, |
| const std::string& client_secret, |
| const std::string& oauth_consumer_name, |
| const ScopeSet& scopes, |
| AccessTokenFetcher::TokenCallback callback, |
| AccessTokenFetcher::Mode mode) { |
| return std::make_unique<AccessTokenFetcher>( |
| account_id, client_id, client_secret, oauth_consumer_name, |
| token_service_.get(), primary_account_manager_.get(), scopes, |
| std::move(callback), mode); |
| } |
| |
| void IdentityManager::RemoveAccessTokenFromCache( |
| const CoreAccountId& account_id, |
| const ScopeSet& scopes, |
| const std::string& access_token) { |
| token_service_->InvalidateAccessToken(account_id, scopes, access_token); |
| } |
| |
| std::vector<CoreAccountInfo> IdentityManager::GetAccountsWithRefreshTokens() |
| const { |
| std::vector<CoreAccountId> account_ids_with_tokens = |
| token_service_->GetAccounts(); |
| |
| std::vector<CoreAccountInfo> accounts; |
| accounts.reserve(account_ids_with_tokens.size()); |
| |
| for (const CoreAccountId& account_id : account_ids_with_tokens) { |
| accounts.push_back(GetAccountInfoForAccountWithRefreshToken(account_id)); |
| } |
| |
| return accounts; |
| } |
| |
| std::vector<AccountInfo> |
| IdentityManager::GetExtendedAccountInfoForAccountsWithRefreshToken() const { |
| std::vector<CoreAccountId> account_ids_with_tokens = |
| token_service_->GetAccounts(); |
| |
| std::vector<AccountInfo> accounts; |
| accounts.reserve(account_ids_with_tokens.size()); |
| |
| for (const CoreAccountId& account_id : account_ids_with_tokens) { |
| accounts.push_back(GetAccountInfoForAccountWithRefreshToken(account_id)); |
| } |
| |
| return accounts; |
| } |
| |
| bool IdentityManager::HasPrimaryAccountWithRefreshToken( |
| ConsentLevel consent_level) const { |
| return HasAccountWithRefreshToken(GetPrimaryAccountId(consent_level)); |
| } |
| |
| bool IdentityManager::HasAccountWithRefreshToken( |
| const CoreAccountId& account_id) const { |
| return token_service_->RefreshTokenIsAvailable(account_id); |
| } |
| |
| bool IdentityManager::AreRefreshTokensLoaded() const { |
| return token_service_->AreAllCredentialsLoaded(); |
| } |
| |
| bool IdentityManager::HasAccountWithRefreshTokenInPersistentErrorState( |
| const CoreAccountId& account_id) const { |
| return GetErrorStateOfRefreshTokenForAccount(account_id).IsPersistentError(); |
| } |
| |
| GoogleServiceAuthError IdentityManager::GetErrorStateOfRefreshTokenForAccount( |
| const CoreAccountId& account_id) const { |
| return token_service_->GetAuthError(account_id); |
| } |
| |
| AccountInfo IdentityManager::FindExtendedAccountInfo( |
| const CoreAccountInfo& account_info) const { |
| return FindExtendedAccountInfoByAccountId(account_info.account_id); |
| } |
| |
| AccountInfo IdentityManager::FindExtendedAccountInfoByAccountId( |
| const CoreAccountId& account_id) const { |
| if (!HasAccountWithRefreshToken(account_id)) |
| return AccountInfo(); |
| |
| // AccountTrackerService returns an empty AccountInfo if the account is not |
| // found. |
| return account_tracker_service_->GetAccountInfo(account_id); |
| } |
| |
| AccountInfo IdentityManager::FindExtendedAccountInfoByEmailAddress( |
| const std::string& email_address) const { |
| AccountInfo account_info = |
| account_tracker_service_->FindAccountInfoByEmail(email_address); |
| // AccountTrackerService always returns an AccountInfo, even on failure. In |
| // case of failure, the AccountInfo will be unpopulated, thus we should not |
| // be able to find a valid refresh token. |
| return HasAccountWithRefreshToken(account_info.account_id) ? account_info |
| : AccountInfo(); |
| } |
| |
| AccountInfo IdentityManager::FindExtendedAccountInfoByGaiaId( |
| const std::string& gaia_id) const { |
| AccountInfo account_info = |
| account_tracker_service_->FindAccountInfoByGaiaId(gaia_id); |
| // AccountTrackerService always returns an AccountInfo, even on failure. In |
| // case of failure, the AccountInfo will be unpopulated, thus we should not |
| // be able to find a valid refresh token. |
| return HasAccountWithRefreshToken(account_info.account_id) ? account_info |
| : AccountInfo(); |
| } |
| |
| std::unique_ptr<UbertokenFetcher> |
| IdentityManager::CreateUbertokenFetcherForAccount( |
| const CoreAccountId& account_id, |
| UbertokenFetcher::CompletionCallback callback, |
| gaia::GaiaSource source, |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { |
| return std::make_unique<UbertokenFetcherImpl>( |
| account_id, token_service_.get(), std::move(callback), source, |
| url_loader_factory); |
| } |
| |
| AccountsInCookieJarInfo IdentityManager::GetAccountsInCookieJar() const { |
| std::vector<gaia::ListedAccount> signed_in_accounts; |
| std::vector<gaia::ListedAccount> signed_out_accounts; |
| bool accounts_are_fresh = gaia_cookie_manager_service_->ListAccounts( |
| &signed_in_accounts, &signed_out_accounts); |
| |
| return AccountsInCookieJarInfo(accounts_are_fresh, signed_in_accounts, |
| signed_out_accounts); |
| } |
| |
| PrimaryAccountMutator* IdentityManager::GetPrimaryAccountMutator() { |
| return identity_mutator_.GetPrimaryAccountMutator(); |
| } |
| |
| AccountsMutator* IdentityManager::GetAccountsMutator() { |
| return identity_mutator_.GetAccountsMutator(); |
| } |
| |
| AccountsCookieMutator* IdentityManager::GetAccountsCookieMutator() { |
| return identity_mutator_.GetAccountsCookieMutator(); |
| } |
| |
| DeviceAccountsSynchronizer* IdentityManager::GetDeviceAccountsSynchronizer() { |
| return identity_mutator_.GetDeviceAccountsSynchronizer(); |
| } |
| |
| void IdentityManager::AddDiagnosticsObserver(DiagnosticsObserver* observer) { |
| diagnostics_observation_list_.AddObserver(observer); |
| } |
| |
| void IdentityManager::RemoveDiagnosticsObserver(DiagnosticsObserver* observer) { |
| diagnostics_observation_list_.RemoveObserver(observer); |
| } |
| |
| void IdentityManager::OnNetworkInitialized() { |
| gaia_cookie_manager_service_->InitCookieListener(); |
| account_fetcher_service_->OnNetworkInitialized(); |
| } |
| |
| IdentityManager::AccountIdMigrationState |
| IdentityManager::GetAccountIdMigrationState() const { |
| return static_cast<IdentityManager::AccountIdMigrationState>( |
| account_tracker_service_->GetMigrationState()); |
| } |
| |
| CoreAccountId IdentityManager::PickAccountIdForAccount( |
| const std::string& gaia, |
| const std::string& email) const { |
| return account_tracker_service_->PickAccountIdForAccount(gaia, email); |
| } |
| |
| // static |
| void IdentityManager::RegisterLocalStatePrefs(PrefRegistrySimple* registry) { |
| PrimaryAccountManager::RegisterPrefs(registry); |
| } |
| |
| // static |
| void IdentityManager::RegisterProfilePrefs(PrefRegistrySimple* registry) { |
| ProfileOAuth2TokenService::RegisterProfilePrefs(registry); |
| PrimaryAccountManager::RegisterProfilePrefs(registry); |
| AccountFetcherService::RegisterPrefs(registry); |
| AccountTrackerService::RegisterPrefs(registry); |
| GaiaCookieManagerService::RegisterPrefs(registry); |
| #if BUILDFLAG(ENABLE_DICE_SUPPORT) |
| MutableProfileOAuth2TokenServiceDelegate::RegisterProfilePrefs(registry); |
| #endif |
| } |
| |
| DiagnosticsProvider* IdentityManager::GetDiagnosticsProvider() { |
| return diagnostics_provider_.get(); |
| } |
| |
| #if defined(OS_ANDROID) |
| base::android::ScopedJavaLocalRef<jobject> |
| IdentityManager::LegacyGetAccountTrackerServiceJavaObject() { |
| return account_tracker_service_->GetJavaObject(); |
| } |
| |
| base::android::ScopedJavaLocalRef<jobject> IdentityManager::GetJavaObject() { |
| DCHECK(java_identity_manager_); |
| return base::android::ScopedJavaLocalRef<jobject>(java_identity_manager_); |
| } |
| |
| base::android::ScopedJavaLocalRef<jobject> |
| IdentityManager::GetIdentityMutatorJavaObject() { |
| return base::android::ScopedJavaLocalRef<jobject>( |
| identity_mutator_.GetJavaObject()); |
| } |
| |
| void IdentityManager::ForceRefreshOfExtendedAccountInfo( |
| const CoreAccountId& account_id) { |
| DCHECK(HasAccountWithRefreshToken(account_id)); |
| AccountInfo account_info = |
| account_tracker_service_->GetAccountInfo(account_id); |
| if (account_info.account_image.IsEmpty()) { |
| account_info_fetch_start_times_[account_id] = base::TimeTicks::Now(); |
| } |
| account_fetcher_service_->ForceRefreshOfAccountInfo(account_id); |
| } |
| |
| void IdentityManager::ForceRefreshOfExtendedAccountInfo( |
| JNIEnv* env, |
| const base::android::JavaParamRef<jobject>& j_core_account_id) { |
| ForceRefreshOfExtendedAccountInfo( |
| ConvertFromJavaCoreAccountId(env, j_core_account_id)); |
| } |
| |
| base::android::ScopedJavaLocalRef<jobject> |
| IdentityManager::GetPrimaryAccountInfo(JNIEnv* env, jint consent_level) const { |
| CoreAccountInfo account_info = |
| GetPrimaryAccountInfo(static_cast<ConsentLevel>(consent_level)); |
| if (account_info.IsEmpty()) |
| return nullptr; |
| return ConvertToJavaCoreAccountInfo(env, account_info); |
| } |
| |
| base::android::ScopedJavaLocalRef<jobject> |
| IdentityManager::FindExtendedAccountInfoByEmailAddress( |
| JNIEnv* env, |
| const base::android::JavaParamRef<jstring>& j_email) const { |
| AccountInfo account_info = FindExtendedAccountInfoByEmailAddress( |
| base::android::ConvertJavaStringToUTF8(env, j_email)); |
| if (account_info.IsEmpty()) |
| return nullptr; |
| return ConvertToJavaAccountInfo(env, account_info); |
| } |
| |
| base::android::ScopedJavaLocalRef<jobjectArray> |
| IdentityManager::GetAccountsWithRefreshTokens(JNIEnv* env) const { |
| std::vector<CoreAccountInfo> accounts = GetAccountsWithRefreshTokens(); |
| |
| base::android::ScopedJavaLocalRef<jclass> coreaccountinfo_clazz = |
| base::android::GetClass( |
| env, "org/chromium/components/signin/base/CoreAccountInfo"); |
| base::android::ScopedJavaLocalRef<jobjectArray> array( |
| env, env->NewObjectArray(accounts.size(), coreaccountinfo_clazz.obj(), |
| nullptr)); |
| base::android::CheckException(env); |
| |
| for (size_t i = 0; i < accounts.size(); ++i) { |
| base::android::ScopedJavaLocalRef<jobject> item = |
| ConvertToJavaCoreAccountInfo(env, accounts[i]); |
| env->SetObjectArrayElement(array.obj(), i, item.obj()); |
| } |
| return array; |
| } |
| #endif |
| |
| AccountInfo IdentityManager::FindExtendedPrimaryAccountInfo( |
| ConsentLevel consent_level) { |
| CoreAccountId account_id = GetPrimaryAccountId(consent_level); |
| return account_tracker_service_->GetAccountInfo(account_id); |
| } |
| |
| PrimaryAccountManager* IdentityManager::GetPrimaryAccountManager() const { |
| return primary_account_manager_.get(); |
| } |
| |
| ProfileOAuth2TokenService* IdentityManager::GetTokenService() const { |
| return token_service_.get(); |
| } |
| |
| AccountTrackerService* IdentityManager::GetAccountTrackerService() const { |
| return account_tracker_service_.get(); |
| } |
| |
| AccountFetcherService* IdentityManager::GetAccountFetcherService() const { |
| return account_fetcher_service_.get(); |
| } |
| |
| GaiaCookieManagerService* IdentityManager::GetGaiaCookieManagerService() const { |
| return gaia_cookie_manager_service_.get(); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| account_manager::AccountManager* IdentityManager::GetAshAccountManager() const { |
| return ash_account_manager_; |
| } |
| #endif |
| |
| AccountInfo IdentityManager::GetAccountInfoForAccountWithRefreshToken( |
| const CoreAccountId& account_id) const { |
| // TODO(https://crbug.com/919793): This invariant is not currently possible to |
| // enforce on Android due to the underlying relationship between |
| // O2TS::GetAccounts(), O2TS::RefreshTokenIsAvailable(), and |
| // O2TS::Observer::OnRefreshTokenAvailable(). |
| #if !defined(OS_ANDROID) |
| DCHECK(HasAccountWithRefreshToken(account_id)); |
| #endif |
| |
| AccountInfo account_info = |
| account_tracker_service_->GetAccountInfo(account_id); |
| DCHECK(!account_info.IsEmpty()); |
| |
| return account_info; |
| } |
| |
| void IdentityManager::OnPrimaryAccountChanged( |
| const PrimaryAccountChangeEvent& event_details) { |
| CoreAccountId event_primary_account_id = |
| event_details.GetCurrentState().primary_account.account_id; |
| DCHECK_EQ(event_primary_account_id, |
| GetPrimaryAccountId(event_details.GetCurrentState().consent_level)); |
| for (auto& observer : observer_list_) { |
| observer.OnPrimaryAccountChanged(event_details); |
| // Ensure that |observer| did not change the primary account as otherwise |
| // |event_details| would not longer be correct. |
| DCHECK_EQ( |
| event_primary_account_id, |
| GetPrimaryAccountId(event_details.GetCurrentState().consent_level)); |
| } |
| |
| #if defined(OS_ANDROID) |
| if (java_identity_manager_) { |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| Java_IdentityManager_onPrimaryAccountChanged( |
| env, java_identity_manager_, |
| ConvertToJavaPrimaryAccountChangeEvent(env, event_details)); |
| } |
| #endif |
| } |
| |
| void IdentityManager::OnRefreshTokenAvailable(const CoreAccountId& account_id) { |
| CoreAccountInfo account_info = |
| GetAccountInfoForAccountWithRefreshToken(account_id); |
| |
| for (auto& observer : observer_list_) { |
| observer.OnRefreshTokenUpdatedForAccount(account_info); |
| } |
| } |
| |
| void IdentityManager::OnRefreshTokenRevoked(const CoreAccountId& account_id) { |
| for (auto& observer : observer_list_) { |
| observer.OnRefreshTokenRemovedForAccount(account_id); |
| } |
| } |
| |
| void IdentityManager::OnRefreshTokensLoaded() { |
| for (auto& observer : observer_list_) |
| observer.OnRefreshTokensLoaded(); |
| } |
| |
| void IdentityManager::OnEndBatchChanges() { |
| for (auto& observer : observer_list_) |
| observer.OnEndBatchOfRefreshTokenStateChanges(); |
| } |
| |
| void IdentityManager::OnAuthErrorChanged( |
| const CoreAccountId& account_id, |
| const GoogleServiceAuthError& auth_error) { |
| CoreAccountInfo account_info = |
| GetAccountInfoForAccountWithRefreshToken(account_id); |
| |
| for (auto& observer : observer_list_) |
| observer.OnErrorStateOfRefreshTokenUpdatedForAccount(account_info, |
| auth_error); |
| } |
| |
| void IdentityManager::OnGaiaAccountsInCookieUpdated( |
| const std::vector<gaia::ListedAccount>& signed_in_accounts, |
| const std::vector<gaia::ListedAccount>& signed_out_accounts, |
| const GoogleServiceAuthError& error) { |
| AccountsInCookieJarInfo accounts_in_cookie_jar_info( |
| error == GoogleServiceAuthError::AuthErrorNone(), signed_in_accounts, |
| signed_out_accounts); |
| |
| for (auto& observer : observer_list_) { |
| observer.OnAccountsInCookieUpdated(accounts_in_cookie_jar_info, error); |
| } |
| } |
| |
| void IdentityManager::OnGaiaCookieDeletedByUserAction() { |
| for (auto& observer : observer_list_) { |
| observer.OnAccountsCookieDeletedByUserAction(); |
| } |
| #if defined(OS_ANDROID) |
| if (java_identity_manager_) { |
| Java_IdentityManager_onAccountsCookieDeletedByUserAction( |
| base::android::AttachCurrentThread(), java_identity_manager_); |
| } |
| #endif |
| } |
| |
| void IdentityManager::OnAccessTokenRequested(const CoreAccountId& account_id, |
| const std::string& consumer_id, |
| const ScopeSet& scopes) { |
| for (auto& observer : diagnostics_observation_list_) { |
| observer.OnAccessTokenRequested(account_id, consumer_id, scopes); |
| } |
| } |
| |
| void IdentityManager::OnFetchAccessTokenComplete( |
| const CoreAccountId& account_id, |
| const std::string& consumer_id, |
| const ScopeSet& scopes, |
| GoogleServiceAuthError error, |
| base::Time expiration_time) { |
| for (auto& observer : diagnostics_observation_list_) |
| observer.OnAccessTokenRequestCompleted(account_id, consumer_id, scopes, |
| error, expiration_time); |
| } |
| |
| void IdentityManager::OnAccessTokenRemoved(const CoreAccountId& account_id, |
| const ScopeSet& scopes) { |
| for (auto& observer : diagnostics_observation_list_) |
| observer.OnAccessTokenRemovedFromCache(account_id, scopes); |
| } |
| |
| void IdentityManager::OnRefreshTokenAvailableFromSource( |
| const CoreAccountId& account_id, |
| bool is_refresh_token_valid, |
| const std::string& source) { |
| for (auto& observer : diagnostics_observation_list_) |
| observer.OnRefreshTokenUpdatedForAccountFromSource( |
| account_id, is_refresh_token_valid, source); |
| } |
| |
| void IdentityManager::OnRefreshTokenRevokedFromSource( |
| const CoreAccountId& account_id, |
| const std::string& source) { |
| for (auto& observer : diagnostics_observation_list_) |
| observer.OnRefreshTokenRemovedForAccountFromSource(account_id, source); |
| } |
| |
| void IdentityManager::OnAccountUpdated(const AccountInfo& info) { |
| if (HasPrimaryAccount(signin::ConsentLevel::kSignin)) { |
| const CoreAccountId primary_account_id = |
| GetPrimaryAccountId(ConsentLevel::kSignin); |
| if (primary_account_id == info.account_id) { |
| primary_account_manager_->UpdatePrimaryAccountInfo(); |
| } |
| } |
| |
| for (auto& observer : observer_list_) { |
| observer.OnExtendedAccountInfoUpdated(info); |
| } |
| #if defined(OS_ANDROID) |
| if (java_identity_manager_) { |
| if (account_info_fetch_start_times_.count(info.account_id) && |
| !info.account_image.IsEmpty()) { |
| base::UmaHistogramTimes( |
| "Signin.AndroidAccountInfoFetchTime", |
| base::TimeTicks::Now() - |
| account_info_fetch_start_times_[info.account_id]); |
| account_info_fetch_start_times_.erase(info.account_id); |
| } |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| Java_IdentityManager_onExtendedAccountInfoUpdated( |
| env, java_identity_manager_, ConvertToJavaAccountInfo(env, info)); |
| } |
| #endif |
| } |
| |
| void IdentityManager::OnAccountRemoved(const AccountInfo& info) { |
| for (auto& observer : observer_list_) |
| observer.OnExtendedAccountInfoRemoved(info); |
| } |
| |
| } // namespace signin |