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