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
21int OAuth2TokenService::max_fetch_retry_num_ = 5;
22
23OAuth2TokenService::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
32OAuth2TokenService::RequestParameters::~RequestParameters() {
33}
34
35bool 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
50OAuth2TokenService::RequestImpl::RequestImpl(
51    const std::string& account_id,
52    OAuth2TokenService::Consumer* consumer)
53    : account_id_(account_id),
54      consumer_(consumer) {
55}
56
57OAuth2TokenService::RequestImpl::~RequestImpl() {
58  DCHECK(CalledOnValidThread());
59}
60
61std::string OAuth2TokenService::RequestImpl::GetAccountId() const {
62  return account_id_;
63}
64
65std::string OAuth2TokenService::RequestImpl::GetConsumerId() const {
66  return consumer_->id();
67}
68
69void 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
80OAuth2TokenService::ScopedBacthChange::ScopedBacthChange(
81    OAuth2TokenService* token_service) : token_service_(token_service) {
82  DCHECK(token_service_);
83  token_service_->StartBatchChanges();
84}
85
86OAuth2TokenService::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).
118class 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
201OAuth2TokenService::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
221OAuth2TokenService::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
241OAuth2TokenService::Fetcher::~Fetcher() {
242  // Inform the waiting requests if it has not done so.
243  if (waiting_requests_.size())
244    InformWaitingRequests();
245}
246
247void 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
257void 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
279void 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.
301int64 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
310bool 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
318void 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
329void 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
337void OAuth2TokenService::Fetcher::AddWaitingRequest(
338    base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) {
339  waiting_requests_.push_back(waiting_request);
340}
341
342size_t OAuth2TokenService::Fetcher::GetWaitingRequestCount() const {
343  return waiting_requests_.size();
344}
345
346void 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
355const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet()
356    const {
357  return scopes_;
358}
359
360const std::string& OAuth2TokenService::Fetcher::GetClientId() const {
361  return client_id_;
362}
363
364const std::string& OAuth2TokenService::Fetcher::GetAccountId() const {
365  return account_id_;
366}
367
368OAuth2TokenService::Request::Request() {
369}
370
371OAuth2TokenService::Request::~Request() {
372}
373
374OAuth2TokenService::Consumer::Consumer(const std::string& id)
375    : id_(id) {}
376
377OAuth2TokenService::Consumer::~Consumer() {
378}
379
380OAuth2TokenService::OAuth2TokenService() : batch_change_depth_(0) {
381}
382
383OAuth2TokenService::~OAuth2TokenService() {
384  // Release all the pending fetchers.
385  STLDeleteContainerPairSecondPointers(
386      pending_fetchers_.begin(), pending_fetchers_.end());
387}
388
389void OAuth2TokenService::AddObserver(Observer* observer) {
390  observer_list_.AddObserver(observer);
391}
392
393void OAuth2TokenService::RemoveObserver(Observer* observer) {
394  observer_list_.RemoveObserver(observer);
395}
396
397void OAuth2TokenService::AddDiagnosticsObserver(DiagnosticsObserver* observer) {
398  diagnostics_observer_list_.AddObserver(observer);
399}
400
401void OAuth2TokenService::RemoveDiagnosticsObserver(
402    DiagnosticsObserver* observer) {
403  diagnostics_observer_list_.RemoveObserver(observer);
404}
405
406std::vector<std::string> OAuth2TokenService::GetAccounts() {
407  return std::vector<std::string>();
408}
409
410scoped_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
423scoped_ptr<OAuth2TokenService::Request>
424OAuth2TokenService::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
439scoped_ptr<OAuth2TokenService::Request>
440OAuth2TokenService::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
454scoped_ptr<OAuth2TokenService::Request>
455OAuth2TokenService::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
503void 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
532void 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
553void 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
562void 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
570void 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
583void 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
641bool 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
647const 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
660bool 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
676void 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
691void OAuth2TokenService::UpdateAuthError(
692    const std::string& account_id,
693    const GoogleServiceAuthError& error) {
694  // Default implementation does nothing.
695}
696
697void 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
709void 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
724void 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
735void 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
748void 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
758void OAuth2TokenService::FireRefreshTokenAvailable(
759    const std::string& account_id) {
760  FOR_EACH_OBSERVER(Observer, observer_list_,
761                    OnRefreshTokenAvailable(account_id));
762}
763
764void OAuth2TokenService::FireRefreshTokenRevoked(
765    const std::string& account_id) {
766  FOR_EACH_OBSERVER(Observer, observer_list_,
767                    OnRefreshTokenRevoked(account_id));
768}
769
770void OAuth2TokenService::FireRefreshTokensLoaded() {
771  FOR_EACH_OBSERVER(Observer, observer_list_, OnRefreshTokensLoaded());
772}
773
774void OAuth2TokenService::StartBatchChanges() {
775  ++batch_change_depth_;
776  if (batch_change_depth_ == 1)
777    FOR_EACH_OBSERVER(Observer, observer_list_, OnStartBatchChanges());
778}
779
780void 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
787int OAuth2TokenService::cache_size_for_testing() const {
788  return token_cache_.size();
789}
790
791void 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
797size_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