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