Commit 646f29b4 authored by Colin Blundell's avatar Colin Blundell Committed by Commit Bot

IdentityProvider: Provide explicit interface to fetch access tokens

One of IdentityProvider's clients' use cases is to fetch access tokens
for the active account. IdentityProvider currently provides no explicit
mechanism for this, instead letting clients directly interact with the
underlying OAuth2TokenService instance via GetTokenService(). However,
it's necessary to decouple IdentityProvider from OAuth2TokenService at
an interface level in order to allow for porting ProfileIdentityProvider
to be backed by IdentityManager.

This CL adds an explicit interface for clients of IdentityProvider to
request access tokens for the active account. This interface is
currently implemented directly in IdentityProvider itself, as it is
common to ProfileIdentityProvider and DeviceIdentityProvider. Before
porting ProfileIdentityProvider to be backed by IdentityManager we
will move this implementation out into those two derived classes,
temporarily duplicating it. However, we will only do that when we are
just at the point of porting ProfileIdentityProvider away from using
ProfileOAuth2TokenService.

Bug: 809452
Change-Id: I402af0cb19b5e0057edc3870ca2a8f564f4f8e10
Reviewed-on: https://chromium-review.googlesource.com/1089051Reviewed-by: default avatarPavel Yatsuk <pavely@chromium.org>
Commit-Queue: Colin Blundell <blundell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565584}
parent 312c8aec
......@@ -12,7 +12,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "components/gcm_driver/gcm_driver.h"
#include "components/invalidation/impl/gcm_invalidation_bridge.h"
#include "components/invalidation/public/identity_provider.h"
#include "google_apis/gaia/gaia_constants.h"
namespace invalidation {
......@@ -173,8 +172,7 @@ void GCMInvalidationBridge::Core::OnStoreReset() {
GCMInvalidationBridge::GCMInvalidationBridge(
gcm::GCMDriver* gcm_driver,
IdentityProvider* identity_provider)
: OAuth2TokenService::Consumer("gcm_network_channel"),
gcm_driver_(gcm_driver),
: gcm_driver_(gcm_driver),
identity_provider_(identity_provider),
subscribed_for_incoming_messages_(false),
weak_factory_(this) {}
......@@ -205,7 +203,7 @@ void GCMInvalidationBridge::CoreInitializationDone(
void GCMInvalidationBridge::RequestToken(
syncer::GCMNetworkChannelDelegate::RequestTokenCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (access_token_request_ != nullptr) {
if (access_token_fetcher_ != nullptr) {
// Report previous request as cancelled.
GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
std::string access_token;
......@@ -220,41 +218,22 @@ void GCMInvalidationBridge::RequestToken(
request_token_callback_ = callback;
OAuth2TokenService::ScopeSet scopes;
scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
access_token_request_ = identity_provider_->GetTokenService()->StartRequest(
identity_provider_->GetActiveAccountId(), scopes, this);
access_token_fetcher_ = identity_provider_->FetchAccessToken(
"gcm_network_channel", scopes,
base::BindOnce(&GCMInvalidationBridge::OnAccessTokenRequestCompleted,
base::Unretained(this)));
}
void GCMInvalidationBridge::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) {
void GCMInvalidationBridge::OnAccessTokenRequestCompleted(
GoogleServiceAuthError error,
std::string access_token) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(access_token_request_.get(), request);
core_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
core_,
request_token_callback_,
GoogleServiceAuthError::AuthErrorNone(),
access_token));
request_token_callback_.Reset();
access_token_request_.reset();
}
void GCMInvalidationBridge::OnGetTokenFailure(
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(access_token_request_.get(), request);
core_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished,
core_,
request_token_callback_,
error,
std::string()));
base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, core_,
request_token_callback_, error, access_token));
request_token_callback_.Reset();
access_token_request_.reset();
access_token_fetcher_.reset();
}
void GCMInvalidationBridge::InvalidateToken(const std::string& token) {
......
......@@ -16,7 +16,7 @@
#include "components/gcm_driver/gcm_client.h"
#include "components/gcm_driver/gcm_connection_observer.h"
#include "components/invalidation/impl/gcm_network_channel_delegate.h"
#include "google_apis/gaia/oauth2_token_service.h"
#include "components/invalidation/public/identity_provider.h"
namespace base {
class SingleThreadTaskRunner;
......@@ -36,8 +36,7 @@ class IdentityProvider;
// all function calls to GCMInvalidationBridge which does actual work to perform
// them.
class GCMInvalidationBridge : public gcm::GCMAppHandler,
public gcm::GCMConnectionObserver,
public OAuth2TokenService::Consumer {
public gcm::GCMConnectionObserver {
public:
class Core;
......@@ -45,12 +44,8 @@ class GCMInvalidationBridge : public gcm::GCMAppHandler,
IdentityProvider* identity_provider);
~GCMInvalidationBridge() override;
// OAuth2TokenService::Consumer implementation.
void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) override;
void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) override;
void OnAccessTokenRequestCompleted(GoogleServiceAuthError error,
std::string access_token);
// gcm::GCMAppHandler implementation.
void ShutdownHandler() override;
......@@ -99,7 +94,7 @@ class GCMInvalidationBridge : public gcm::GCMAppHandler,
scoped_refptr<base::SingleThreadTaskRunner> core_thread_task_runner_;
// Fields related to RequestToken function.
std::unique_ptr<OAuth2TokenService::Request> access_token_request_;
std::unique_ptr<ActiveAccountAccessTokenFetcher> access_token_fetcher_;
syncer::GCMNetworkChannelDelegate::RequestTokenCallback
request_token_callback_;
bool subscribed_for_incoming_messages_;
......
......@@ -61,8 +61,7 @@ TiclInvalidationService::TiclInvalidationService(
std::unique_ptr<TiclSettingsProvider> settings_provider,
gcm::GCMDriver* gcm_driver,
const scoped_refptr<net::URLRequestContextGetter>& request_context)
: OAuth2TokenService::Consumer("ticl_invalidation"),
user_agent_(user_agent),
: user_agent_(user_agent),
identity_provider_(std::move(identity_provider)),
settings_provider_(std::move(settings_provider)),
invalidator_registrar_(new syncer::InvalidatorRegistrar()),
......@@ -182,7 +181,7 @@ void TiclInvalidationService::RequestDetailedStatus(
void TiclInvalidationService::RequestAccessToken() {
// Only one active request at a time.
if (access_token_request_ != nullptr)
if (access_token_fetcher_ != nullptr)
return;
request_access_token_retry_timer_.Stop();
OAuth2TokenService::ScopeSet oauth2_scopes;
......@@ -195,16 +194,24 @@ void TiclInvalidationService::RequestAccessToken() {
token_service->InvalidateAccessToken(account_id, oauth2_scopes,
access_token_);
access_token_.clear();
access_token_request_ =
token_service->StartRequest(account_id, oauth2_scopes, this);
access_token_fetcher_ = identity_provider_->FetchAccessToken(
"ticl_invalidation", oauth2_scopes,
base::BindOnce(&TiclInvalidationService::OnAccessTokenRequestCompleted,
base::Unretained(this)));
}
void TiclInvalidationService::OnAccessTokenRequestCompleted(
GoogleServiceAuthError error,
std::string access_token) {
access_token_fetcher_.reset();
if (error.state() == GoogleServiceAuthError::NONE)
OnAccessTokenRequestSucceeded(access_token);
else
OnAccessTokenRequestFailed(error);
}
void TiclInvalidationService::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) {
DCHECK_EQ(access_token_request_.get(), request);
access_token_request_.reset();
void TiclInvalidationService::OnAccessTokenRequestSucceeded(
std::string access_token) {
// Reset backoff time after successful response.
request_access_token_backoff_.Reset();
access_token_ = access_token;
......@@ -215,12 +222,9 @@ void TiclInvalidationService::OnGetTokenSuccess(
}
}
void TiclInvalidationService::OnGetTokenFailure(
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) {
DCHECK_EQ(access_token_request_.get(), request);
void TiclInvalidationService::OnAccessTokenRequestFailed(
GoogleServiceAuthError error) {
DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
access_token_request_.reset();
switch (error.state()) {
case GoogleServiceAuthError::CONNECTION_FAILED:
case GoogleServiceAuthError::SERVICE_UNAVAILABLE: {
......@@ -262,7 +266,7 @@ void TiclInvalidationService::OnActiveAccountRefreshTokenRemoved() {
}
void TiclInvalidationService::OnActiveAccountLogout() {
access_token_request_.reset();
access_token_fetcher_.reset();
request_access_token_retry_timer_.Stop();
if (gcm_invalidation_bridge_)
......
......@@ -43,7 +43,6 @@ class GCMInvalidationBridge;
// This InvalidationService wraps the C++ Invalidation Client (TICL) library.
// It provides invalidations for desktop platforms (Win, Mac, Linux).
class TiclInvalidationService : public InvalidationService,
public OAuth2TokenService::Consumer,
public IdentityProvider::Observer,
public TiclSettingsProvider::Observer,
public syncer::InvalidationHandler {
......@@ -84,12 +83,10 @@ class TiclInvalidationService : public InvalidationService,
void RequestAccessToken();
// OAuth2TokenService::Consumer implementation
void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) override;
void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) override;
void OnAccessTokenRequestCompleted(GoogleServiceAuthError error,
std::string access_token);
void OnAccessTokenRequestSucceeded(std::string access_token);
void OnAccessTokenRequestFailed(GoogleServiceAuthError error);
// IdentityProvider::Observer implementation.
void OnActiveAccountRefreshTokenUpdated() override;
......@@ -137,9 +134,9 @@ class TiclInvalidationService : public InvalidationService,
// invalidate it with OAuth2TokenService.
std::string access_token_;
// TiclInvalidationService needs to hold reference to access_token_request_
// TiclInvalidationService needs to hold reference to access_token_fetcher_
// for the duration of request in order to receive callbacks.
std::unique_ptr<OAuth2TokenService::Request> access_token_request_;
std::unique_ptr<ActiveAccountAccessTokenFetcher> access_token_fetcher_;
base::OneShotTimer request_access_token_retry_timer_;
net::BackoffEntry request_access_token_backoff_;
......
......@@ -6,10 +6,88 @@
namespace invalidation {
class ActiveAccountAccessTokenFetcherImpl
: public ActiveAccountAccessTokenFetcher,
OAuth2TokenService::Consumer {
public:
ActiveAccountAccessTokenFetcherImpl(
const std::string& active_account_id,
const std::string& oauth_consumer_name,
OAuth2TokenService* token_service,
const OAuth2TokenService::ScopeSet& scopes,
ActiveAccountAccessTokenCallback callback);
~ActiveAccountAccessTokenFetcherImpl() override = default;
private:
// OAuth2TokenService::Consumer implementation.
void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) override;
void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) override;
// Invokes |callback_| with (|access_token|, |error|).
void HandleTokenRequestCompletion(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error,
const std::string& access_token);
ActiveAccountAccessTokenCallback callback_;
std::unique_ptr<OAuth2TokenService::Request> access_token_request_;
DISALLOW_COPY_AND_ASSIGN(ActiveAccountAccessTokenFetcherImpl);
};
ActiveAccountAccessTokenFetcherImpl::ActiveAccountAccessTokenFetcherImpl(
const std::string& active_account_id,
const std::string& oauth_consumer_name,
OAuth2TokenService* token_service,
const OAuth2TokenService::ScopeSet& scopes,
ActiveAccountAccessTokenCallback callback)
: OAuth2TokenService::Consumer(oauth_consumer_name),
callback_(std::move(callback)) {
access_token_request_ =
token_service->StartRequest(active_account_id, scopes, this);
}
void ActiveAccountAccessTokenFetcherImpl::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) {
HandleTokenRequestCompletion(request, GoogleServiceAuthError::AuthErrorNone(),
access_token);
}
void ActiveAccountAccessTokenFetcherImpl::OnGetTokenFailure(
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) {
HandleTokenRequestCompletion(request, error, std::string());
}
void ActiveAccountAccessTokenFetcherImpl::HandleTokenRequestCompletion(
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error,
const std::string& access_token) {
DCHECK_EQ(request, access_token_request_.get());
std::unique_ptr<OAuth2TokenService::Request> request_deleter(
std::move(access_token_request_));
std::move(callback_).Run(error, access_token);
}
IdentityProvider::Observer::~Observer() {}
IdentityProvider::~IdentityProvider() {}
std::unique_ptr<ActiveAccountAccessTokenFetcher>
IdentityProvider::FetchAccessToken(const std::string& oauth_consumer_name,
const OAuth2TokenService::ScopeSet& scopes,
ActiveAccountAccessTokenCallback callback) {
return std::make_unique<ActiveAccountAccessTokenFetcherImpl>(
GetActiveAccountId(), oauth_consumer_name, GetTokenService(), scopes,
std::move(callback));
}
void IdentityProvider::AddObserver(Observer* observer) {
// See the comment on |num_observers_| in the .h file for why this addition
// must happen here.
......
......@@ -7,6 +7,7 @@
#include <string>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/observer_list.h"
......@@ -14,6 +15,18 @@
namespace invalidation {
// An opaque object that clients can use to control the lifetime of access
// token requests.
class ActiveAccountAccessTokenFetcher {
public:
ActiveAccountAccessTokenFetcher() = default;
virtual ~ActiveAccountAccessTokenFetcher() = default;
};
using ActiveAccountAccessTokenCallback =
base::OnceCallback<void(GoogleServiceAuthError error,
std::string access_token)>;
// Helper class that provides access to information about the "active GAIA
// account" with which invalidation should interact. The definition of the
// "active Gaia account is context-dependent": the purpose of this abstraction
......@@ -58,6 +71,15 @@ class IdentityProvider : public OAuth2TokenService::Observer {
// Gets the token service vending OAuth tokens for all logged-in accounts.
virtual OAuth2TokenService* GetTokenService() = 0;
// Starts an access token request for |oauth_consumer_name| and |scopes|. When
// the request completes, |callback| will be invoked with the access token
// or error. To cancel the request, destroy the returned TokenFetcher.
std::unique_ptr<ActiveAccountAccessTokenFetcher> FetchAccessToken(
const std::string& oauth_consumer_name,
const OAuth2TokenService::ScopeSet& scopes,
ActiveAccountAccessTokenCallback callback);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
......
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