Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(520)

Unified Diff: components/signin/ios/browser/profile_oauth2_token_service_ios.mm

Issue 1143323005: Refactor AO2TS to make it easier to componentize. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address final comments Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/signin/ios/browser/profile_oauth2_token_service_ios.mm
diff --git a/components/signin/ios/browser/profile_oauth2_token_service_ios.mm b/components/signin/ios/browser/profile_oauth2_token_service_ios.mm
deleted file mode 100644
index 2eb3cff42429ff2564df047782c82c5e57351f19..0000000000000000000000000000000000000000
--- a/components/signin/ios/browser/profile_oauth2_token_service_ios.mm
+++ /dev/null
@@ -1,499 +0,0 @@
-// Copyright 2014 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/ios/browser/profile_oauth2_token_service_ios.h"
-
-#include <Foundation/Foundation.h>
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/prefs/pref_service.h"
-#include "base/prefs/scoped_user_pref_update.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/values.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "components/signin/core/common/signin_pref_names.h"
-#include "google_apis/gaia/oauth2_access_token_fetcher.h"
-#include "ios/public/provider/components/signin/browser/profile_oauth2_token_service_ios_provider.h"
-#include "net/url_request/url_request_status.h"
-
-namespace {
-
-// Match the way Chromium handles authentication errors in
-// google_apis/gaia/oauth2_access_token_fetcher.cc:
-GoogleServiceAuthError GetGoogleServiceAuthErrorFromNSError(
- ios::ProfileOAuth2TokenServiceIOSProvider* provider,
- NSError* error) {
- if (!error)
- return GoogleServiceAuthError::AuthErrorNone();
-
- ios::AuthenticationErrorCategory errorCategory =
- provider->GetAuthenticationErrorCategory(error);
- switch (errorCategory) {
- case ios::kAuthenticationErrorCategoryUnknownErrors:
- // Treat all unknown error as unexpected service response errors.
- // This may be too general and may require a finer grain filtering.
- return GoogleServiceAuthError(
- GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE);
- case ios::kAuthenticationErrorCategoryAuthorizationErrors:
- return GoogleServiceAuthError(
- GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
- case ios::kAuthenticationErrorCategoryAuthorizationForbiddenErrors:
- // HTTP_FORBIDDEN (403) is treated as temporary error, because it may be
- // '403 Rate Limit Exceeded.' (for more details, see
- // google_apis/gaia/oauth2_access_token_fetcher.cc).
- return GoogleServiceAuthError(
- GoogleServiceAuthError::SERVICE_UNAVAILABLE);
- case ios::kAuthenticationErrorCategoryNetworkServerErrors:
- // Just set the connection error state to FAILED.
- return GoogleServiceAuthError::FromConnectionError(
- net::URLRequestStatus::FAILED);
- case ios::kAuthenticationErrorCategoryUserCancellationErrors:
- return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
- case ios::kAuthenticationErrorCategoryUnknownIdentityErrors:
- return GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
- }
-}
-
-class SSOAccessTokenFetcher : public OAuth2AccessTokenFetcher {
- public:
- SSOAccessTokenFetcher(OAuth2AccessTokenConsumer* consumer,
- ios::ProfileOAuth2TokenServiceIOSProvider* provider,
- const std::string account_id);
- ~SSOAccessTokenFetcher() override;
-
- void Start(const std::string& client_id,
- const std::string& client_secret,
- const std::vector<std::string>& scopes) override;
-
- void CancelRequest() override;
-
- // Handles an access token response.
- void OnAccessTokenResponse(NSString* token,
- NSDate* expiration,
- NSError* error);
-
- private:
- ios::ProfileOAuth2TokenServiceIOSProvider* provider_; // weak
- std::string account_id_;
- bool request_was_cancelled_;
- base::WeakPtrFactory<SSOAccessTokenFetcher> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(SSOAccessTokenFetcher);
-};
-
-SSOAccessTokenFetcher::SSOAccessTokenFetcher(
- OAuth2AccessTokenConsumer* consumer,
- ios::ProfileOAuth2TokenServiceIOSProvider* provider,
- const std::string account_id)
- : OAuth2AccessTokenFetcher(consumer),
- provider_(provider),
- account_id_(account_id),
- request_was_cancelled_(false),
- weak_factory_(this) {
- DCHECK(provider_);
-}
-
-SSOAccessTokenFetcher::~SSOAccessTokenFetcher() {}
-
-void SSOAccessTokenFetcher::Start(const std::string& client_id,
- const std::string& client_secret,
- const std::vector<std::string>& scopes) {
- std::set<std::string> scopes_set(scopes.begin(), scopes.end());
- provider_->GetAccessToken(
- account_id_, client_id, client_secret, scopes_set,
- base::Bind(&SSOAccessTokenFetcher::OnAccessTokenResponse,
- weak_factory_.GetWeakPtr()));
-}
-
-void SSOAccessTokenFetcher::CancelRequest() { request_was_cancelled_ = true; }
-
-void SSOAccessTokenFetcher::OnAccessTokenResponse(NSString* token,
- NSDate* expiration,
- NSError* error) {
- if (request_was_cancelled_) {
- // Ignore the callback if the request was cancelled.
- return;
- }
- GoogleServiceAuthError auth_error =
- GetGoogleServiceAuthErrorFromNSError(provider_, error);
- if (auth_error.state() == GoogleServiceAuthError::NONE) {
- base::Time expiration_date =
- base::Time::FromDoubleT([expiration timeIntervalSince1970]);
- FireOnGetTokenSuccess(base::SysNSStringToUTF8(token), expiration_date);
- } else {
- FireOnGetTokenFailure(auth_error);
- }
-}
-
-} // namespace
-
-ProfileOAuth2TokenServiceIOS::AccountInfo::AccountInfo(
- SigninErrorController* signin_error_controller,
- const std::string& account_id)
- : signin_error_controller_(signin_error_controller),
- account_id_(account_id),
- last_auth_error_(GoogleServiceAuthError::NONE),
- marked_for_removal_(false) {
- DCHECK(signin_error_controller_);
- DCHECK(!account_id_.empty());
- signin_error_controller_->AddProvider(this);
-}
-
-ProfileOAuth2TokenServiceIOS::AccountInfo::~AccountInfo() {
- signin_error_controller_->RemoveProvider(this);
-}
-
-void ProfileOAuth2TokenServiceIOS::AccountInfo::SetLastAuthError(
- const GoogleServiceAuthError& error) {
- if (error.state() != last_auth_error_.state()) {
- last_auth_error_ = error;
- signin_error_controller_->AuthStatusChanged();
- }
-}
-
-std::string ProfileOAuth2TokenServiceIOS::AccountInfo::GetAccountId() const {
- return account_id_;
-}
-
-GoogleServiceAuthError
-ProfileOAuth2TokenServiceIOS::AccountInfo::GetAuthStatus() const {
- return last_auth_error_;
-}
-
-ProfileOAuth2TokenServiceIOS::ProfileOAuth2TokenServiceIOS()
- : ProfileOAuth2TokenService() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-ProfileOAuth2TokenServiceIOS::~ProfileOAuth2TokenServiceIOS() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-void ProfileOAuth2TokenServiceIOS::Initialize(
- SigninClient* client, SigninErrorController* signin_error_controller) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ProfileOAuth2TokenService::Initialize(client, signin_error_controller);
-}
-
-void ProfileOAuth2TokenServiceIOS::Shutdown() {
- DCHECK(thread_checker_.CalledOnValidThread());
- CancelAllRequests();
- accounts_.clear();
- ProfileOAuth2TokenService::Shutdown();
-}
-
-ios::ProfileOAuth2TokenServiceIOSProvider*
-ProfileOAuth2TokenServiceIOS::GetProvider() {
- ios::ProfileOAuth2TokenServiceIOSProvider* provider =
- client()->GetIOSProvider();
- DCHECK(provider);
- return provider;
-}
-
-void ProfileOAuth2TokenServiceIOS::LoadCredentials(
- const std::string& primary_account_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // LoadCredentials() is called iff the user is signed in to Chrome, so the
- // primary account id must not be empty.
- DCHECK(!primary_account_id.empty());
-
- GetProvider()->InitializeSharedAuthentication();
- ReloadCredentials(primary_account_id);
- FireRefreshTokensLoaded();
-}
-
-void ProfileOAuth2TokenServiceIOS::ReloadCredentials(
- const std::string& primary_account_id) {
- DCHECK(!primary_account_id.empty());
- DCHECK(primary_account_id_.empty() ||
- primary_account_id_ == primary_account_id);
- primary_account_id_ = primary_account_id;
- ReloadCredentials();
-}
-
-void ProfileOAuth2TokenServiceIOS::ReloadCredentials() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (primary_account_id_.empty()) {
- // Avoid loading the credentials if there is no primary account id.
- return;
- }
-
- std::vector<std::string> new_accounts(GetProvider()->GetAllAccountIds());
- if (GetExcludeAllSecondaryAccounts()) {
- // Only keep the |primary_account_id| in the list of new accounts.
- if (std::find(new_accounts.begin(),
- new_accounts.end(),
- primary_account_id_) != new_accounts.end()) {
- new_accounts.clear();
- new_accounts.push_back(primary_account_id_);
- }
- } else {
- std::set<std::string> exclude_secondary_accounts =
- GetExcludedSecondaryAccounts();
- DCHECK(std::find(exclude_secondary_accounts.begin(),
- exclude_secondary_accounts.end(),
- primary_account_id_) == exclude_secondary_accounts.end());
- for (const auto& excluded_account_id : exclude_secondary_accounts) {
- DCHECK(!excluded_account_id.empty());
- auto account_id_to_remove_position = std::remove(
- new_accounts.begin(), new_accounts.end(), excluded_account_id);
- new_accounts.erase(account_id_to_remove_position, new_accounts.end());
- }
- }
-
- std::vector<std::string> old_accounts(GetAccounts());
- std::sort(new_accounts.begin(), new_accounts.end());
- std::sort(old_accounts.begin(), old_accounts.end());
- if (new_accounts == old_accounts) {
- // Avoid starting a batch change if there are no changes in the list of
- // account.
- return;
- }
-
- // Remove all old accounts that do not appear in |new_accounts| and then
- // load |new_accounts|.
- ScopedBatchChange batch(this);
- for (auto i = old_accounts.begin(); i != old_accounts.end(); ++i) {
- if (std::find(new_accounts.begin(), new_accounts.end(), *i) ==
- new_accounts.end()) {
- RemoveAccount(*i);
- }
- }
-
- // Load all new_accounts.
- for (auto i = new_accounts.begin(); i != new_accounts.end(); ++i) {
- AddOrUpdateAccount(*i);
- }
-}
-
-void ProfileOAuth2TokenServiceIOS::UpdateCredentials(
- const std::string& account_id,
- const std::string& refresh_token) {
- DCHECK(thread_checker_.CalledOnValidThread());
- NOTREACHED() << "Unexpected call to UpdateCredentials when using shared "
- "authentication.";
-}
-
-void ProfileOAuth2TokenServiceIOS::RevokeAllCredentials() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- ScopedBatchChange batch(this);
- AccountInfoMap toRemove = accounts_;
- for (AccountInfoMap::iterator i = toRemove.begin(); i != toRemove.end(); ++i)
- RemoveAccount(i->first);
-
- DCHECK_EQ(0u, accounts_.size());
- primary_account_id_.clear();
- ClearExcludedSecondaryAccounts();
- // |RemoveAccount| should have cancelled all the requests and cleared the
- // cache, account-by-account. This extra-cleaning should do nothing unless
- // something went wrong and some cache values and/or pending requests were not
- // linked to any valid account.
- CancelAllRequests();
- ClearCache();
-}
-
-OAuth2AccessTokenFetcher*
-ProfileOAuth2TokenServiceIOS::CreateAccessTokenFetcher(
- const std::string& account_id,
- net::URLRequestContextGetter* getter,
- OAuth2AccessTokenConsumer* consumer) {
- return new SSOAccessTokenFetcher(consumer, GetProvider(), account_id);
-}
-
-void ProfileOAuth2TokenServiceIOS::InvalidateOAuth2Token(
- const std::string& account_id,
- const std::string& client_id,
- const ScopeSet& scopes,
- const std::string& access_token) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Call |ProfileOAuth2TokenService::InvalidateOAuth2Token| to clear the
- // cached access token.
- ProfileOAuth2TokenService::InvalidateOAuth2Token(account_id,
- client_id,
- scopes,
- access_token);
-
- // There is no need to inform the authentication library that the access
- // token is invalid as it never caches the token.
-}
-
-std::vector<std::string> ProfileOAuth2TokenServiceIOS::GetAccounts() {
- DCHECK(thread_checker_.CalledOnValidThread());
- std::vector<std::string> account_ids;
- for (auto i = accounts_.begin(); i != accounts_.end(); ++i)
- account_ids.push_back(i->first);
- return account_ids;
-}
-
-bool ProfileOAuth2TokenServiceIOS::RefreshTokenIsAvailable(
- const std::string& account_id) const {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- AccountInfoMap::const_iterator iter = accounts_.find(account_id);
- return iter != accounts_.end() && !iter->second->marked_for_removal();
-}
-
-void ProfileOAuth2TokenServiceIOS::UpdateAuthError(
- const std::string& account_id,
- const GoogleServiceAuthError& error) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Do not report connection errors as these are not actually auth errors.
- // We also want to avoid masking a "real" auth error just because we
- // subsequently get a transient network error.
- if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
- error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
- return;
- }
-
- if (accounts_.count(account_id) == 0) {
- NOTREACHED();
- return;
- }
- accounts_[account_id]->SetLastAuthError(error);
-}
-
-// Clear the authentication error state and notify all observers that a new
-// refresh token is available so that they request new access tokens.
-void ProfileOAuth2TokenServiceIOS::AddOrUpdateAccount(
- const std::string& account_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!account_id.empty());
-
- bool account_present = accounts_.count(account_id) > 0;
- if (account_present && accounts_[account_id]->GetAuthStatus().state() ==
- GoogleServiceAuthError::NONE) {
- // No need to update the account if it is already a known account and if
- // there is no auth error.
- return;
- }
-
- if (account_present) {
- CancelRequestsForAccount(account_id);
- ClearCacheForAccount(account_id);
- } else {
- accounts_[account_id].reset(
- new AccountInfo(signin_error_controller(), account_id));
- }
- UpdateAuthError(account_id, GoogleServiceAuthError::AuthErrorNone());
- FireRefreshTokenAvailable(account_id);
-}
-
-void ProfileOAuth2TokenServiceIOS::RemoveAccount(
- const std::string& account_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!account_id.empty());
-
- if (accounts_.count(account_id) > 0) {
- // This is needed to ensure that refresh token for |acccount_id| is not
- // available while the account is removed. Thus all access token requests
- // for |account_id| triggered while an account is being removed will get a
- // user not signed up error response.
- accounts_[account_id]->set_marked_for_removal(true);
- CancelRequestsForAccount(account_id);
- ClearCacheForAccount(account_id);
- accounts_.erase(account_id);
- FireRefreshTokenRevoked(account_id);
- }
-}
-
-std::set<std::string>
-ProfileOAuth2TokenServiceIOS::GetExcludedSecondaryAccounts() {
- const base::ListValue* excluded_secondary_accounts_pref =
- client()->GetPrefs()->GetList(
- prefs::kTokenServiceExcludedSecondaryAccounts);
- std::set<std::string> excluded_secondary_accounts;
- for (base::Value* pref_value : *excluded_secondary_accounts_pref) {
- std::string value;
- if (pref_value->GetAsString(&value))
- excluded_secondary_accounts.insert(value);
- }
- return excluded_secondary_accounts;
-}
-
-void ProfileOAuth2TokenServiceIOS::ExcludeSecondaryAccounts(
- const std::vector<std::string>& account_ids) {
- for (const auto& account_id : account_ids)
- ExcludeSecondaryAccount(account_id);
-}
-
-void ProfileOAuth2TokenServiceIOS::ExcludeSecondaryAccount(
- const std::string& account_id) {
- if (GetExcludeAllSecondaryAccounts()) {
- // Avoid excluding individual secondary accounts when all secondary
- // accounts are excluded.
- return;
- }
-
- DCHECK(!account_id.empty());
- ListPrefUpdate update(client()->GetPrefs(),
- prefs::kTokenServiceExcludedSecondaryAccounts);
- base::ListValue* excluded_secondary_accounts = update.Get();
- for (base::Value* pref_value : *excluded_secondary_accounts) {
- std::string value_at_it;
- if (pref_value->GetAsString(&value_at_it) && (value_at_it == account_id)) {
- // |account_id| is already excluded.
- return;
- }
- }
- excluded_secondary_accounts->AppendString(account_id);
-}
-
-void ProfileOAuth2TokenServiceIOS::IncludeSecondaryAccount(
- const std::string& account_id) {
- if (GetExcludeAllSecondaryAccounts()) {
- // Avoid including individual secondary accounts when all secondary
- // accounts are excluded.
- return;
- }
-
- DCHECK_NE(account_id, primary_account_id_);
- DCHECK(!primary_account_id_.empty());
-
- // Excluded secondary account ids is a logical set (not a list) of accounts.
- // As the value stored in the excluded account ids preference is a list,
- // the code below removes all occurences of |account_id| from this list. This
- // ensures that |account_id| is actually included even in cases when the
- // preference value was corrupted (see bug http://crbug.com/453470 as
- // example).
- ListPrefUpdate update(client()->GetPrefs(),
- prefs::kTokenServiceExcludedSecondaryAccounts);
- base::ListValue* excluded_secondary_accounts = update.Get();
- base::ListValue::iterator it = excluded_secondary_accounts->begin();
- while (it != excluded_secondary_accounts->end()) {
- base::Value* pref_value = *it;
- std::string value_at_it;
- if (pref_value->GetAsString(&value_at_it) && (value_at_it == account_id)) {
- it = excluded_secondary_accounts->Erase(it, nullptr);
- continue;
- }
- ++it;
- }
-}
-
-bool ProfileOAuth2TokenServiceIOS::GetExcludeAllSecondaryAccounts() {
- return client()->GetPrefs()->GetBoolean(
- prefs::kTokenServiceExcludeAllSecondaryAccounts);
-}
-
-void ProfileOAuth2TokenServiceIOS::ExcludeAllSecondaryAccounts() {
- client()->GetPrefs()->SetBoolean(
- prefs::kTokenServiceExcludeAllSecondaryAccounts, true);
-}
-
-void ProfileOAuth2TokenServiceIOS::ClearExcludedSecondaryAccounts() {
- client()->GetPrefs()->ClearPref(
- prefs::kTokenServiceExcludeAllSecondaryAccounts);
- client()->GetPrefs()->ClearPref(
- prefs::kTokenServiceExcludedSecondaryAccounts);
-}

Powered by Google App Engine
This is Rietveld 408576698