Home | History | Annotate | Download | only in gaia
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "google_apis/gaia/oauth2_token_service.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/memory/weak_ptr.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/rand_util.h"
     13 #include "base/stl_util.h"
     14 #include "base/time/time.h"
     15 #include "base/timer/timer.h"
     16 #include "google_apis/gaia/gaia_urls.h"
     17 #include "google_apis/gaia/google_service_auth_error.h"
     18 #include "net/url_request/url_request_context_getter.h"
     19 
     20 int OAuth2TokenService::max_fetch_retry_num_ = 5;
     21 
     22 OAuth2TokenService::RequestParameters::RequestParameters(
     23     const std::string& client_id,
     24     const std::string& account_id,
     25     const ScopeSet& scopes)
     26     : client_id(client_id),
     27       account_id(account_id),
     28       scopes(scopes) {
     29 }
     30 
     31 OAuth2TokenService::RequestParameters::~RequestParameters() {
     32 }
     33 
     34 bool OAuth2TokenService::RequestParameters::operator<(
     35     const RequestParameters& p) const {
     36   if (client_id < p.client_id)
     37     return true;
     38   else if (p.client_id < client_id)
     39     return false;
     40 
     41   if (account_id < p.account_id)
     42     return true;
     43   else if (p.account_id < account_id)
     44     return false;
     45 
     46   return scopes < p.scopes;
     47 }
     48 
     49 OAuth2TokenService::RequestImpl::RequestImpl(
     50     const std::string& account_id,
     51     OAuth2TokenService::Consumer* consumer)
     52     : account_id_(account_id),
     53       consumer_(consumer) {
     54 }
     55 
     56 OAuth2TokenService::RequestImpl::~RequestImpl() {
     57   DCHECK(CalledOnValidThread());
     58 }
     59 
     60 std::string OAuth2TokenService::RequestImpl::GetAccountId() const {
     61   return account_id_;
     62 }
     63 
     64 void OAuth2TokenService::RequestImpl::InformConsumer(
     65     const GoogleServiceAuthError& error,
     66     const std::string& access_token,
     67     const base::Time& expiration_date) {
     68   DCHECK(CalledOnValidThread());
     69   if (error.state() == GoogleServiceAuthError::NONE)
     70     consumer_->OnGetTokenSuccess(this, access_token, expiration_date);
     71   else
     72     consumer_->OnGetTokenFailure(this, error);
     73 }
     74 
     75 // Class that fetches an OAuth2 access token for a given set of scopes and
     76 // OAuth2 refresh token.
     77 
     78 // Class that fetches OAuth2 access tokens for given scopes and refresh token.
     79 //
     80 // It aims to meet OAuth2TokenService's requirements on token fetching. Retry
     81 // mechanism is used to handle failures.
     82 //
     83 // To use this class, call CreateAndStart() to create and start a Fetcher.
     84 //
     85 // The Fetcher will call back the service by calling
     86 // OAuth2TokenService::OnFetchComplete() when it completes fetching, if it is
     87 // not destructed before it completes fetching; if the Fetcher is destructed
     88 // before it completes fetching, the service will never be called back. The
     89 // Fetcher destructs itself after calling back the service when finishes
     90 // fetching.
     91 //
     92 // Requests that are waiting for the fetching results of this Fetcher can be
     93 // added to the Fetcher by calling
     94 // OAuth2TokenService::Fetcher::AddWaitingRequest() before the Fetcher
     95 // completes fetching.
     96 //
     97 // The waiting requests are taken as weak pointers and they can be deleted.
     98 // The waiting requests will be called back with fetching results if they are
     99 // not deleted
    100 // - when the Fetcher completes fetching, if the Fetcher is not destructed
    101 //   before it completes fetching, or
    102 // - when the Fetcher is destructed if the Fetcher is destructed before it
    103 //   completes fetching (in this case, the waiting requests will be called
    104 //   back with error).
    105 class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer {
    106  public:
    107   // Creates a Fetcher and starts fetching an OAuth2 access token for
    108   // |refresh_token| and |scopes| in the request context obtained by |getter|.
    109   // The given |oauth2_token_service| will be informed when fetching is done.
    110   static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service,
    111                                  const std::string& account_id,
    112                                  net::URLRequestContextGetter* getter,
    113                                  const std::string& client_id,
    114                                  const std::string& client_secret,
    115                                  const std::string& refresh_token,
    116                                  const ScopeSet& scopes,
    117                                  base::WeakPtr<RequestImpl> waiting_request);
    118   virtual ~Fetcher();
    119 
    120   // Add a request that is waiting for the result of this Fetcher.
    121   void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request);
    122 
    123   // Returns count of waiting requests.
    124   size_t GetWaitingRequestCount() const;
    125 
    126   void Cancel();
    127 
    128   const ScopeSet& GetScopeSet() const;
    129   const std::string& GetRefreshToken() const;
    130   const std::string& GetClientId() const;
    131   const std::string& GetAccountId() const;
    132 
    133   // The error result from this fetcher.
    134   const GoogleServiceAuthError& error() const { return error_; }
    135 
    136  protected:
    137    // OAuth2AccessTokenConsumer
    138   virtual void OnGetTokenSuccess(const std::string& access_token,
    139                                  const base::Time& expiration_date) OVERRIDE;
    140   virtual void OnGetTokenFailure(
    141       const GoogleServiceAuthError& error) OVERRIDE;
    142 
    143  private:
    144   Fetcher(OAuth2TokenService* oauth2_token_service,
    145           const std::string& account_id,
    146           net::URLRequestContextGetter* getter,
    147           const std::string& client_id,
    148           const std::string& client_secret,
    149           const std::string& refresh_token,
    150           const OAuth2TokenService::ScopeSet& scopes,
    151           base::WeakPtr<RequestImpl> waiting_request);
    152   void Start();
    153   void InformWaitingRequests();
    154   void InformWaitingRequestsAndDelete();
    155   static bool ShouldRetry(const GoogleServiceAuthError& error);
    156   int64 ComputeExponentialBackOffMilliseconds(int retry_num);
    157 
    158   // |oauth2_token_service_| remains valid for the life of this Fetcher, since
    159   // this Fetcher is destructed in the dtor of the OAuth2TokenService or is
    160   // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess
    161   // (whichever comes first).
    162   OAuth2TokenService* const oauth2_token_service_;
    163   scoped_refptr<net::URLRequestContextGetter> getter_;
    164   const std::string account_id_;
    165   const std::string refresh_token_;
    166   const ScopeSet scopes_;
    167   std::vector<base::WeakPtr<RequestImpl> > waiting_requests_;
    168 
    169   int retry_number_;
    170   base::OneShotTimer<Fetcher> retry_timer_;
    171   scoped_ptr<OAuth2AccessTokenFetcher> fetcher_;
    172 
    173   // Variables that store fetch results.
    174   // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle
    175   // destruction.
    176   GoogleServiceAuthError error_;
    177   std::string access_token_;
    178   base::Time expiration_date_;
    179 
    180   // OAuth2 client id and secret.
    181   std::string client_id_;
    182   std::string client_secret_;
    183 
    184   DISALLOW_COPY_AND_ASSIGN(Fetcher);
    185 };
    186 
    187 // static
    188 OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart(
    189     OAuth2TokenService* oauth2_token_service,
    190     const std::string& account_id,
    191     net::URLRequestContextGetter* getter,
    192     const std::string& client_id,
    193     const std::string& client_secret,
    194     const std::string& refresh_token,
    195     const OAuth2TokenService::ScopeSet& scopes,
    196     base::WeakPtr<RequestImpl> waiting_request) {
    197   OAuth2TokenService::Fetcher* fetcher = new Fetcher(
    198       oauth2_token_service,
    199       account_id,
    200       getter,
    201       client_id,
    202       client_secret,
    203       refresh_token,
    204       scopes,
    205       waiting_request);
    206   fetcher->Start();
    207   return fetcher;
    208 }
    209 
    210 OAuth2TokenService::Fetcher::Fetcher(
    211     OAuth2TokenService* oauth2_token_service,
    212     const std::string& account_id,
    213     net::URLRequestContextGetter* getter,
    214     const std::string& client_id,
    215     const std::string& client_secret,
    216     const std::string& refresh_token,
    217     const OAuth2TokenService::ScopeSet& scopes,
    218     base::WeakPtr<RequestImpl> waiting_request)
    219     : oauth2_token_service_(oauth2_token_service),
    220       getter_(getter),
    221       account_id_(account_id),
    222       refresh_token_(refresh_token),
    223       scopes_(scopes),
    224       retry_number_(0),
    225       error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE),
    226       client_id_(client_id),
    227       client_secret_(client_secret) {
    228   DCHECK(oauth2_token_service_);
    229   DCHECK(getter_.get());
    230   DCHECK(refresh_token_.length());
    231   waiting_requests_.push_back(waiting_request);
    232 }
    233 
    234 OAuth2TokenService::Fetcher::~Fetcher() {
    235   // Inform the waiting requests if it has not done so.
    236   if (waiting_requests_.size())
    237     InformWaitingRequests();
    238 }
    239 
    240 void OAuth2TokenService::Fetcher::Start() {
    241   fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_.get()));
    242   fetcher_->Start(client_id_,
    243                   client_secret_,
    244                   refresh_token_,
    245                   std::vector<std::string>(scopes_.begin(), scopes_.end()));
    246   retry_timer_.Stop();
    247 }
    248 
    249 void OAuth2TokenService::Fetcher::OnGetTokenSuccess(
    250     const std::string& access_token,
    251     const base::Time& expiration_date) {
    252   fetcher_.reset();
    253 
    254   // Fetch completes.
    255   error_ = GoogleServiceAuthError::AuthErrorNone();
    256   access_token_ = access_token;
    257   expiration_date_ = expiration_date;
    258 
    259   // Subclasses may override this method to skip caching in some cases, but
    260   // we still inform all waiting Consumers of a successful token fetch below.
    261   // This is intentional -- some consumers may need the token for cleanup
    262   // tasks. https://chromiumcodereview.appspot.com/11312124/
    263   oauth2_token_service_->RegisterCacheEntry(client_id_,
    264                                             account_id_,
    265                                             scopes_,
    266                                             access_token_,
    267                                             expiration_date_);
    268   InformWaitingRequestsAndDelete();
    269 }
    270 
    271 void OAuth2TokenService::Fetcher::OnGetTokenFailure(
    272     const GoogleServiceAuthError& error) {
    273   fetcher_.reset();
    274 
    275   if (ShouldRetry(error) && retry_number_ < max_fetch_retry_num_) {
    276     int64 backoff = ComputeExponentialBackOffMilliseconds(retry_number_);
    277     ++retry_number_;
    278     retry_timer_.Stop();
    279     retry_timer_.Start(FROM_HERE,
    280                        base::TimeDelta::FromMilliseconds(backoff),
    281                        this,
    282                        &OAuth2TokenService::Fetcher::Start);
    283     return;
    284   }
    285 
    286   error_ = error;
    287   InformWaitingRequestsAndDelete();
    288 }
    289 
    290 // Returns an exponential backoff in milliseconds including randomness less than
    291 // 1000 ms when retrying fetching an OAuth2 access token.
    292 int64 OAuth2TokenService::Fetcher::ComputeExponentialBackOffMilliseconds(
    293     int retry_num) {
    294   DCHECK(retry_num < max_fetch_retry_num_);
    295   int64 exponential_backoff_in_seconds = 1 << retry_num;
    296   // Returns a backoff with randomness < 1000ms
    297   return (exponential_backoff_in_seconds + base::RandDouble()) * 1000;
    298 }
    299 
    300 // static
    301 bool OAuth2TokenService::Fetcher::ShouldRetry(
    302     const GoogleServiceAuthError& error) {
    303   GoogleServiceAuthError::State error_state = error.state();
    304   return error_state == GoogleServiceAuthError::CONNECTION_FAILED ||
    305          error_state == GoogleServiceAuthError::REQUEST_CANCELED ||
    306          error_state == GoogleServiceAuthError::SERVICE_UNAVAILABLE;
    307 }
    308 
    309 void OAuth2TokenService::Fetcher::InformWaitingRequests() {
    310   std::vector<base::WeakPtr<RequestImpl> >::const_iterator iter =
    311       waiting_requests_.begin();
    312   for (; iter != waiting_requests_.end(); ++iter) {
    313     base::WeakPtr<RequestImpl> waiting_request = *iter;
    314     if (waiting_request.get())
    315       waiting_request->InformConsumer(error_, access_token_, expiration_date_);
    316   }
    317   waiting_requests_.clear();
    318 }
    319 
    320 void OAuth2TokenService::Fetcher::InformWaitingRequestsAndDelete() {
    321   // Deregisters itself from the service to prevent more waiting requests to
    322   // be added when it calls back the waiting requests.
    323   oauth2_token_service_->OnFetchComplete(this);
    324   InformWaitingRequests();
    325   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
    326 }
    327 
    328 void OAuth2TokenService::Fetcher::AddWaitingRequest(
    329     base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) {
    330   waiting_requests_.push_back(waiting_request);
    331 }
    332 
    333 size_t OAuth2TokenService::Fetcher::GetWaitingRequestCount() const {
    334   return waiting_requests_.size();
    335 }
    336 
    337 void OAuth2TokenService::Fetcher::Cancel() {
    338   fetcher_.reset();
    339   retry_timer_.Stop();
    340   error_ = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
    341   InformWaitingRequestsAndDelete();
    342 }
    343 
    344 const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet()
    345     const {
    346   return scopes_;
    347 }
    348 
    349 const std::string& OAuth2TokenService::Fetcher::GetRefreshToken() const {
    350   return refresh_token_;
    351 }
    352 
    353 const std::string& OAuth2TokenService::Fetcher::GetClientId() const {
    354   return client_id_;
    355 }
    356 
    357 const std::string& OAuth2TokenService::Fetcher::GetAccountId() const {
    358   return account_id_;
    359 }
    360 
    361 OAuth2TokenService::Request::Request() {
    362 }
    363 
    364 OAuth2TokenService::Request::~Request() {
    365 }
    366 
    367 OAuth2TokenService::Consumer::Consumer() {
    368 }
    369 
    370 OAuth2TokenService::Consumer::~Consumer() {
    371 }
    372 
    373 OAuth2TokenService::OAuth2TokenService() {
    374 }
    375 
    376 OAuth2TokenService::~OAuth2TokenService() {
    377   // Release all the pending fetchers.
    378   STLDeleteContainerPairSecondPointers(
    379       pending_fetchers_.begin(), pending_fetchers_.end());
    380 }
    381 
    382 void OAuth2TokenService::AddObserver(Observer* observer) {
    383   observer_list_.AddObserver(observer);
    384 }
    385 
    386 void OAuth2TokenService::RemoveObserver(Observer* observer) {
    387   observer_list_.RemoveObserver(observer);
    388 }
    389 
    390 bool OAuth2TokenService::RefreshTokenIsAvailable(
    391     const std::string& account_id) {
    392   DCHECK(CalledOnValidThread());
    393   return !GetRefreshToken(account_id).empty();
    394 }
    395 
    396 std::vector<std::string> OAuth2TokenService::GetAccounts() {
    397   return std::vector<std::string>();
    398 }
    399 
    400 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest(
    401     const std::string& account_id,
    402     const OAuth2TokenService::ScopeSet& scopes,
    403     OAuth2TokenService::Consumer* consumer) {
    404   return StartRequestForClientWithContext(
    405       account_id,
    406       GetRequestContext(),
    407       GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
    408       GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
    409       scopes,
    410       consumer);
    411 }
    412 
    413 scoped_ptr<OAuth2TokenService::Request>
    414 OAuth2TokenService::StartRequestForClient(
    415     const std::string& account_id,
    416     const std::string& client_id,
    417     const std::string& client_secret,
    418     const OAuth2TokenService::ScopeSet& scopes,
    419     OAuth2TokenService::Consumer* consumer) {
    420   return StartRequestForClientWithContext(
    421       account_id,
    422       GetRequestContext(),
    423       client_id,
    424       client_secret,
    425       scopes,
    426       consumer);
    427 }
    428 
    429 scoped_ptr<OAuth2TokenService::Request>
    430 OAuth2TokenService::StartRequestWithContext(
    431     const std::string& account_id,
    432     net::URLRequestContextGetter* getter,
    433     const ScopeSet& scopes,
    434     Consumer* consumer) {
    435   return StartRequestForClientWithContext(
    436       account_id,
    437       getter,
    438       GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
    439       GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
    440       scopes,
    441       consumer);
    442 }
    443 
    444 scoped_ptr<OAuth2TokenService::Request>
    445 OAuth2TokenService::StartRequestForClientWithContext(
    446     const std::string& account_id,
    447     net::URLRequestContextGetter* getter,
    448     const std::string& client_id,
    449     const std::string& client_secret,
    450     const ScopeSet& scopes,
    451     Consumer* consumer) {
    452   DCHECK(CalledOnValidThread());
    453 
    454   scoped_ptr<RequestImpl> request = CreateRequest(account_id, consumer);
    455 
    456   if (!RefreshTokenIsAvailable(account_id)) {
    457     base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
    458         &RequestImpl::InformConsumer,
    459         request->AsWeakPtr(),
    460         GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP),
    461         std::string(),
    462         base::Time()));
    463     return request.PassAs<Request>();
    464   }
    465 
    466   RequestParameters request_parameters(client_id,
    467                                        account_id,
    468                                        scopes);
    469   if (HasCacheEntry(request_parameters)) {
    470     StartCacheLookupRequest(request.get(), request_parameters, consumer);
    471   } else {
    472     FetchOAuth2Token(request.get(),
    473                      account_id,
    474                      getter,
    475                      client_id,
    476                      client_secret,
    477                      scopes);
    478   }
    479   return request.PassAs<Request>();
    480 }
    481 
    482 scoped_ptr<OAuth2TokenService::RequestImpl> OAuth2TokenService::CreateRequest(
    483     const std::string& account_id,
    484     Consumer* consumer) {
    485   return scoped_ptr<RequestImpl>(new RequestImpl(account_id, consumer));
    486 }
    487 
    488 void OAuth2TokenService::FetchOAuth2Token(RequestImpl* request,
    489                                           const std::string& account_id,
    490                                           net::URLRequestContextGetter* getter,
    491                                           const std::string& client_id,
    492                                           const std::string& client_secret,
    493                                           const ScopeSet& scopes) {
    494   std::string refresh_token = GetRefreshToken(account_id);
    495 
    496   // If there is already a pending fetcher for |scopes| and |account_id|,
    497   // simply register this |request| for those results rather than starting
    498   // a new fetcher.
    499   RequestParameters request_parameters = RequestParameters(client_id,
    500                                                            account_id,
    501                                                            scopes);
    502   std::map<RequestParameters, Fetcher*>::iterator iter =
    503       pending_fetchers_.find(request_parameters);
    504   if (iter != pending_fetchers_.end()) {
    505     iter->second->AddWaitingRequest(request->AsWeakPtr());
    506     return;
    507   }
    508 
    509   pending_fetchers_[request_parameters] =
    510       Fetcher::CreateAndStart(this,
    511                               account_id,
    512                               getter,
    513                               client_id,
    514                               client_secret,
    515                               refresh_token,
    516                               scopes,
    517                               request->AsWeakPtr());
    518 }
    519 
    520 void OAuth2TokenService::StartCacheLookupRequest(
    521     RequestImpl* request,
    522     const OAuth2TokenService::RequestParameters& request_parameters,
    523     OAuth2TokenService::Consumer* consumer) {
    524   CHECK(HasCacheEntry(request_parameters));
    525   const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
    526   base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
    527       &RequestImpl::InformConsumer,
    528       request->AsWeakPtr(),
    529       GoogleServiceAuthError(GoogleServiceAuthError::NONE),
    530       cache_entry->access_token,
    531       cache_entry->expiration_date));
    532 }
    533 
    534 void OAuth2TokenService::InvalidateToken(const std::string& account_id,
    535                                          const ScopeSet& scopes,
    536                                          const std::string& access_token) {
    537   InvalidateOAuth2Token(account_id,
    538                         GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
    539                         scopes,
    540                         access_token);
    541 }
    542 
    543 void OAuth2TokenService::InvalidateTokenForClient(
    544     const std::string& account_id,
    545     const std::string& client_id,
    546     const ScopeSet& scopes,
    547     const std::string& access_token) {
    548   InvalidateOAuth2Token(account_id, client_id, scopes, access_token);
    549 }
    550 
    551 void OAuth2TokenService::InvalidateOAuth2Token(
    552     const std::string& account_id,
    553     const std::string& client_id,
    554     const ScopeSet& scopes,
    555     const std::string& access_token) {
    556   DCHECK(CalledOnValidThread());
    557   RemoveCacheEntry(
    558       RequestParameters(client_id,
    559                         account_id,
    560                         scopes),
    561       access_token);
    562 }
    563 
    564 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) {
    565   DCHECK(CalledOnValidThread());
    566 
    567   // Update the auth error state so auth errors are appropriately communicated
    568   // to the user.
    569   UpdateAuthError(fetcher->GetAccountId(), fetcher->error());
    570 
    571   // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh
    572   // token and scope set. This is guaranteed as follows; here a Fetcher is said
    573   // to be uncompleted if it has not finished calling back
    574   // OAuth2TokenService::OnFetchComplete().
    575   //
    576   // (1) All the live Fetchers are created by this service.
    577   //     This is because (1) all the live Fetchers are created by a live
    578   //     service, as all the fetchers created by a service are destructed in the
    579   //     service's dtor.
    580   //
    581   // (2) All the uncompleted Fetchers created by this service are recorded in
    582   //     |pending_fetchers_|.
    583   //     This is because (1) all the created Fetchers are added to
    584   //     |pending_fetchers_| (in method StartRequest()) and (2) method
    585   //     OnFetchComplete() is the only place where a Fetcher is erased from
    586   //     |pending_fetchers_|. Note no Fetcher is erased in method
    587   //     StartRequest().
    588   //
    589   // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its
    590   //     refresh token and ScopeSet. This is guaranteed by Fetcher creation in
    591   //     method StartRequest().
    592   //
    593   // When this method is called, |fetcher| is alive and uncompleted.
    594   // By (1), |fetcher| is created by this service.
    595   // Then by (2), |fetcher| is recorded in |pending_fetchers_|.
    596   // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet.
    597   std::map<RequestParameters, Fetcher*>::iterator iter =
    598     pending_fetchers_.find(RequestParameters(
    599         fetcher->GetClientId(),
    600         fetcher->GetAccountId(),
    601         fetcher->GetScopeSet()));
    602   DCHECK(iter != pending_fetchers_.end());
    603   DCHECK_EQ(fetcher, iter->second);
    604   pending_fetchers_.erase(iter);
    605 }
    606 
    607 bool OAuth2TokenService::HasCacheEntry(
    608     const RequestParameters& request_parameters) {
    609   const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
    610   return cache_entry && cache_entry->access_token.length();
    611 }
    612 
    613 const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry(
    614     const RequestParameters& request_parameters) {
    615   DCHECK(CalledOnValidThread());
    616   TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
    617   if (token_iterator == token_cache_.end())
    618     return NULL;
    619   if (token_iterator->second.expiration_date <= base::Time::Now()) {
    620     token_cache_.erase(token_iterator);
    621     return NULL;
    622   }
    623   return &token_iterator->second;
    624 }
    625 
    626 bool OAuth2TokenService::RemoveCacheEntry(
    627     const RequestParameters& request_parameters,
    628     const std::string& token_to_remove) {
    629   DCHECK(CalledOnValidThread());
    630   TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
    631   if (token_iterator != token_cache_.end() &&
    632       token_iterator->second.access_token == token_to_remove) {
    633     token_cache_.erase(token_iterator);
    634     return true;
    635   }
    636   return false;
    637 }
    638 
    639 void OAuth2TokenService::RegisterCacheEntry(
    640     const std::string& client_id,
    641     const std::string& account_id,
    642     const OAuth2TokenService::ScopeSet& scopes,
    643     const std::string& access_token,
    644     const base::Time& expiration_date) {
    645   DCHECK(CalledOnValidThread());
    646 
    647   CacheEntry& token = token_cache_[RequestParameters(client_id,
    648                                                      account_id,
    649                                                      scopes)];
    650   token.access_token = access_token;
    651   token.expiration_date = expiration_date;
    652 }
    653 
    654 void OAuth2TokenService::UpdateAuthError(
    655     const std::string& account_id,
    656     const GoogleServiceAuthError& error) {
    657   // Default implementation does nothing.
    658 }
    659 
    660 void OAuth2TokenService::ClearCache() {
    661   DCHECK(CalledOnValidThread());
    662   token_cache_.clear();
    663 }
    664 
    665 void OAuth2TokenService::ClearCacheForAccount(const std::string& account_id) {
    666   DCHECK(CalledOnValidThread());
    667   for (TokenCache::iterator iter = token_cache_.begin();
    668        iter != token_cache_.end();
    669        /* iter incremented in body */) {
    670     if (iter->first.account_id == account_id) {
    671       token_cache_.erase(iter++);
    672     } else {
    673       ++iter;
    674     }
    675   }
    676 }
    677 
    678 void OAuth2TokenService::CancelAllRequests() {
    679   std::vector<Fetcher*> fetchers_to_cancel;
    680   for (std::map<RequestParameters, Fetcher*>::iterator iter =
    681            pending_fetchers_.begin();
    682        iter != pending_fetchers_.end();
    683        ++iter) {
    684     fetchers_to_cancel.push_back(iter->second);
    685   }
    686   CancelFetchers(fetchers_to_cancel);
    687 }
    688 
    689 void OAuth2TokenService::CancelRequestsForAccount(
    690     const std::string& account_id) {
    691   std::vector<Fetcher*> fetchers_to_cancel;
    692   for (std::map<RequestParameters, Fetcher*>::iterator iter =
    693            pending_fetchers_.begin();
    694        iter != pending_fetchers_.end();
    695        ++iter) {
    696     if (iter->first.account_id == account_id)
    697       fetchers_to_cancel.push_back(iter->second);
    698   }
    699   CancelFetchers(fetchers_to_cancel);
    700 }
    701 
    702 void OAuth2TokenService::CancelFetchers(
    703     std::vector<Fetcher*> fetchers_to_cancel) {
    704   for (std::vector<OAuth2TokenService::Fetcher*>::iterator iter =
    705            fetchers_to_cancel.begin();
    706        iter != fetchers_to_cancel.end();
    707        ++iter) {
    708     (*iter)->Cancel();
    709   }
    710 }
    711 
    712 void OAuth2TokenService::FireRefreshTokenAvailable(
    713     const std::string& account_id) {
    714   FOR_EACH_OBSERVER(Observer, observer_list_,
    715                     OnRefreshTokenAvailable(account_id));
    716 }
    717 
    718 void OAuth2TokenService::FireRefreshTokenRevoked(
    719     const std::string& account_id) {
    720   FOR_EACH_OBSERVER(Observer, observer_list_,
    721                     OnRefreshTokenRevoked(account_id));
    722 }
    723 
    724 void OAuth2TokenService::FireRefreshTokensLoaded() {
    725   FOR_EACH_OBSERVER(Observer, observer_list_, OnRefreshTokensLoaded());
    726 }
    727 
    728 int OAuth2TokenService::cache_size_for_testing() const {
    729   return token_cache_.size();
    730 }
    731 
    732 void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing(
    733     int max_retries) {
    734   DCHECK(CalledOnValidThread());
    735   max_fetch_retry_num_ = max_retries;
    736 }
    737 
    738 size_t OAuth2TokenService::GetNumPendingRequestsForTesting(
    739     const std::string& client_id,
    740     const std::string& account_id,
    741     const ScopeSet& scopes) const {
    742   PendingFetcherMap::const_iterator iter = pending_fetchers_.find(
    743       OAuth2TokenService::RequestParameters(
    744           client_id,
    745           account_id,
    746           scopes));
    747   return iter == pending_fetchers_.end() ?
    748              0 : iter->second->GetWaitingRequestCount();
    749 }
    750