summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/signin.gypi21
-rw-r--r--components/signin/core/browser/signin_client.h14
-rw-r--r--components/signin/core/browser/test_signin_client.cc8
-rw-r--r--components/signin/core/browser/test_signin_client.h4
-rw-r--r--components/signin/ios/DEPS3
-rw-r--r--components/signin/ios/browser/profile_oauth2_token_service_ios.h163
-rw-r--r--components/signin/ios/browser/profile_oauth2_token_service_ios.mm498
-rw-r--r--ios/provider/ios_components.gyp20
-rw-r--r--ios/public/DEPS12
-rw-r--r--ios/public/provider/components/signin/browser/profile_oauth2_token_service_ios_provider.h78
10 files changed, 809 insertions, 12 deletions
diff --git a/components/signin.gypi b/components/signin.gypi
index aa09f77..5473b57 100644
--- a/components/signin.gypi
+++ b/components/signin.gypi
@@ -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',
+ ],
+ },
+ ],
+ }],
+ ],
}
diff --git a/components/signin/core/browser/signin_client.h b/components/signin/core/browser/signin_client.h
index 4b8837c..4187f47 100644
--- a/components/signin/core/browser/signin_client.h
+++ b/components/signin/core/browser/signin_client.h
@@ -17,6 +17,14 @@ class CanonicalCookie;
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
// embedder.
class SigninClient {
@@ -57,6 +65,12 @@ class SigninClient {
// Called when Google signin has succeeded.
virtual void GoogleSigninSucceeded(const std::string& username,
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_
diff --git a/components/signin/core/browser/test_signin_client.cc b/components/signin/core/browser/test_signin_client.cc
index 86bb74f..af05dd1 100644
--- a/components/signin/core/browser/test_signin_client.cc
+++ b/components/signin/core/browser/test_signin_client.cc
@@ -53,3 +53,11 @@ bool TestSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
void TestSigninClient::SetCookieChangedCallback(
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
diff --git a/components/signin/core/browser/test_signin_client.h b/components/signin/core/browser/test_signin_client.h
index ff82be0..03e0b88 100644
--- a/components/signin/core/browser/test_signin_client.h
+++ b/components/signin/core/browser/test_signin_client.h
@@ -39,6 +39,10 @@ class TestSigninClient : public SigninClient {
// Returns a TestURLRequestContextGetter.
virtual net::URLRequestContextGetter* GetURLRequestContext() OVERRIDE;
+#if defined(OS_IOS)
+ virtual ios::ProfileOAuth2TokenServiceIOSProvider* GetIOSProvider() OVERRIDE;
+#endif
+
// Returns true.
virtual bool ShouldMergeSigninCredentialsIntoCookieJar() OVERRIDE;
diff --git a/components/signin/ios/DEPS b/components/signin/ios/DEPS
new file mode 100644
index 0000000..9af4fb8
--- /dev/null
+++ b/components/signin/ios/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+ios/public/provider/components/signin",
+]
diff --git a/components/signin/ios/browser/profile_oauth2_token_service_ios.h b/components/signin/ios/browser/profile_oauth2_token_service_ios.h
new file mode 100644
index 0000000..2f32d1c
--- /dev/null
+++ b/components/signin/ios/browser/profile_oauth2_token_service_ios.h
@@ -0,0 +1,163 @@
+// 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_
diff --git a/components/signin/ios/browser/profile_oauth2_token_service_ios.mm b/components/signin/ios/browser/profile_oauth2_token_service_ios.mm
new file mode 100644
index 0000000..b17a701
--- /dev/null
+++ b/components/signin/ios/browser/profile_oauth2_token_service_ios.mm
@@ -0,0 +1,498 @@
+// 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;
+}
diff --git a/ios/provider/ios_components.gyp b/ios/provider/ios_components.gyp
new file mode 100644
index 0000000..002c43a
--- /dev/null
+++ b/ios/provider/ios_components.gyp
@@ -0,0 +1,20 @@
+# 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',
+ ]
+ },
+ ],
+}
diff --git a/ios/public/DEPS b/ios/public/DEPS
deleted file mode 100644
index c04c1d5..0000000
--- a/ios/public/DEPS
+++ /dev/null
@@ -1,12 +0,0 @@
-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",
-]
diff --git a/ios/public/provider/components/signin/browser/profile_oauth2_token_service_ios_provider.h b/ios/public/provider/components/signin/browser/profile_oauth2_token_service_ios_provider.h
new file mode 100644
index 0000000..d6f5238
--- /dev/null
+++ b/ios/public/provider/components/signin/browser/profile_oauth2_token_service_ios_provider.h
@@ -0,0 +1,78 @@
+// 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_