Commit e72a5906 authored by msarda@chromium.org's avatar msarda@chromium.org

Upstream iOS implementation of ProfileOAuth2TokenService

This CL adds the iOS implementation of the ProfileOAuth2TokenService.

BUG=NONE

Review URL: https://codereview.chromium.org/226643012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@263008 0039d316-1c4b-4281-b951-d872f2087c98
parent 1cf6ad92
...@@ -103,4 +103,25 @@ ...@@ -103,4 +103,25 @@
], ],
}, },
], ],
'conditions': [
['OS == "ios"', {
'targets': [
{
'target_name': 'signin_ios_browser',
'type': 'static_library',
'dependencies': [
'signin_core_browser',
'../ios/provider/ios_components.gyp:ios_components',
],
'include_dirs': [
'..',
],
'sources': [
'signin/ios/browser/profile_oauth2_token_service_ios.h',
'signin/ios/browser/profile_oauth2_token_service_ios.mm',
],
},
],
}],
],
} }
...@@ -17,6 +17,14 @@ class CanonicalCookie; ...@@ -17,6 +17,14 @@ class CanonicalCookie;
class URLRequestContextGetter; class URLRequestContextGetter;
} }
#if defined(OS_IOS)
namespace ios {
// TODO(msarda): http://crbug.com/358544 Remove this iOS specific code from the
// core SigninClient.
class ProfileOAuth2TokenServiceIOSProvider;
}
#endif
// An interface that needs to be supplied to the Signin component by its // An interface that needs to be supplied to the Signin component by its
// embedder. // embedder.
class SigninClient { class SigninClient {
...@@ -57,6 +65,12 @@ class SigninClient { ...@@ -57,6 +65,12 @@ class SigninClient {
// Called when Google signin has succeeded. // Called when Google signin has succeeded.
virtual void GoogleSigninSucceeded(const std::string& username, virtual void GoogleSigninSucceeded(const std::string& username,
const std::string& password) {} const std::string& password) {}
#if defined(OS_IOS)
// TODO(msarda): http://crbug.com/358544 Remove this iOS specific code from
// the core SigninClient.
virtual ios::ProfileOAuth2TokenServiceIOSProvider* GetIOSProvider() = 0;
#endif
}; };
#endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_CLIENT_H_ #endif // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_CLIENT_H_
...@@ -53,3 +53,11 @@ bool TestSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() { ...@@ -53,3 +53,11 @@ bool TestSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
void TestSigninClient::SetCookieChangedCallback( void TestSigninClient::SetCookieChangedCallback(
const CookieChangedCallback& callback) {} const CookieChangedCallback& callback) {}
#if defined(OS_IOS)
ios::ProfileOAuth2TokenServiceIOSProvider* TestSigninClient::GetIOSProvider() {
// Just returns NULL for now. It should be changed to return an
// |ios::FakeProfileOAuth2TokenServiceIOSProvider|.
return NULL;
}
#endif
...@@ -39,6 +39,10 @@ class TestSigninClient : public SigninClient { ...@@ -39,6 +39,10 @@ class TestSigninClient : public SigninClient {
// Returns a TestURLRequestContextGetter. // Returns a TestURLRequestContextGetter.
virtual net::URLRequestContextGetter* GetURLRequestContext() OVERRIDE; virtual net::URLRequestContextGetter* GetURLRequestContext() OVERRIDE;
#if defined(OS_IOS)
virtual ios::ProfileOAuth2TokenServiceIOSProvider* GetIOSProvider() OVERRIDE;
#endif
// Returns true. // Returns true.
virtual bool ShouldMergeSigninCredentialsIntoCookieJar() OVERRIDE; virtual bool ShouldMergeSigninCredentialsIntoCookieJar() OVERRIDE;
......
include_rules = [
"+ios/public/provider/components/signin",
]
// 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.
#ifndef COMPONENTS_SIGNIN_IOS_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_H_
#define COMPONENTS_SIGNIN_IOS_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_H_
#include <string>
#include "base/threading/thread_checker.h"
#include "components/signin/core/browser/mutable_profile_oauth2_token_service.h"
class OAuth2AccessTokenFetcher;
namespace ios{
class ProfileOAuth2TokenServiceIOSProvider;
}
// A specialization of ProfileOAuth2TokenService for OS_IOS. It fetches access
// tokens from the SSOAuth library if the user is signed in using shared
// authentication or defaults to the parent class
// |MutableProfileOAuth2TokenService| for pre-SSO signed in users.
//
// See |ProfileOAuth2TokenService| for usage details.
class ProfileOAuth2TokenServiceIOS : public MutableProfileOAuth2TokenService {
public:
virtual ~ProfileOAuth2TokenServiceIOS();
// KeyedService
virtual void Shutdown() OVERRIDE;
// OAuth2TokenService
virtual bool RefreshTokenIsAvailable(
const std::string& account_id) const OVERRIDE;
virtual void InvalidateOAuth2Token(const std::string& account_id,
const std::string& client_id,
const ScopeSet& scopes,
const std::string& access_token) OVERRIDE;
// ProfileOAuth2TokenService
virtual void Initialize(SigninClient* client) OVERRIDE;
virtual void LoadCredentials(const std::string& primary_account_id) OVERRIDE;
virtual std::vector<std::string> GetAccounts() OVERRIDE;
virtual void UpdateAuthError(const std::string& account_id,
const GoogleServiceAuthError& error) OVERRIDE;
// This method should not be called when using shared authentication.
virtual void UpdateCredentials(const std::string& account_id,
const std::string& refresh_token) OVERRIDE;
// Removes all credentials from this instance of |ProfileOAuth2TokenService|,
// however, it does not revoke the identities from the device.
// Subsequent calls to |RefreshTokenIsAvailable| will return |false|.
virtual void RevokeAllCredentials() OVERRIDE;
// Returns the refresh token for |account_id| .
// Must only be called when |ShouldUseIOSSharedAuthentication| returns false.
std::string GetRefreshTokenWhenNotUsingSharedAuthentication(
const std::string& account_id);
// Reloads accounts from the provider. Fires |OnRefreshTokenAvailable| for
// each new account. Fires |OnRefreshTokenRevoked| for each account that was
// removed.
void ReloadCredentials();
// Upgrades to using shared authentication token service.
//
// Note: If this |ProfileOAuth2TokenServiceIOS| was using the legacy token
// service, then this call also revokes all tokens from the parent
// |MutableProfileOAuth2TokenService|.
void StartUsingSharedAuthentication();
// Sets |use_legacy_token_service_| to |use_legacy_token_service|.
//
// Should only be called for testing.
void SetUseLegacyTokenServiceForTesting(bool use_legacy_token_service);
// Revokes the OAuth2 refresh tokens for all accounts from the parent
// |MutableProfileOAuth2TokenService|.
//
// Note: This method should only be called if the legacy pre-SSOAuth token
// service is used.
void ForceInvalidGrantResponses();
protected:
friend class ProfileOAuth2TokenServiceFactory;
ProfileOAuth2TokenServiceIOS();
virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
const std::string& account_id,
net::URLRequestContextGetter* getter,
OAuth2AccessTokenConsumer* consumer) OVERRIDE;
// Protected and virtual to be overriden by fake for testing.
// Adds |account_id| to |accounts_| if it does not exist or udpates
// the auth error state of |account_id| if it exists. Fires
// |OnRefreshTokenAvailable| if the account info is updated.
virtual void AddOrUpdateAccount(const std::string& account_id);
// Removes |account_id| from |accounts_|. Fires |OnRefreshTokenRevoked|
// if the account info is removed.
virtual void RemoveAccount(const std::string& account_id);
private:
class AccountInfo : public SigninErrorController::AuthStatusProvider {
public:
AccountInfo(ProfileOAuth2TokenService* token_service,
const std::string& account_id);
virtual ~AccountInfo();
void SetLastAuthError(const GoogleServiceAuthError& error);
// SigninErrorController::AuthStatusProvider implementation.
virtual std::string GetAccountId() const OVERRIDE;
virtual GoogleServiceAuthError GetAuthStatus() const OVERRIDE;
private:
ProfileOAuth2TokenService* token_service_;
std::string account_id_;
GoogleServiceAuthError last_auth_error_;
DISALLOW_COPY_AND_ASSIGN(AccountInfo);
};
// Maps the |account_id| of accounts known to ProfileOAuth2TokenService
// to information about the account.
typedef std::map<std::string, linked_ptr<AccountInfo> > AccountInfoMap;
// MutableProfileOAuth2TokenService
virtual std::string GetRefreshToken(
const std::string& account_id) const OVERRIDE;
// Returns the iOS provider;
ios::ProfileOAuth2TokenServiceIOSProvider* GetProvider();
// Info about the existing accounts.
AccountInfoMap accounts_;
// Calls to this class are expected to be made from the browser UI thread.
// The purpose of this this checker is to warn us if the upstream usage of
// ProfileOAuth2TokenService ever gets changed to have it be used across
// multiple threads.
base::ThreadChecker thread_checker_;
// Whether to use the legacy pre-SSOAuth token service.
//
// |use_legacy_token_service_| is true iff the provider is not using shared
// authentication during |LoadCredentials|. Note that |LoadCredentials| is
// called exactly once after the PO2TS initialization iff the user is signed
// in.
//
// If |use_legacy_token_service_| is true, then this
// |ProfileOAuth2TokenServiceIOS| delegates all calls to the parent
// |MutableProfileOAuth2TokenService|.
bool use_legacy_token_service_;
DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenServiceIOS);
};
#endif // COMPONENTS_SIGNIN_IOS_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_H_
// 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/message_loop/message_loop.h"
#include "base/strings/sys_string_conversions.h"
#include "components/signin/core/browser/signin_client.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 {
const char* kForceInvalidGrantResponsesRefreshToken =
"force_invalid_grant_responses_refresh_token";
// 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);
virtual ~SSOAccessTokenFetcher();
virtual void Start(const std::string& client_id,
const std::string& client_secret,
const std::vector<std::string>& scopes) OVERRIDE;
virtual void CancelRequest() OVERRIDE;
// Handles an access token response.
void OnAccessTokenResponse(NSString* token,
NSDate* expiration,
NSError* error);
private:
base::WeakPtrFactory<SSOAccessTokenFetcher> weak_factory_;
ios::ProfileOAuth2TokenServiceIOSProvider* provider_; // weak
std::string account_id_;
bool request_was_cancelled_;
DISALLOW_COPY_AND_ASSIGN(SSOAccessTokenFetcher);
};
SSOAccessTokenFetcher::SSOAccessTokenFetcher(
OAuth2AccessTokenConsumer* consumer,
ios::ProfileOAuth2TokenServiceIOSProvider* provider,
const std::string account_id)
: OAuth2AccessTokenFetcher(consumer),
weak_factory_(this),
provider_(provider),
account_id_(account_id),
request_was_cancelled_(false) {
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);
}
}
// Fetcher that returns INVALID_GAIA_CREDENTIALS responses for all requests.
class InvalidGrantAccessTokenFetcher : public OAuth2AccessTokenFetcher {
public:
explicit InvalidGrantAccessTokenFetcher(OAuth2AccessTokenConsumer* consumer);
virtual ~InvalidGrantAccessTokenFetcher();
// OAuth2AccessTokenFetcher
virtual void Start(const std::string& client_id,
const std::string& client_secret,
const std::vector<std::string>& scopes) OVERRIDE;
virtual void CancelRequest() OVERRIDE;
// Fires token failure notifications with INVALID_GAIA_CREDENTIALS error.
void FireInvalidGrant();
private:
bool request_was_cancelled_;
DISALLOW_COPY_AND_ASSIGN(InvalidGrantAccessTokenFetcher);
};
InvalidGrantAccessTokenFetcher::InvalidGrantAccessTokenFetcher(
OAuth2AccessTokenConsumer* consumer)
: OAuth2AccessTokenFetcher(consumer),
request_was_cancelled_(false) {}
InvalidGrantAccessTokenFetcher::~InvalidGrantAccessTokenFetcher() {}
void InvalidGrantAccessTokenFetcher::Start(
const std::string& client_id,
const std::string& client_secret,
const std::vector<std::string>& scopes) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&InvalidGrantAccessTokenFetcher::FireInvalidGrant,
base::Unretained(this)));
};
void InvalidGrantAccessTokenFetcher::FireInvalidGrant() {
if (request_was_cancelled_)
return;
GoogleServiceAuthError auth_error(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
FireOnGetTokenFailure(auth_error);
}
void InvalidGrantAccessTokenFetcher::CancelRequest() {
request_was_cancelled_ = true;
}
} // namespace
ProfileOAuth2TokenServiceIOS::AccountInfo::AccountInfo(
ProfileOAuth2TokenService* token_service,
const std::string& account_id)
: token_service_(token_service),
account_id_(account_id),
last_auth_error_(GoogleServiceAuthError::NONE) {
DCHECK(token_service_);
DCHECK(!account_id_.empty());
token_service_->signin_error_controller()->AddProvider(this);
}
ProfileOAuth2TokenServiceIOS::AccountInfo::~AccountInfo() {
token_service_->signin_error_controller()->RemoveProvider(this);
}
void ProfileOAuth2TokenServiceIOS::AccountInfo::SetLastAuthError(
const GoogleServiceAuthError& error) {
if (error.state() != last_auth_error_.state()) {
last_auth_error_ = error;
token_service_->signin_error_controller()->AuthStatusChanged();
}
}
std::string ProfileOAuth2TokenServiceIOS::AccountInfo::GetAccountId() const {
return account_id_;
}
GoogleServiceAuthError
ProfileOAuth2TokenServiceIOS::AccountInfo::GetAuthStatus() const {
return last_auth_error_;
}
ProfileOAuth2TokenServiceIOS::ProfileOAuth2TokenServiceIOS()
: MutableProfileOAuth2TokenService(),
use_legacy_token_service_(false) {
DCHECK(thread_checker_.CalledOnValidThread());
}
ProfileOAuth2TokenServiceIOS::~ProfileOAuth2TokenServiceIOS() {
DCHECK(thread_checker_.CalledOnValidThread());
}
void ProfileOAuth2TokenServiceIOS::Initialize(SigninClient* client) {
DCHECK(thread_checker_.CalledOnValidThread());
MutableProfileOAuth2TokenService::Initialize(client);
}
void ProfileOAuth2TokenServiceIOS::Shutdown() {
DCHECK(thread_checker_.CalledOnValidThread());
CancelAllRequests();
accounts_.clear();
MutableProfileOAuth2TokenService::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());
use_legacy_token_service_ = !GetProvider()->IsUsingSharedAuthentication();
if (use_legacy_token_service_) {
MutableProfileOAuth2TokenService::LoadCredentials(primary_account_id);
return;
}
GetProvider()->InitializeSharedAuthentication();
ReloadCredentials();
FireRefreshTokensLoaded();
}
void ProfileOAuth2TokenServiceIOS::ReloadCredentials() {
DCHECK(thread_checker_.CalledOnValidThread());
if (use_legacy_token_service_) {
NOTREACHED();
return;
}
// Remove all old accounts that do not appear in |new_accounts| and then
// load |new_accounts|.
std::vector<std::string> new_accounts(GetProvider()->GetAllAccountIds());
std::vector<std::string> old_accounts(GetAccounts());
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());
if (use_legacy_token_service_) {
MutableProfileOAuth2TokenService::UpdateCredentials(account_id,
refresh_token);
return;
}
NOTREACHED() << "Unexpected call to UpdateCredentials when using shared "
"authentication.";
}
void ProfileOAuth2TokenServiceIOS::RevokeAllCredentials() {
DCHECK(thread_checker_.CalledOnValidThread());
if (use_legacy_token_service_) {
MutableProfileOAuth2TokenService::RevokeAllCredentials();
return;
}
CancelAllRequests();
ClearCache();
AccountInfoMap toRemove = accounts_;
for (AccountInfoMap::iterator i = toRemove.begin(); i != toRemove.end(); ++i)
RemoveAccount(i->first);
DCHECK_EQ(0u, accounts_.size());
}
OAuth2AccessTokenFetcher*
ProfileOAuth2TokenServiceIOS::CreateAccessTokenFetcher(
const std::string& account_id,
net::URLRequestContextGetter* getter,
OAuth2AccessTokenConsumer* consumer) {
if (use_legacy_token_service_) {
std::string refresh_token = GetRefreshToken(account_id);
DCHECK(!refresh_token.empty());
if (refresh_token == kForceInvalidGrantResponsesRefreshToken) {
return new InvalidGrantAccessTokenFetcher(consumer);
} else {
return MutableProfileOAuth2TokenService::CreateAccessTokenFetcher(
account_id, getter, consumer);
}
}
return new SSOAccessTokenFetcher(consumer, GetProvider(), account_id);
}
void ProfileOAuth2TokenServiceIOS::ForceInvalidGrantResponses() {
if (!use_legacy_token_service_) {
NOTREACHED();
return;
}
std::vector<std::string> accounts =
MutableProfileOAuth2TokenService::GetAccounts();
if (accounts.empty()) {
NOTREACHED();
return;
}
std::string first_account_id = *accounts.begin();
if (RefreshTokenIsAvailable(first_account_id) &&
GetRefreshToken(first_account_id) !=
kForceInvalidGrantResponsesRefreshToken) {
MutableProfileOAuth2TokenService::RevokeAllCredentials();
}
for (auto i = accounts.begin(); i != accounts.end(); ++i) {
std::string account_id = *i;
MutableProfileOAuth2TokenService::UpdateCredentials(
account_id,
kForceInvalidGrantResponsesRefreshToken);
}
}
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 |MutableProfileOAuth2TokenService::InvalidateOAuth2Token| to clear the
// cached access token.
MutableProfileOAuth2TokenService::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());
if (use_legacy_token_service_) {
return MutableProfileOAuth2TokenService::GetAccounts();
}
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());
if (use_legacy_token_service_) {
return MutableProfileOAuth2TokenService::RefreshTokenIsAvailable(
account_id);
}
return accounts_.count(account_id) > 0;
}
std::string ProfileOAuth2TokenServiceIOS::GetRefreshToken(
const std::string& account_id) const {
DCHECK(thread_checker_.CalledOnValidThread());
if (use_legacy_token_service_)
return MutableProfileOAuth2TokenService::GetRefreshToken(account_id);
// On iOS, the refresh token does not exist as ProfileOAuth2TokenServiceIOS
// fetches the access token from the iOS authentication library.
NOTREACHED();
return std::string();
}
std::string
ProfileOAuth2TokenServiceIOS::GetRefreshTokenWhenNotUsingSharedAuthentication(
const std::string& account_id) {
DCHECK(use_legacy_token_service_);
return GetRefreshToken(account_id);
}
void ProfileOAuth2TokenServiceIOS::UpdateAuthError(
const std::string& account_id,
const GoogleServiceAuthError& error) {
DCHECK(thread_checker_.CalledOnValidThread());
if (use_legacy_token_service_) {
MutableProfileOAuth2TokenService::UpdateAuthError(account_id, error);
return;
}
// 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(this, 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) {
CancelRequestsForAccount(account_id);
ClearCacheForAccount(account_id);
accounts_.erase(account_id);
FireRefreshTokenRevoked(account_id);
}
}
void ProfileOAuth2TokenServiceIOS::StartUsingSharedAuthentication() {
if (!use_legacy_token_service_)
return;
MutableProfileOAuth2TokenService::RevokeAllCredentials();
use_legacy_token_service_ = false;
}
void ProfileOAuth2TokenServiceIOS::SetUseLegacyTokenServiceForTesting(
bool use_legacy_token_service) {
use_legacy_token_service_ = use_legacy_token_service;
}
# 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.
{
'variables': {
'chromium_code': 1,
},
'targets': [
{
'target_name': 'ios_components',
'type': 'none',
'include_dirs': [
'../..',
],
'sources': [
'../public/provider/components/signin/browser/profile_oauth2_token_service_ios_provider.h',
]
},
],
}
include_rules = [
# The public interfaces cannot reference Chromium code, so all allowances
# that the top-level DEPS file introduces are removed here. This list should
# be kept in sync with src/DEPS.
"-base",
"-build",
"-library_loaders",
"-testing",
"-third_party/icu/source/common/unicode",
"-third_party/icu/source/i18n/unicode",
"-url",
]
// 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.
#ifndef IOS_PUBLIC_PROVIDER_COMPONENTS_SIGNIN_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_PROVIDER_H_
#define IOS_PUBLIC_PROVIDER_COMPONENTS_SIGNIN_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_PROVIDER_H_
#if defined(__OBJC__)
@class NSDate;
@class NSError;
@class NSString;
#else
class NSDate;
class NSError;
class NSString;
#endif // defined(__OBJC__)
#include <set>
#include <string>
#include <vector>
#include "base/callback.h"
namespace ios {
enum AuthenticationErrorCategory {
// Unknown errors.
kAuthenticationErrorCategoryUnknownErrors,
// Authorization errors.
kAuthenticationErrorCategoryAuthorizationErrors,
// Authorization errors with HTTP_FORBIDDEN (403) error code.
kAuthenticationErrorCategoryAuthorizationForbiddenErrors,
// Network server errors includes parsing error and should be treated as
// transient/offline errors.
kAuthenticationErrorCategoryNetworkServerErrors,
// User cancellation errors should be handled by treating them as a no-op.
kAuthenticationErrorCategoryUserCancellationErrors,
// User identity not found errors.
kAuthenticationErrorCategoryUnknownIdentityErrors,
};
// Interface that provides support for ProfileOAuth2TokenServiceIOS.
class ProfileOAuth2TokenServiceIOSProvider {
public:
typedef base::Callback<void(NSString* token,
NSDate* expiration,
NSError* error)> AccessTokenCallback;
ProfileOAuth2TokenServiceIOSProvider() {};
virtual ~ProfileOAuth2TokenServiceIOSProvider() {};
// Returns whether authentication is using the shared authentication library.
virtual bool IsUsingSharedAuthentication() const = 0;
// Initializes the shared authentication library. This method should be called
// when loading credentials if the user is signed in to Chrome via the shared
// authentication library.
virtual void InitializeSharedAuthentication() = 0;
// Returns the ids of all accounts.
virtual std::vector<std::string> GetAllAccountIds() = 0;
// Starts fetching an access token for the account with id |account_id| with
// the given |scopes|. Once the token is obtained, |callback| is called.
virtual void GetAccessToken(const std::string& account_id,
const std::string& client_id,
const std::string& client_secret,
const std::set<std::string>& scopes,
const AccessTokenCallback& callback) = 0;
// Returns the authentication error category of |error|.
virtual AuthenticationErrorCategory GetAuthenticationErrorCategory(
NSError* error) const = 0;
};
} // namespace ios
#endif // IOS_PUBLIC_PROVIDER_COMPONENTS_SIGNIN_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_PROVIDER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment