Chromium Code Reviews| Index: chrome/browser/signin/oauth2_token_service.cc |
| diff --git a/chrome/browser/signin/oauth2_token_service.cc b/chrome/browser/signin/oauth2_token_service.cc |
| index e21911d00ffee39bea0bd97305fe4fb9eb5c1837..0b15f84b2bfec69fb92ae28571e07680ad08511a 100644 |
| --- a/chrome/browser/signin/oauth2_token_service.cc |
| +++ b/chrome/browser/signin/oauth2_token_service.cc |
| @@ -20,21 +20,7 @@ |
| #include "google_apis/gaia/oauth2_access_token_fetcher.h" |
| #include "net/url_request/url_request_context_getter.h" |
| -namespace { |
| - |
| -// Maximum number of retries in fetching an OAuth2 access token. |
| -const int kMaxFetchRetryNum = 5; |
| - |
| -// Returns an exponential backoff in milliseconds including randomness less than |
| -// 1000 ms when retrying fetching an OAuth2 access token. |
| -int64 ComputeExponentialBackOffMilliseconds(int retry_num) { |
| - DCHECK(retry_num < kMaxFetchRetryNum); |
| - int64 exponential_backoff_in_seconds = 1 << retry_num; |
| - // Returns a backoff with randomness < 1000ms |
| - return (exponential_backoff_in_seconds + base::RandDouble()) * 1000; |
| -} |
| - |
| -} // namespace |
| +int OAuth2TokenService::max_fetch_retry_num_ = 5; |
| OAuth2TokenService::RequestImpl::RequestImpl( |
| OAuth2TokenService::Consumer* consumer) |
| @@ -84,7 +70,8 @@ void OAuth2TokenService::RequestImpl::InformConsumer( |
| // - when the Fetcher is destructed if the Fetcher is destructed before it |
| // completes fetching (in this case, the waiting requests will be called back |
| // with error). |
| -class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { |
| +class OAuth2TokenService::Fetcher : public RefreshTokenValidationConsumer, |
| + public OAuth2AccessTokenConsumer { |
| public: |
| // Creates a Fetcher and starts fetching an OAuth2 access token for |
| // |refresh_token| and |scopes| in the request context obtained by |getter|. |
| @@ -111,6 +98,11 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { |
| const base::Time& expiration_date) OVERRIDE; |
| virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; |
| + // RefreshTokenValidationConsumer |
| + virtual void OnRefreshTokenValidationComplete( |
| + const std::string& refresh_token, |
| + bool is_valid) OVERRIDE; |
| + |
| private: |
| Fetcher(OAuth2TokenService* oauth2_token_service, |
| net::URLRequestContextGetter* getter, |
| @@ -118,8 +110,11 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { |
| const OAuth2TokenService::ScopeSet& scopes, |
| base::WeakPtr<RequestImpl> waiting_request); |
| void Start(); |
| + void StartAccessTokenFetch(); |
| void InformWaitingRequests(); |
| + void InformWaitingRequestsAndQuit(); |
| static bool ShouldRetry(const GoogleServiceAuthError& error); |
| + int64 ComputeExponentialBackOffMilliseconds(int retry_num); |
| // |oauth2_token_service_| remains valid for the life of this Fetcher, since |
| // this Fetcher is destructed in the dtor of the OAuth2TokenService or is |
| @@ -183,6 +178,26 @@ OAuth2TokenService::Fetcher::~Fetcher() { |
| } |
| void OAuth2TokenService::Fetcher::Start() { |
| + if (!oauth2_token_service_->StartRefreshTokenValidation(refresh_token_, |
| + this)) { |
| + StartAccessTokenFetch(); |
| + } |
| +} |
| + |
| +void OAuth2TokenService::Fetcher::OnRefreshTokenValidationComplete( |
| + const std::string& refresh_token, |
|
Mattias Nissler (ping if slow)
2013/06/19 17:53:17
nit: indentation
David Roche
2013/06/20 17:49:29
Removed.
|
| + bool is_valid) { |
| + DCHECK(refresh_token_ == refresh_token); |
| + if (is_valid) { |
| + StartAccessTokenFetch(); |
| + } else { |
| + error_ = GoogleServiceAuthError( |
| + GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); |
| + InformWaitingRequestsAndQuit(); |
| + } |
| +} |
| + |
| +void OAuth2TokenService::Fetcher::StartAccessTokenFetch() { |
| fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_.get())); |
| fetcher_->Start(GaiaUrls::GetInstance()->oauth2_chrome_client_id(), |
| GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), |
| @@ -209,18 +224,14 @@ void OAuth2TokenService::Fetcher::OnGetTokenSuccess( |
| scopes_, |
| access_token_, |
| expiration_date_); |
| - // Deregisters itself from the service to prevent more waiting requests to |
| - // be added when it calls back the waiting requests. |
| - oauth2_token_service_->OnFetchComplete(this); |
| - InformWaitingRequests(); |
| - base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| + InformWaitingRequestsAndQuit(); |
| } |
| void OAuth2TokenService::Fetcher::OnGetTokenFailure( |
| const GoogleServiceAuthError& error) { |
| fetcher_.reset(); |
| - if (ShouldRetry(error) && retry_number_ < kMaxFetchRetryNum) { |
| + if (ShouldRetry(error) && retry_number_ < max_fetch_retry_num_) { |
| int64 backoff = ComputeExponentialBackOffMilliseconds(retry_number_); |
| ++retry_number_; |
| retry_timer_.Stop(); |
| @@ -231,14 +242,18 @@ void OAuth2TokenService::Fetcher::OnGetTokenFailure( |
| return; |
| } |
| - // Fetch completes. |
| error_ = error; |
| + InformWaitingRequestsAndQuit(); |
| +} |
| - // Deregisters itself from the service to prevent more waiting requests to be |
| - // added when it calls back the waiting requests. |
| - oauth2_token_service_->OnFetchComplete(this); |
| - InformWaitingRequests(); |
| - base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| +// Returns an exponential backoff in milliseconds including randomness less than |
| +// 1000 ms when retrying fetching an OAuth2 access token. |
| +int64 OAuth2TokenService::Fetcher::ComputeExponentialBackOffMilliseconds( |
| + int retry_num) { |
| + DCHECK(retry_num < max_fetch_retry_num_); |
| + int64 exponential_backoff_in_seconds = 1 << retry_num; |
| + // Returns a backoff with randomness < 1000ms |
| + return (exponential_backoff_in_seconds + base::RandDouble()) * 1000; |
| } |
| // static |
| @@ -261,6 +276,14 @@ void OAuth2TokenService::Fetcher::InformWaitingRequests() { |
| waiting_requests_.clear(); |
| } |
| +void OAuth2TokenService::Fetcher::InformWaitingRequestsAndQuit() { |
| + // Deregisters itself from the service to prevent more waiting requests to |
| + // be added when it calls back the waiting requests. |
| + oauth2_token_service_->OnFetchComplete(this); |
| + InformWaitingRequests(); |
| + base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| +} |
| + |
| void OAuth2TokenService::Fetcher::AddWaitingRequest( |
| base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) { |
| waiting_requests_.push_back(waiting_request); |
| @@ -298,11 +321,6 @@ OAuth2TokenService::~OAuth2TokenService() { |
| pending_fetchers_.begin(), pending_fetchers_.end()); |
| } |
| -bool OAuth2TokenService::RefreshTokenIsAvailable() { |
| - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| - return !GetRefreshToken().empty(); |
| -} |
| - |
| scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( |
| const OAuth2TokenService::ScopeSet& scopes, |
| OAuth2TokenService::Consumer* consumer) { |
| @@ -323,11 +341,11 @@ scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( |
| } |
| if (HasCacheEntry(scopes)) |
| - return StartCacheLookupRequest(scopes, consumer); |
| + return StartCacheLookupRequest(scopes, request.Pass()); |
| - // Makes sure there is a pending fetcher for |scopes| and |refresh_token|. |
| - // Adds |request| to the waiting request list of this fetcher so |request| |
| - // will be called back when this fetcher finishes fetching. |
| + // If there is already a pending fetcher for |scopes| and |refresh_token|, |
| + // simply register this |request| for those results rather than starting |
| + // a new fetcher. |
| FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); |
| std::map<FetchParameters, Fetcher*>::iterator iter = |
| pending_fetchers_.find(fetch_parameters); |
| @@ -335,6 +353,7 @@ scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( |
| iter->second->AddWaitingRequest(request->AsWeakPtr()); |
| return request.PassAs<Request>(); |
| } |
| + |
| pending_fetchers_[fetch_parameters] = |
| Fetcher::CreateAndStart(this, |
| request_context_getter_.get(), |
| @@ -347,10 +366,9 @@ scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( |
| scoped_ptr<OAuth2TokenService::Request> |
| OAuth2TokenService::StartCacheLookupRequest( |
| const OAuth2TokenService::ScopeSet& scopes, |
| - OAuth2TokenService::Consumer* consumer) { |
| + scoped_ptr<RequestImpl> request) { |
| CHECK(HasCacheEntry(scopes)); |
| const CacheEntry* cache_entry = GetCacheEntry(scopes); |
| - scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); |
| base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
| &RequestImpl::InformConsumer, |
| request->AsWeakPtr(), |
| @@ -451,6 +469,12 @@ void OAuth2TokenService::RegisterCacheEntry( |
| token.expiration_date = expiration_date; |
| } |
| +bool OAuth2TokenService::StartRefreshTokenValidation( |
| + const std::string refresh_token, |
|
Mattias Nissler (ping if slow)
2013/06/19 17:53:17
nit: indentation
David Roche
2013/06/20 17:49:29
Removed.
|
| + RefreshTokenValidationConsumer* consumer) { |
| + return false; // No validation needed; use token directly. |
| +} |
| + |
| void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) { |
| // Default implementation does nothing. |
| } |
| @@ -463,3 +487,9 @@ void OAuth2TokenService::ClearCache() { |
| int OAuth2TokenService::cache_size_for_testing() const { |
| return token_cache_.size(); |
| } |
| + |
| +void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing( |
| + int max_retries) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + max_fetch_retry_num_ = max_retries; |
| +} |