diff options
author | maniscalco@chromium.org <maniscalco@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-02 16:09:04 +0000 |
---|---|---|
committer | maniscalco@chromium.org <maniscalco@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-02 16:09:04 +0000 |
commit | 0dae69276ba560251e1f4c079ffd0a6130b57b06 (patch) | |
tree | 6464d23d0de1e9d3697da1f594b5347673ec1f35 /google_apis | |
parent | a4205207e8e6bba4ebe0946b9d0b34abe946065f (diff) | |
download | chromium_src-0dae69276ba560251e1f4c079ffd0a6130b57b06.zip chromium_src-0dae69276ba560251e1f4c079ffd0a6130b57b06.tar.gz chromium_src-0dae69276ba560251e1f4c079ffd0a6130b57b06.tar.bz2 |
Componentize and rename ProfileOAuth2TokenServiceRequest.
The purpose of this change is to move ProfileOAuth2TokenServiceRequest
into google_apis/gaia and drop any browser dependencies.
ProfileOAuth2TokenServiceRequest becomes OAuth2TokenServiceRequest.
Add support for invalidating tokens.
Review URL: https://codereview.chromium.org/299943003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274255 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'google_apis')
-rw-r--r-- | google_apis/gaia/oauth2_token_service_request.cc | 348 | ||||
-rw-r--r-- | google_apis/gaia/oauth2_token_service_request.h | 96 | ||||
-rw-r--r-- | google_apis/gaia/oauth2_token_service_request_unittest.cc | 257 | ||||
-rw-r--r-- | google_apis/google_apis.gyp | 3 |
4 files changed, 704 insertions, 0 deletions
diff --git a/google_apis/gaia/oauth2_token_service_request.cc b/google_apis/gaia/oauth2_token_service_request.cc new file mode 100644 index 0000000..c946fde --- /dev/null +++ b/google_apis/gaia/oauth2_token_service_request.cc @@ -0,0 +1,348 @@ +// 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 "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 "google_apis/gaia/google_service_auth_error.h" +#include "google_apis/gaia/oauth2_access_token_consumer.h" + +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. + 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(); + + // 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( + FROM_HERE, + base::Bind(&OAuth2TokenServiceRequest::Core::StopOnTokenServiceThread, + this)); +} + +bool OAuth2TokenServiceRequest::Core::IsStopped() const { + DCHECK(CalledOnValidThread()); + return owner_ == NULL; +} + +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; + virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) OVERRIDE; + + private: + friend class base::RefCountedThreadSafe<RequestCore>; + + // Must be destroyed on the owner thread. + virtual ~RequestCore(); + + // Core implementation. + virtual void StartOnTokenServiceThread() OVERRIDE; + virtual void StopOnTokenServiceThread() OVERRIDE; + + void InformOwnerOnGetTokenSuccess(std::string access_token, + base::Time expiration_time); + void InformOwnerOnGetTokenFailure(GoogleServiceAuthError error); + + 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 token service thread. + scoped_ptr<OAuth2TokenService::Request> request_; + + DISALLOW_COPY_AND_ASSIGN(RequestCore); +}; + +RequestCore::RequestCore( + OAuth2TokenServiceRequest* owner, + OAuth2TokenServiceRequest::TokenServiceProvider* provider, + OAuth2TokenService::Consumer* consumer, + const std::string& account_id, + 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()); +} + +RequestCore::~RequestCore() { +} + +void RequestCore::StartOnTokenServiceThread() { + DCHECK(token_service_task_runner()->BelongsToCurrentThread()); + request_ = token_service()->StartRequest(account_id_, scopes_, this).Pass(); +} + +void RequestCore::StopOnTokenServiceThread() { + DCHECK(token_service_task_runner()->BelongsToCurrentThread()); + request_.reset(); +} + +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(&RequestCore::InformOwnerOnGetTokenSuccess, + this, + access_token, + expiration_time)); + request_.reset(); +} + +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(&RequestCore::InformOwnerOnGetTokenFailure, this, error)); + request_.reset(); +} + +void RequestCore::InformOwnerOnGetTokenSuccess(std::string access_token, + base::Time expiration_time) { + DCHECK(CalledOnValidThread()); + if (!IsStopped()) { + consumer_->OnGetTokenSuccess(owner(), access_token, expiration_time); + } +} + +void RequestCore::InformOwnerOnGetTokenFailure(GoogleServiceAuthError error) { + DCHECK(CalledOnValidThread()); + if (!IsStopped()) { + consumer_->OnGetTokenFailure(owner(), error); + } +} + +// 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(); + + // 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 +scoped_ptr<OAuth2TokenServiceRequest> OAuth2TokenServiceRequest::CreateAndStart( + TokenServiceProvider* provider, + const std::string& account_id, + const OAuth2TokenService::ScopeSet& 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(); +} + +// 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 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(); +} diff --git a/google_apis/gaia/oauth2_token_service_request.h b/google_apis/gaia/oauth2_token_service_request.h new file mode 100644 index 0000000..972e518 --- /dev/null +++ b/google_apis/gaia/oauth2_token_service_request.h @@ -0,0 +1,96 @@ +// 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 GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_REQUEST_H_ +#define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_REQUEST_H_ + +#include <set> +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/non_thread_safe.h" +#include "google_apis/gaia/oauth2_token_service.h" + +// OAuth2TokenServiceRequest represents an asynchronous request to an +// OAuth2TokenService that may live in another thread. +// +// An OAuth2TokenServiceRequest can be created and started from any thread. +class OAuth2TokenServiceRequest : public OAuth2TokenService::Request, + public base::NonThreadSafe { + public: + class Core; + + // Interface for providing an OAuth2TokenService. + class TokenServiceProvider { + public: + TokenServiceProvider(); + virtual ~TokenServiceProvider(); + + // Returns the task runner on which the token service lives. + // + // This method may be called from any thread. + virtual scoped_refptr<base::SingleThreadTaskRunner> + GetTokenServiceTaskRunner() = 0; + + // Returns a pointer to a token service. + // + // Caller does not own the token service and must not delete it. The token + // service must outlive all instances of OAuth2TokenServiceRequest. + // + // This method may only be called from the task runner returned by + // |GetTokenServiceTaskRunner|. + virtual OAuth2TokenService* GetTokenService() = 0; + }; + + // Creates and starts an access token request for |account_id| and |scopes|. + // + // |provider| is used to get the OAuth2TokenService and must outlive the + // returned request object. + // + // |account_id| must not be empty. + // + // |scopes| must not be empty. + // + // |consumer| will be invoked in the same thread that invoked CreateAndStart + // and must outlive the returned request object. Destroying the request + // object ensure that |consumer| will not be called. However, the actual + // network activities may not be canceled and the cache in OAuth2TokenService + // may be populated with the fetched results. + static scoped_ptr<OAuth2TokenServiceRequest> CreateAndStart( + TokenServiceProvider* provider, + const std::string& account_id, + const OAuth2TokenService::ScopeSet& scopes, + OAuth2TokenService::Consumer* consumer); + + // Invalidates |access_token| for |account_id| and |scopes|. + // + // |provider| is used to get the OAuth2TokenService and must outlive the + // returned request object. + // + // |account_id| must not be empty. + // + // |scopes| must not be empty. + static void InvalidateToken(TokenServiceProvider* provider, + const std::string& account_id, + const OAuth2TokenService::ScopeSet& scopes, + const std::string& access_token); + + virtual ~OAuth2TokenServiceRequest(); + + // OAuth2TokenService::Request. + virtual std::string GetAccountId() const OVERRIDE; + + private: + OAuth2TokenServiceRequest(const std::string& account_id); + + void StartWithCore(const scoped_refptr<Core>& core); + + const std::string account_id_; + scoped_refptr<Core> core_; + + DISALLOW_COPY_AND_ASSIGN(OAuth2TokenServiceRequest); +}; + +#endif // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_REQUEST_H_ diff --git a/google_apis/gaia/oauth2_token_service_request_unittest.cc b/google_apis/gaia/oauth2_token_service_request_unittest.cc new file mode 100644 index 0000000..b627006 --- /dev/null +++ b/google_apis/gaia/oauth2_token_service_request_unittest.cc @@ -0,0 +1,257 @@ +// 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 "google_apis/gaia/oauth2_token_service_request.h" + +#include <set> +#include <string> +#include <vector> +#include "base/threading/thread.h" +#include "google_apis/gaia/fake_oauth2_token_service.h" +#include "google_apis/gaia/google_service_auth_error.h" +#include "google_apis/gaia/oauth2_token_service.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const char kAccessToken[] = "access_token"; +const char kAccountId[] = "test_user@gmail.com"; +const char kScope[] = "SCOPE"; + +class TestingOAuth2TokenServiceConsumer : public OAuth2TokenService::Consumer { + public: + TestingOAuth2TokenServiceConsumer(); + virtual ~TestingOAuth2TokenServiceConsumer(); + + virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, + const std::string& access_token, + const base::Time& expiration_time) OVERRIDE; + virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) OVERRIDE; + + int num_get_token_success_; + int num_get_token_failure_; + std::string last_token_; + GoogleServiceAuthError last_error_; +}; + +TestingOAuth2TokenServiceConsumer::TestingOAuth2TokenServiceConsumer() + : OAuth2TokenService::Consumer("test"), + num_get_token_success_(0), + num_get_token_failure_(0), + last_error_(GoogleServiceAuthError::AuthErrorNone()) { +} + +TestingOAuth2TokenServiceConsumer::~TestingOAuth2TokenServiceConsumer() { +} + +void TestingOAuth2TokenServiceConsumer::OnGetTokenSuccess( + const OAuth2TokenService::Request* request, + const std::string& token, + const base::Time& expiration_date) { + last_token_ = token; + ++num_get_token_success_; +} + +void TestingOAuth2TokenServiceConsumer::OnGetTokenFailure( + const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) { + last_error_ = error; + ++num_get_token_failure_; +} + +// A mock implementation of an OAuth2TokenService. +// +// Use SetResponse to vary the response to token requests. +class MockOAuth2TokenService : public FakeOAuth2TokenService { + public: + MockOAuth2TokenService(); + virtual ~MockOAuth2TokenService(); + + void SetResponse(const GoogleServiceAuthError& error, + const std::string& access_token, + const base::Time& expiration); + + int num_invalidate_token() const { return num_invalidate_token_; } + + const std::string& last_token_invalidated() const { + return last_token_invalidated_; + } + + protected: + virtual void FetchOAuth2Token(RequestImpl* request, + const std::string& account_id, + net::URLRequestContextGetter* getter, + const std::string& client_id, + const std::string& client_secret, + const ScopeSet& scopes) OVERRIDE; + + virtual void InvalidateOAuth2Token(const std::string& account_id, + const std::string& client_id, + const ScopeSet& scopes, + const std::string& access_token) OVERRIDE; + + private: + GoogleServiceAuthError response_error_; + std::string response_access_token_; + base::Time response_expiration_; + int num_invalidate_token_; + std::string last_token_invalidated_; +}; + +MockOAuth2TokenService::MockOAuth2TokenService() + : response_error_(GoogleServiceAuthError::AuthErrorNone()), + response_access_token_(kAccessToken), + response_expiration_(base::Time::Max()), + num_invalidate_token_(0) { +} + +MockOAuth2TokenService::~MockOAuth2TokenService() { +} + +void MockOAuth2TokenService::SetResponse(const GoogleServiceAuthError& error, + const std::string& access_token, + const base::Time& expiration) { + response_error_ = error; + response_access_token_ = access_token; + response_expiration_ = expiration; +} + +void MockOAuth2TokenService::FetchOAuth2Token( + RequestImpl* request, + const std::string& account_id, + net::URLRequestContextGetter* getter, + const std::string& client_id, + const std::string& client_secret, + const ScopeSet& scopes) { + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&OAuth2TokenService::RequestImpl::InformConsumer, + request->AsWeakPtr(), + response_error_, + response_access_token_, + response_expiration_)); +} + +void MockOAuth2TokenService::InvalidateOAuth2Token( + const std::string& account_id, + const std::string& client_id, + const ScopeSet& scopes, + const std::string& access_token) { + ++num_invalidate_token_; + last_token_invalidated_ = access_token; +} + +class OAuth2TokenServiceRequestTest : public testing::Test { + public: + virtual void SetUp() OVERRIDE; + + protected: + class Provider : public OAuth2TokenServiceRequest::TokenServiceProvider { + public: + Provider(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + OAuth2TokenService* token_service); + + virtual scoped_refptr<base::SingleThreadTaskRunner> + GetTokenServiceTaskRunner() OVERRIDE; + virtual OAuth2TokenService* GetTokenService() OVERRIDE; + + private: + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + OAuth2TokenService* token_service_; + }; + + base::MessageLoop ui_loop_; + OAuth2TokenService::ScopeSet scopes_; + scoped_ptr<MockOAuth2TokenService> oauth2_service_; + scoped_ptr<OAuth2TokenServiceRequest::TokenServiceProvider> provider_; + TestingOAuth2TokenServiceConsumer consumer_; +}; + +void OAuth2TokenServiceRequestTest::SetUp() { + scopes_.insert(kScope); + oauth2_service_.reset(new MockOAuth2TokenService); + oauth2_service_->AddAccount(kAccountId); + provider_.reset( + new Provider(base::MessageLoopProxy::current(), oauth2_service_.get())); +} + +OAuth2TokenServiceRequestTest::Provider::Provider( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + OAuth2TokenService* token_service) + : task_runner_(task_runner), token_service_(token_service) { +} + +scoped_refptr<base::SingleThreadTaskRunner> +OAuth2TokenServiceRequestTest::Provider::GetTokenServiceTaskRunner() { + return task_runner_; +} + +OAuth2TokenService* OAuth2TokenServiceRequestTest::Provider::GetTokenService() { + return token_service_; +} + +TEST_F(OAuth2TokenServiceRequestTest, CreateAndStart_Failure) { + oauth2_service_->SetResponse( + GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE), + std::string(), + base::Time()); + scoped_ptr<OAuth2TokenServiceRequest> request( + OAuth2TokenServiceRequest::CreateAndStart( + provider_.get(), kAccountId, scopes_, &consumer_)); + ui_loop_.RunUntilIdle(); + EXPECT_EQ(0, consumer_.num_get_token_success_); + EXPECT_EQ(1, consumer_.num_get_token_failure_); + EXPECT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE, + consumer_.last_error_.state()); + EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); +} + +TEST_F(OAuth2TokenServiceRequestTest, CreateAndStart_Success) { + scoped_ptr<OAuth2TokenServiceRequest> request( + OAuth2TokenServiceRequest::CreateAndStart( + provider_.get(), kAccountId, scopes_, &consumer_)); + ui_loop_.RunUntilIdle(); + EXPECT_EQ(1, consumer_.num_get_token_success_); + EXPECT_EQ(0, consumer_.num_get_token_failure_); + EXPECT_EQ(kAccessToken, consumer_.last_token_); + EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); +} + +TEST_F(OAuth2TokenServiceRequestTest, + CreateAndStart_DestroyRequestBeforeCompletes) { + scoped_ptr<OAuth2TokenServiceRequest> request( + OAuth2TokenServiceRequest::CreateAndStart( + provider_.get(), kAccountId, scopes_, &consumer_)); + request.reset(); + ui_loop_.RunUntilIdle(); + EXPECT_EQ(0, consumer_.num_get_token_success_); + EXPECT_EQ(0, consumer_.num_get_token_failure_); + EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); +} + +TEST_F(OAuth2TokenServiceRequestTest, + CreateAndStart_DestroyRequestAfterCompletes) { + scoped_ptr<OAuth2TokenServiceRequest> request( + OAuth2TokenServiceRequest::CreateAndStart( + provider_.get(), kAccountId, scopes_, &consumer_)); + ui_loop_.RunUntilIdle(); + request.reset(); + EXPECT_EQ(1, consumer_.num_get_token_success_); + EXPECT_EQ(0, consumer_.num_get_token_failure_); + EXPECT_EQ(kAccessToken, consumer_.last_token_); + EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); +} + +TEST_F(OAuth2TokenServiceRequestTest, InvalidateToken) { + OAuth2TokenServiceRequest::InvalidateToken( + provider_.get(), kAccountId, scopes_, kAccessToken); + ui_loop_.RunUntilIdle(); + EXPECT_EQ(0, consumer_.num_get_token_success_); + EXPECT_EQ(0, consumer_.num_get_token_failure_); + EXPECT_EQ(kAccessToken, oauth2_service_->last_token_invalidated()); + EXPECT_EQ(1, oauth2_service_->num_invalidate_token()); +} + +} // namespace diff --git a/google_apis/google_apis.gyp b/google_apis/google_apis.gyp index ec9c8c8..1fa476c 100644 --- a/google_apis/google_apis.gyp +++ b/google_apis/google_apis.gyp @@ -128,6 +128,8 @@ 'gaia/oauth2_mint_token_flow.h', 'gaia/oauth2_token_service.cc', 'gaia/oauth2_token_service.h', + 'gaia/oauth2_token_service_request.cc', + 'gaia/oauth2_token_service_request.h', 'gaia/ubertoken_fetcher.cc', 'gaia/ubertoken_fetcher.h', 'google_api_keys.cc', @@ -175,6 +177,7 @@ 'gaia/oauth2_access_token_fetcher_impl_unittest.cc', 'gaia/oauth2_api_call_flow_unittest.cc', 'gaia/oauth2_mint_token_flow_unittest.cc', + 'gaia/oauth2_token_service_request_unittest.cc', 'gaia/oauth2_token_service_unittest.cc', 'gaia/ubertoken_fetcher_unittest.cc', ], |