Chromium Code Reviews| Index: google_apis/gaia/oauth2_token_service_request.cc |
| diff --git a/chrome/browser/signin/profile_oauth2_token_service_request.cc b/google_apis/gaia/oauth2_token_service_request.cc |
| similarity index 16% |
| rename from chrome/browser/signin/profile_oauth2_token_service_request.cc |
| rename to google_apis/gaia/oauth2_token_service_request.cc |
| index caa2f3034c340db811bee18cf8d186cc214caaad..c946fde088e89f31d7edbf1206bfe22adbbe1e4a 100644 |
| --- a/chrome/browser/signin/profile_oauth2_token_service_request.cc |
| +++ b/google_apis/gaia/oauth2_token_service_request.cc |
| @@ -1,43 +1,148 @@ |
| -// Copyright 2012 The Chromium Authors. All rights reserved. |
| +// 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 "chrome/browser/signin/profile_oauth2_token_service_request.h" |
| +#include "google_apis/gaia/oauth2_token_service_request.h" |
| #include "base/bind.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/thread_task_runner_handle.h" |
| -#include "chrome/browser/profiles/profile.h" |
| -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
| -#include "chrome/browser/signin/signin_manager_factory.h" |
| -#include "components/signin/core/browser/profile_oauth2_token_service.h" |
| -#include "components/signin/core/browser/signin_manager.h" |
| -#include "content/public/browser/browser_thread.h" |
| #include "google_apis/gaia/google_service_auth_error.h" |
| #include "google_apis/gaia/oauth2_access_token_consumer.h" |
| -class ProfileOAuth2TokenServiceRequest::Core |
| - : public base::RefCountedThreadSafe<ProfileOAuth2TokenServiceRequest::Core>, |
| - public OAuth2TokenService::Consumer { |
| +OAuth2TokenServiceRequest::TokenServiceProvider::TokenServiceProvider() { |
| +} |
| + |
| +OAuth2TokenServiceRequest::TokenServiceProvider::~TokenServiceProvider() { |
| +} |
| + |
| +// Core serves as the base class for OAuth2TokenService operations. Each |
| +// operation should be modeled as a derived type. |
| +// |
| +// Core is used like this: |
| +// |
| +// 1. Constructed on owner thread. |
| +// |
| +// 2. Start() is called on owner thread, which calls StartOnTokenServiceThread() |
| +// on token service thread. |
| +// |
| +// 3. Request is executed. |
| +// |
| +// 4. Stop() is called on owner thread, which calls StopOnTokenServiceThread() |
| +// on token service thread. |
| +// |
| +// 5. Core is destroyed on owner thread. |
| +class OAuth2TokenServiceRequest::Core |
| + : public base::NonThreadSafe, |
| + public base::RefCountedThreadSafe<OAuth2TokenServiceRequest::Core> { |
| public: |
| // Note the thread where an instance of Core is constructed is referred to as |
| - // the "owner thread" here. This will be the thread of |owner_task_runner_|. |
| - Core(Profile* profile, |
| - ProfileOAuth2TokenServiceRequest* owner); |
| - // Starts fetching an OAuth2 access token for |account_id| and |scopes|. It |
| - // should be called on the owner thread. |
| - void Start( |
| - const std::string& account_id, |
| - const OAuth2TokenService::ScopeSet& scopes); |
| - // Stops the OAuth2 access token fetching. It should be called on the owner |
| - // thread. |
| + // the "owner thread" here. |
| + Core(OAuth2TokenServiceRequest* owner, TokenServiceProvider* provider); |
| + |
| + // Starts the core. Must be called on the owner thread. |
| + void Start(); |
| + |
| + // Stops the core. Must be called on the owner thread. |
| void Stop(); |
| - OAuth2TokenService::Request* request(); |
| + // Returns true if this object has been stopped. Must be called on the owner |
| + // thread. |
| + bool IsStopped() const; |
| + |
| + protected: |
| + // Core must be destroyed on the owner thread. If data members must be |
| + // cleaned up or destroyed on the token service thread, do so in the |
| + // StopOnTokenServiceThread method. |
| + virtual ~Core(); |
| + |
| + // Called on the token service thread. |
| + virtual void StartOnTokenServiceThread() = 0; |
| + |
| + // Called on the token service thread. |
| + virtual void StopOnTokenServiceThread() = 0; |
| + |
| + base::SingleThreadTaskRunner* token_service_task_runner(); |
| + OAuth2TokenService* token_service(); |
| + OAuth2TokenServiceRequest* owner(); |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<OAuth2TokenServiceRequest::Core>; |
| + |
| + scoped_refptr<base::SingleThreadTaskRunner> token_service_task_runner_; |
| + OAuth2TokenServiceRequest* owner_; |
| + TokenServiceProvider* provider_; |
| + DISALLOW_COPY_AND_ASSIGN(Core); |
| +}; |
| + |
| +OAuth2TokenServiceRequest::Core::Core(OAuth2TokenServiceRequest* owner, |
| + TokenServiceProvider* provider) |
| + : owner_(owner), provider_(provider) { |
| + DCHECK(owner_); |
| + DCHECK(provider_); |
| + token_service_task_runner_ = provider_->GetTokenServiceTaskRunner(); |
| + DCHECK(token_service_task_runner_); |
| +} |
| + |
| +OAuth2TokenServiceRequest::Core::~Core() { |
| +} |
| + |
| +void OAuth2TokenServiceRequest::Core::Start() { |
| + DCHECK(CalledOnValidThread()); |
| + token_service_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&OAuth2TokenServiceRequest::Core::StartOnTokenServiceThread, |
| + this)); |
| +} |
| + |
| +void OAuth2TokenServiceRequest::Core::Stop() { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(!IsStopped()); |
| + |
| + // Detaches |owner_| from this instance so |owner_| will be called back only |
| + // if |Stop()| has never been called. |
| + owner_ = NULL; |
| + token_service_task_runner_->PostTask( |
|
blundell
2014/06/04 13:55:14
There's a bug here. This object requires that it's
maniscalco
2014/06/04 16:41:38
Good catch.
If we use PostTaskAndReply, the "owne
maniscalco
2014/06/04 17:29:42
blundell, I want to make sure I understand the Pos
|
| + FROM_HERE, |
| + base::Bind(&OAuth2TokenServiceRequest::Core::StopOnTokenServiceThread, |
| + this)); |
| +} |
| + |
| +bool OAuth2TokenServiceRequest::Core::IsStopped() const { |
| + DCHECK(CalledOnValidThread()); |
| + return owner_ == NULL; |
| +} |
| - // OAuth2TokenService::Consumer. It should be called on the UI thread. |
| +base::SingleThreadTaskRunner* |
| +OAuth2TokenServiceRequest::Core::token_service_task_runner() { |
| + return token_service_task_runner_; |
| +} |
| + |
| +OAuth2TokenService* OAuth2TokenServiceRequest::Core::token_service() { |
| + DCHECK(token_service_task_runner_->BelongsToCurrentThread()); |
| + return provider_->GetTokenService(); |
| +} |
| + |
| +OAuth2TokenServiceRequest* OAuth2TokenServiceRequest::Core::owner() { |
| + DCHECK(CalledOnValidThread()); |
| + return owner_; |
| +} |
| + |
| +namespace { |
| + |
| +// An implementation of Core for getting an access token. |
| +class RequestCore : public OAuth2TokenServiceRequest::Core, |
| + public OAuth2TokenService::Consumer { |
| + public: |
| + RequestCore(OAuth2TokenServiceRequest* owner, |
| + OAuth2TokenServiceRequest::TokenServiceProvider* provider, |
| + OAuth2TokenService::Consumer* consumer, |
| + const std::string& account_id, |
| + const OAuth2TokenService::ScopeSet& scopes); |
| + |
| + // OAuth2TokenService::Consumer. Must be called on the token service thread. |
| virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, |
| const std::string& access_token, |
| const base::Time& expiration_time) OVERRIDE; |
| @@ -45,187 +150,199 @@ class ProfileOAuth2TokenServiceRequest::Core |
| const GoogleServiceAuthError& error) OVERRIDE; |
| private: |
| - friend class |
| - base::RefCountedThreadSafe<ProfileOAuth2TokenServiceRequest::Core>; |
| + friend class base::RefCountedThreadSafe<RequestCore>; |
| - // Note this can be destructed on the owner thread or on the UI thread, |
| - // depending on the reference count. |
| - virtual ~Core(); |
| + // Must be destroyed on the owner thread. |
| + virtual ~RequestCore(); |
| - // Starts an OAuth2TokenService::Request on the UI thread. |
| - void StartOnUIThread( |
| - const std::string& account_id, |
| - const OAuth2TokenService::ScopeSet& scopes); |
| - // Stops the OAuth2TokenService::Request on the UI thread. |
| - void StopOnUIThread(); |
| + // Core implementation. |
| + virtual void StartOnTokenServiceThread() OVERRIDE; |
| + virtual void StopOnTokenServiceThread() OVERRIDE; |
| - // Method posted to the owner thread to call back |owner_|. Note when this |
| - // posted task is actually running on the owner thread, it is possible that |
| - // |owner_| has been reset NULL. |
| void InformOwnerOnGetTokenSuccess(std::string access_token, |
| base::Time expiration_time); |
| void InformOwnerOnGetTokenFailure(GoogleServiceAuthError error); |
| - // The profile with which this instance was initialized. |
| - Profile* const profile_; |
| - |
| - // The object to call back when fetching completes. |owner_| should be |
| - // called back only on the owner thread. |
| - ProfileOAuth2TokenServiceRequest* owner_; |
| - // Task runner on which |owner_| should be called back. |
| scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner_; |
| + OAuth2TokenService::Consumer* const consumer_; |
| + std::string account_id_; |
| + OAuth2TokenService::ScopeSet scopes_; |
| // OAuth2TokenService request for fetching OAuth2 access token; it should be |
| - // created, reset and accessed only on the UI thread. |
| + // created, reset and accessed only on the token service thread. |
| scoped_ptr<OAuth2TokenService::Request> request_; |
| - DISALLOW_COPY_AND_ASSIGN(Core); |
| + DISALLOW_COPY_AND_ASSIGN(RequestCore); |
| }; |
| -ProfileOAuth2TokenServiceRequest::Core::Core( |
| - Profile* profile, |
| - ProfileOAuth2TokenServiceRequest* owner) |
| - : OAuth2TokenService::Consumer("oauth2_token_service"), |
| - profile_(profile), |
| - owner_(owner), |
| - owner_task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
| - DCHECK(profile); |
| - DCHECK(owner); |
| -} |
| - |
| -ProfileOAuth2TokenServiceRequest::Core::~Core() { |
| -} |
| - |
| -void ProfileOAuth2TokenServiceRequest::Core::Start( |
| +RequestCore::RequestCore( |
| + OAuth2TokenServiceRequest* owner, |
| + OAuth2TokenServiceRequest::TokenServiceProvider* provider, |
| + OAuth2TokenService::Consumer* consumer, |
| const std::string& account_id, |
| - const OAuth2TokenService::ScopeSet& scopes) { |
| - DCHECK(owner_task_runner_->BelongsToCurrentThread()); |
| - |
| - if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { |
| - StartOnUIThread(account_id, scopes); |
| - } else { |
| - content::BrowserThread::PostTask( |
| - content::BrowserThread::UI, |
| - FROM_HERE, |
| - base::Bind(&ProfileOAuth2TokenServiceRequest::Core::StartOnUIThread, |
| - this, account_id, scopes)); |
| - } |
| + const OAuth2TokenService::ScopeSet& scopes) |
| + : OAuth2TokenServiceRequest::Core(owner, provider), |
| + OAuth2TokenService::Consumer("oauth2_token_service"), |
| + owner_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| + consumer_(consumer), |
| + account_id_(account_id), |
| + scopes_(scopes) { |
| + DCHECK(consumer_); |
| + DCHECK(!account_id_.empty()); |
| + DCHECK(!scopes_.empty()); |
| } |
| -void ProfileOAuth2TokenServiceRequest::Core::Stop() { |
| - DCHECK(owner_task_runner_->BelongsToCurrentThread()); |
| - |
| - // Detaches |owner_| from this instance so |owner_| will be called back only |
| - // if |Stop()| has never been called. |
| - owner_ = NULL; |
| - if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { |
| - StopOnUIThread(); |
| - } else { |
| - content::BrowserThread::PostTask( |
| - content::BrowserThread::UI, |
| - FROM_HERE, |
| - base::Bind(&ProfileOAuth2TokenServiceRequest::Core::StopOnUIThread, |
| - this)); |
| - } |
| +RequestCore::~RequestCore() { |
| } |
| -OAuth2TokenService::Request* ProfileOAuth2TokenServiceRequest::Core::request() { |
| - return request_.get(); |
| +void RequestCore::StartOnTokenServiceThread() { |
| + DCHECK(token_service_task_runner()->BelongsToCurrentThread()); |
| + request_ = token_service()->StartRequest(account_id_, scopes_, this).Pass(); |
| } |
| -void ProfileOAuth2TokenServiceRequest::Core::StopOnUIThread() { |
| - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| +void RequestCore::StopOnTokenServiceThread() { |
| + DCHECK(token_service_task_runner()->BelongsToCurrentThread()); |
| request_.reset(); |
| } |
| -void ProfileOAuth2TokenServiceRequest::Core::StartOnUIThread( |
| - const std::string& account_id, |
| - const OAuth2TokenService::ScopeSet& scopes) { |
| - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| - |
| - ProfileOAuth2TokenService* service = |
| - ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| - DCHECK(service); |
| - SigninManagerBase* signin_manager = |
| - SigninManagerFactory::GetForProfile(profile_); |
| - DCHECK(signin_manager); |
| - std::string account_id_to_use = |
| - account_id.empty() ? signin_manager->GetAuthenticatedAccountId() |
| - : account_id; |
| - request_.reset( |
| - service->StartRequest(account_id_to_use, scopes, this).release()); |
| -} |
| - |
| -void ProfileOAuth2TokenServiceRequest::Core::OnGetTokenSuccess( |
| - const OAuth2TokenService::Request* request, |
| - const std::string& access_token, |
| - const base::Time& expiration_time) { |
| - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| +void RequestCore::OnGetTokenSuccess(const OAuth2TokenService::Request* request, |
| + const std::string& access_token, |
| + const base::Time& expiration_time) { |
| + DCHECK(token_service_task_runner()->BelongsToCurrentThread()); |
| DCHECK_EQ(request_.get(), request); |
| - owner_task_runner_->PostTask(FROM_HERE, base::Bind( |
| - &ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess, |
| - this, |
| - access_token, |
| - expiration_time)); |
| + owner_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&RequestCore::InformOwnerOnGetTokenSuccess, |
| + this, |
| + access_token, |
| + expiration_time)); |
| request_.reset(); |
| } |
| -void ProfileOAuth2TokenServiceRequest::Core::OnGetTokenFailure( |
| - const OAuth2TokenService::Request* request, |
| - const GoogleServiceAuthError& error) { |
| - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| +void RequestCore::OnGetTokenFailure(const OAuth2TokenService::Request* request, |
| + const GoogleServiceAuthError& error) { |
| + DCHECK(token_service_task_runner()->BelongsToCurrentThread()); |
| DCHECK_EQ(request_.get(), request); |
| - owner_task_runner_->PostTask(FROM_HERE, base::Bind( |
| - &ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure, |
| - this, |
| - error)); |
| + owner_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&RequestCore::InformOwnerOnGetTokenFailure, this, error)); |
| request_.reset(); |
| } |
| -void ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess( |
| - std::string access_token, |
| - base::Time expiration_time) { |
| - DCHECK(owner_task_runner_->BelongsToCurrentThread()); |
| +void RequestCore::InformOwnerOnGetTokenSuccess(std::string access_token, |
| + base::Time expiration_time) { |
| + DCHECK(CalledOnValidThread()); |
| + if (!IsStopped()) { |
| + consumer_->OnGetTokenSuccess(owner(), access_token, expiration_time); |
| + } |
| +} |
| - if (owner_) |
| - owner_->consumer_->OnGetTokenSuccess(owner_, access_token, expiration_time); |
| +void RequestCore::InformOwnerOnGetTokenFailure(GoogleServiceAuthError error) { |
| + DCHECK(CalledOnValidThread()); |
| + if (!IsStopped()) { |
| + consumer_->OnGetTokenFailure(owner(), error); |
| + } |
| } |
| -void ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure( |
| - GoogleServiceAuthError error) { |
| - DCHECK(owner_task_runner_->BelongsToCurrentThread()); |
| +// An implementation of Core for invalidating an access token. |
| +class InvalidateCore : public OAuth2TokenServiceRequest::Core { |
| + public: |
| + InvalidateCore(OAuth2TokenServiceRequest* owner, |
| + OAuth2TokenServiceRequest::TokenServiceProvider* provider, |
| + const std::string& access_token, |
| + const std::string& account_id, |
| + const OAuth2TokenService::ScopeSet& scopes); |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<InvalidateCore>; |
| + |
| + // Must be destroyed on the owner thread. |
| + virtual ~InvalidateCore(); |
| - if (owner_) |
| - owner_->consumer_->OnGetTokenFailure(owner_, error); |
| + // Core implementation. |
| + virtual void StartOnTokenServiceThread() OVERRIDE; |
| + virtual void StopOnTokenServiceThread() OVERRIDE; |
| + |
| + std::string access_token_; |
| + std::string account_id_; |
| + OAuth2TokenService::ScopeSet scopes_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(InvalidateCore); |
| +}; |
| + |
| +InvalidateCore::InvalidateCore( |
| + OAuth2TokenServiceRequest* owner, |
| + OAuth2TokenServiceRequest::TokenServiceProvider* provider, |
| + const std::string& access_token, |
| + const std::string& account_id, |
| + const OAuth2TokenService::ScopeSet& scopes) |
| + : OAuth2TokenServiceRequest::Core(owner, provider), |
| + access_token_(access_token), |
| + account_id_(account_id), |
| + scopes_(scopes) { |
| + DCHECK(!access_token_.empty()); |
| + DCHECK(!account_id_.empty()); |
| + DCHECK(!scopes.empty()); |
| +} |
| + |
| +InvalidateCore::~InvalidateCore() { |
| +} |
| + |
| +void InvalidateCore::StartOnTokenServiceThread() { |
| + DCHECK(token_service_task_runner()->BelongsToCurrentThread()); |
| + token_service()->InvalidateToken(account_id_, scopes_, access_token_); |
| +} |
| + |
| +void InvalidateCore::StopOnTokenServiceThread() { |
| + DCHECK(token_service_task_runner()->BelongsToCurrentThread()); |
| + // Nothing to do. |
| } |
| +} // namespace |
| + |
| // static |
| -ProfileOAuth2TokenServiceRequest* |
| - ProfileOAuth2TokenServiceRequest::CreateAndStart( |
| - Profile* profile, |
| - const std::string& account_id, |
| - const OAuth2TokenService::ScopeSet& scopes, |
| - OAuth2TokenService::Consumer* consumer) { |
| - return new ProfileOAuth2TokenServiceRequest(profile, account_id, scopes, |
| - consumer); |
| -} |
| - |
| -ProfileOAuth2TokenServiceRequest::ProfileOAuth2TokenServiceRequest( |
| - Profile* profile, |
| +scoped_ptr<OAuth2TokenServiceRequest> OAuth2TokenServiceRequest::CreateAndStart( |
| + TokenServiceProvider* provider, |
| const std::string& account_id, |
| const OAuth2TokenService::ScopeSet& scopes, |
| - OAuth2TokenService::Consumer* consumer) |
| - : consumer_(consumer), |
| - core_(new Core(profile, this)) { |
| - core_->Start(account_id, scopes); |
| + OAuth2TokenService::Consumer* consumer) { |
| + scoped_ptr<OAuth2TokenServiceRequest> request( |
| + new OAuth2TokenServiceRequest(account_id)); |
| + scoped_refptr<Core> core( |
| + new RequestCore(request.get(), provider, consumer, account_id, scopes)); |
| + request->StartWithCore(core); |
| + return request.Pass(); |
| } |
| -ProfileOAuth2TokenServiceRequest::~ProfileOAuth2TokenServiceRequest() { |
| - DCHECK(CalledOnValidThread()); |
| +// static |
| +void OAuth2TokenServiceRequest::InvalidateToken( |
| + OAuth2TokenServiceRequest::TokenServiceProvider* provider, |
| + const std::string& account_id, |
| + const OAuth2TokenService::ScopeSet& scopes, |
| + const std::string& access_token) { |
| + scoped_ptr<OAuth2TokenServiceRequest> request( |
| + new OAuth2TokenServiceRequest(account_id)); |
| + scoped_refptr<Core> core(new InvalidateCore( |
| + request.get(), provider, access_token, account_id, scopes)); |
| + request->StartWithCore(core); |
| +} |
| + |
| +OAuth2TokenServiceRequest::~OAuth2TokenServiceRequest() { |
| core_->Stop(); |
| } |
| -std::string ProfileOAuth2TokenServiceRequest::GetAccountId() const { |
| - return core_->request()->GetAccountId(); |
| +std::string OAuth2TokenServiceRequest::GetAccountId() const { |
| + return account_id_; |
| } |
| +OAuth2TokenServiceRequest::OAuth2TokenServiceRequest( |
| + const std::string& account_id) |
| + : account_id_(account_id) { |
| + DCHECK(!account_id_.empty()); |
| +} |
| + |
| +void OAuth2TokenServiceRequest::StartWithCore(const scoped_refptr<Core>& core) { |
| + DCHECK(core); |
| + core_ = core; |
| + core_->Start(); |
| +} |