Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / google_apis / gaia / oauth2_token_service.cc
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   DCHECK(getter_.get());
239   waiting_requests_.push_back(waiting_request);
240 }
241
242 OAuth2TokenService::Fetcher::~Fetcher() {
243   // Inform the waiting requests if it has not done so.
244   if (waiting_requests_.size())
245     InformWaitingRequests();
246 }
247
248 void OAuth2TokenService::Fetcher::Start() {
249   fetcher_.reset(oauth2_token_service_->CreateAccessTokenFetcher(
250       account_id_, getter_.get(), this));
251   DCHECK(fetcher_);
252   fetcher_->Start(client_id_,
253                   client_secret_,
254                   std::vector<std::string>(scopes_.begin(), scopes_.end()));
255   retry_timer_.Stop();
256 }
257
258 void OAuth2TokenService::Fetcher::OnGetTokenSuccess(
259     const std::string& access_token,
260     const base::Time& expiration_date) {
261   fetcher_.reset();
262
263   // Fetch completes.
264   error_ = GoogleServiceAuthError::AuthErrorNone();
265   access_token_ = access_token;
266   expiration_date_ = expiration_date;
267
268   // Subclasses may override this method to skip caching in some cases, but
269   // we still inform all waiting Consumers of a successful token fetch below.
270   // This is intentional -- some consumers may need the token for cleanup
271   // tasks. https://chromiumcodereview.appspot.com/11312124/
272   oauth2_token_service_->RegisterCacheEntry(client_id_,
273                                             account_id_,
274                                             scopes_,
275                                             access_token_,
276                                             expiration_date_);
277   InformWaitingRequestsAndDelete();
278 }
279
280 void OAuth2TokenService::Fetcher::OnGetTokenFailure(
281     const GoogleServiceAuthError& error) {
282   fetcher_.reset();
283
284   if (ShouldRetry(error) && retry_number_ < max_fetch_retry_num_) {
285     base::TimeDelta backoff = base::TimeDelta::FromMilliseconds(
286         ComputeExponentialBackOffMilliseconds(retry_number_));
287     ++retry_number_;
288     retry_timer_.Stop();
289     retry_timer_.Start(FROM_HERE,
290                        backoff,
291                        this,
292                        &OAuth2TokenService::Fetcher::Start);
293     return;
294   }
295
296   error_ = error;
297   InformWaitingRequestsAndDelete();
298 }
299
300 // Returns an exponential backoff in milliseconds including randomness less than
301 // 1000 ms when retrying fetching an OAuth2 access token.
302 int64 OAuth2TokenService::Fetcher::ComputeExponentialBackOffMilliseconds(
303     int retry_num) {
304   DCHECK(retry_num < max_fetch_retry_num_);
305   int64 exponential_backoff_in_seconds = 1 << retry_num;
306   // Returns a backoff with randomness < 1000ms
307   return (exponential_backoff_in_seconds + base::RandDouble()) * 1000;
308 }
309
310 // static
311 bool OAuth2TokenService::Fetcher::ShouldRetry(
312     const GoogleServiceAuthError& error) {
313   GoogleServiceAuthError::State error_state = error.state();
314   return error_state == GoogleServiceAuthError::CONNECTION_FAILED ||
315          error_state == GoogleServiceAuthError::REQUEST_CANCELED ||
316          error_state == GoogleServiceAuthError::SERVICE_UNAVAILABLE;
317 }
318
319 void OAuth2TokenService::Fetcher::InformWaitingRequests() {
320   std::vector<base::WeakPtr<RequestImpl> >::const_iterator iter =
321       waiting_requests_.begin();
322   for (; iter != waiting_requests_.end(); ++iter) {
323     base::WeakPtr<RequestImpl> waiting_request = *iter;
324     if (waiting_request.get())
325       waiting_request->InformConsumer(error_, access_token_, expiration_date_);
326   }
327   waiting_requests_.clear();
328 }
329
330 void OAuth2TokenService::Fetcher::InformWaitingRequestsAndDelete() {
331   // Deregisters itself from the service to prevent more waiting requests to
332   // be added when it calls back the waiting requests.
333   oauth2_token_service_->OnFetchComplete(this);
334   InformWaitingRequests();
335   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
336 }
337
338 void OAuth2TokenService::Fetcher::AddWaitingRequest(
339     base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) {
340   waiting_requests_.push_back(waiting_request);
341 }
342
343 size_t OAuth2TokenService::Fetcher::GetWaitingRequestCount() const {
344   return waiting_requests_.size();
345 }
346
347 void OAuth2TokenService::Fetcher::Cancel() {
348   fetcher_.reset();
349   retry_timer_.Stop();
350   error_ = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
351   InformWaitingRequestsAndDelete();
352 }
353
354 const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet()
355     const {
356   return scopes_;
357 }
358
359 const std::string& OAuth2TokenService::Fetcher::GetClientId() const {
360   return client_id_;
361 }
362
363 const std::string& OAuth2TokenService::Fetcher::GetAccountId() const {
364   return account_id_;
365 }
366
367 OAuth2TokenService::Request::Request() {
368 }
369
370 OAuth2TokenService::Request::~Request() {
371 }
372
373 OAuth2TokenService::Consumer::Consumer(const std::string& id)
374     : id_(id) {}
375
376 OAuth2TokenService::Consumer::~Consumer() {
377 }
378
379 OAuth2TokenService::OAuth2TokenService() : batch_change_depth_(0) {
380 }
381
382 OAuth2TokenService::~OAuth2TokenService() {
383   // Release all the pending fetchers.
384   STLDeleteContainerPairSecondPointers(
385       pending_fetchers_.begin(), pending_fetchers_.end());
386 }
387
388 void OAuth2TokenService::AddObserver(Observer* observer) {
389   observer_list_.AddObserver(observer);
390 }
391
392 void OAuth2TokenService::RemoveObserver(Observer* observer) {
393   observer_list_.RemoveObserver(observer);
394 }
395
396 void OAuth2TokenService::AddDiagnosticsObserver(DiagnosticsObserver* observer) {
397   diagnostics_observer_list_.AddObserver(observer);
398 }
399
400 void OAuth2TokenService::RemoveDiagnosticsObserver(
401     DiagnosticsObserver* observer) {
402   diagnostics_observer_list_.RemoveObserver(observer);
403 }
404
405 std::vector<std::string> OAuth2TokenService::GetAccounts() {
406   return std::vector<std::string>();
407 }
408
409 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest(
410     const std::string& account_id,
411     const OAuth2TokenService::ScopeSet& scopes,
412     OAuth2TokenService::Consumer* consumer) {
413   return StartRequestForClientWithContext(
414       account_id,
415       GetRequestContext(),
416       GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
417       GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
418       scopes,
419       consumer);
420 }
421
422 scoped_ptr<OAuth2TokenService::Request>
423 OAuth2TokenService::StartRequestForClient(
424     const std::string& account_id,
425     const std::string& client_id,
426     const std::string& client_secret,
427     const OAuth2TokenService::ScopeSet& scopes,
428     OAuth2TokenService::Consumer* consumer) {
429   return StartRequestForClientWithContext(
430       account_id,
431       GetRequestContext(),
432       client_id,
433       client_secret,
434       scopes,
435       consumer);
436 }
437
438 scoped_ptr<OAuth2TokenService::Request>
439 OAuth2TokenService::StartRequestWithContext(
440     const std::string& account_id,
441     net::URLRequestContextGetter* getter,
442     const ScopeSet& scopes,
443     Consumer* consumer) {
444   return StartRequestForClientWithContext(
445       account_id,
446       getter,
447       GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
448       GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
449       scopes,
450       consumer);
451 }
452
453 scoped_ptr<OAuth2TokenService::Request>
454 OAuth2TokenService::StartRequestForClientWithContext(
455     const std::string& account_id,
456     net::URLRequestContextGetter* getter,
457     const std::string& client_id,
458     const std::string& client_secret,
459     const ScopeSet& scopes,
460     Consumer* consumer) {
461   DCHECK(CalledOnValidThread());
462
463   scoped_ptr<RequestImpl> request(new RequestImpl(account_id, consumer));
464   FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
465                     OnAccessTokenRequested(account_id,
466                                            consumer->id(),
467                                            scopes));
468
469   if (!RefreshTokenIsAvailable(account_id)) {
470     GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
471
472     FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
473                       OnFetchAccessTokenComplete(
474                           account_id, consumer->id(), scopes, error,
475                           base::Time()));
476
477     base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
478         &RequestImpl::InformConsumer,
479         request->AsWeakPtr(),
480         error,
481         std::string(),
482         base::Time()));
483     return request.PassAs<Request>();
484   }
485
486   RequestParameters request_parameters(client_id,
487                                        account_id,
488                                        scopes);
489   if (HasCacheEntry(request_parameters)) {
490     StartCacheLookupRequest(request.get(), request_parameters, consumer);
491   } else {
492     FetchOAuth2Token(request.get(),
493                      account_id,
494                      getter,
495                      client_id,
496                      client_secret,
497                      scopes);
498   }
499   return request.PassAs<Request>();
500 }
501
502 void OAuth2TokenService::FetchOAuth2Token(RequestImpl* request,
503                                           const std::string& account_id,
504                                           net::URLRequestContextGetter* getter,
505                                           const std::string& client_id,
506                                           const std::string& client_secret,
507                                           const ScopeSet& scopes) {
508   // If there is already a pending fetcher for |scopes| and |account_id|,
509   // simply register this |request| for those results rather than starting
510   // a new fetcher.
511   RequestParameters request_parameters = RequestParameters(client_id,
512                                                            account_id,
513                                                            scopes);
514   std::map<RequestParameters, Fetcher*>::iterator iter =
515       pending_fetchers_.find(request_parameters);
516   if (iter != pending_fetchers_.end()) {
517     iter->second->AddWaitingRequest(request->AsWeakPtr());
518     return;
519   }
520
521   pending_fetchers_[request_parameters] =
522       Fetcher::CreateAndStart(this,
523                               account_id,
524                               getter,
525                               client_id,
526                               client_secret,
527                               scopes,
528                               request->AsWeakPtr());
529 }
530
531 void OAuth2TokenService::StartCacheLookupRequest(
532     RequestImpl* request,
533     const OAuth2TokenService::RequestParameters& request_parameters,
534     OAuth2TokenService::Consumer* consumer) {
535   CHECK(HasCacheEntry(request_parameters));
536   const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
537   FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
538                     OnFetchAccessTokenComplete(
539                         request_parameters.account_id,
540                         consumer->id(),
541                         request_parameters.scopes,
542                         GoogleServiceAuthError::AuthErrorNone(),
543                         cache_entry->expiration_date));
544   base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
545       &RequestImpl::InformConsumer,
546       request->AsWeakPtr(),
547       GoogleServiceAuthError(GoogleServiceAuthError::NONE),
548       cache_entry->access_token,
549       cache_entry->expiration_date));
550 }
551
552 void OAuth2TokenService::InvalidateToken(const std::string& account_id,
553                                          const ScopeSet& scopes,
554                                          const std::string& access_token) {
555   InvalidateOAuth2Token(account_id,
556                         GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
557                         scopes,
558                         access_token);
559 }
560
561 void OAuth2TokenService::InvalidateTokenForClient(
562     const std::string& account_id,
563     const std::string& client_id,
564     const ScopeSet& scopes,
565     const std::string& access_token) {
566   InvalidateOAuth2Token(account_id, client_id, scopes, access_token);
567 }
568
569 void OAuth2TokenService::InvalidateOAuth2Token(
570     const std::string& account_id,
571     const std::string& client_id,
572     const ScopeSet& scopes,
573     const std::string& access_token) {
574   DCHECK(CalledOnValidThread());
575   RemoveCacheEntry(
576       RequestParameters(client_id,
577                         account_id,
578                         scopes),
579       access_token);
580 }
581
582 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) {
583   DCHECK(CalledOnValidThread());
584
585   // Update the auth error state so auth errors are appropriately communicated
586   // to the user.
587   UpdateAuthError(fetcher->GetAccountId(), fetcher->error());
588
589   // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh
590   // token and scope set. This is guaranteed as follows; here a Fetcher is said
591   // to be uncompleted if it has not finished calling back
592   // OAuth2TokenService::OnFetchComplete().
593   //
594   // (1) All the live Fetchers are created by this service.
595   //     This is because (1) all the live Fetchers are created by a live
596   //     service, as all the fetchers created by a service are destructed in the
597   //     service's dtor.
598   //
599   // (2) All the uncompleted Fetchers created by this service are recorded in
600   //     |pending_fetchers_|.
601   //     This is because (1) all the created Fetchers are added to
602   //     |pending_fetchers_| (in method StartRequest()) and (2) method
603   //     OnFetchComplete() is the only place where a Fetcher is erased from
604   //     |pending_fetchers_|. Note no Fetcher is erased in method
605   //     StartRequest().
606   //
607   // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its
608   //     refresh token and ScopeSet. This is guaranteed by Fetcher creation in
609   //     method StartRequest().
610   //
611   // When this method is called, |fetcher| is alive and uncompleted.
612   // By (1), |fetcher| is created by this service.
613   // Then by (2), |fetcher| is recorded in |pending_fetchers_|.
614   // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet.
615   RequestParameters request_param(fetcher->GetClientId(),
616                                   fetcher->GetAccountId(),
617                                   fetcher->GetScopeSet());
618
619   const OAuth2TokenService::CacheEntry* entry = GetCacheEntry(request_param);
620   const std::vector<base::WeakPtr<RequestImpl> >& requests =
621       fetcher->waiting_requests();
622   for (size_t i = 0; i < requests.size(); ++i) {
623     const RequestImpl* req = requests[i].get();
624     if (req) {
625       FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
626                         OnFetchAccessTokenComplete(
627                             req->GetAccountId(), req->GetConsumerId(),
628                             fetcher->GetScopeSet(), fetcher->error(),
629                             entry ? entry->expiration_date : base::Time()));
630     }
631   }
632
633   std::map<RequestParameters, Fetcher*>::iterator iter =
634     pending_fetchers_.find(request_param);
635   DCHECK(iter != pending_fetchers_.end());
636   DCHECK_EQ(fetcher, iter->second);
637   pending_fetchers_.erase(iter);
638 }
639
640 bool OAuth2TokenService::HasCacheEntry(
641     const RequestParameters& request_parameters) {
642   const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
643   return cache_entry && cache_entry->access_token.length();
644 }
645
646 const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry(
647     const RequestParameters& request_parameters) {
648   DCHECK(CalledOnValidThread());
649   TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
650   if (token_iterator == token_cache_.end())
651     return NULL;
652   if (token_iterator->second.expiration_date <= base::Time::Now()) {
653     token_cache_.erase(token_iterator);
654     return NULL;
655   }
656   return &token_iterator->second;
657 }
658
659 bool OAuth2TokenService::RemoveCacheEntry(
660     const RequestParameters& request_parameters,
661     const std::string& token_to_remove) {
662   DCHECK(CalledOnValidThread());
663   TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
664   if (token_iterator != token_cache_.end() &&
665       token_iterator->second.access_token == token_to_remove) {
666     FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
667                       OnTokenRemoved(request_parameters.account_id,
668                                      request_parameters.scopes));
669     token_cache_.erase(token_iterator);
670     return true;
671   }
672   return false;
673 }
674
675 void OAuth2TokenService::RegisterCacheEntry(
676     const std::string& client_id,
677     const std::string& account_id,
678     const OAuth2TokenService::ScopeSet& scopes,
679     const std::string& access_token,
680     const base::Time& expiration_date) {
681   DCHECK(CalledOnValidThread());
682
683   CacheEntry& token = token_cache_[RequestParameters(client_id,
684                                                      account_id,
685                                                      scopes)];
686   token.access_token = access_token;
687   token.expiration_date = expiration_date;
688 }
689
690 void OAuth2TokenService::UpdateAuthError(
691     const std::string& account_id,
692     const GoogleServiceAuthError& error) {
693   // Default implementation does nothing.
694 }
695
696 void OAuth2TokenService::ClearCache() {
697   DCHECK(CalledOnValidThread());
698   for (TokenCache::iterator iter = token_cache_.begin();
699        iter != token_cache_.end(); ++iter) {
700     FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
701                       OnTokenRemoved(iter->first.account_id,
702                                      iter->first.scopes));
703   }
704
705   token_cache_.clear();
706 }
707
708 void OAuth2TokenService::ClearCacheForAccount(const std::string& account_id) {
709   DCHECK(CalledOnValidThread());
710   for (TokenCache::iterator iter = token_cache_.begin();
711        iter != token_cache_.end();
712        /* iter incremented in body */) {
713     if (iter->first.account_id == account_id) {
714       FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
715                         OnTokenRemoved(account_id, iter->first.scopes));
716       token_cache_.erase(iter++);
717     } else {
718       ++iter;
719     }
720   }
721 }
722
723 void OAuth2TokenService::CancelAllRequests() {
724   std::vector<Fetcher*> fetchers_to_cancel;
725   for (std::map<RequestParameters, Fetcher*>::iterator iter =
726            pending_fetchers_.begin();
727        iter != pending_fetchers_.end();
728        ++iter) {
729     fetchers_to_cancel.push_back(iter->second);
730   }
731   CancelFetchers(fetchers_to_cancel);
732 }
733
734 void OAuth2TokenService::CancelRequestsForAccount(
735     const std::string& account_id) {
736   std::vector<Fetcher*> fetchers_to_cancel;
737   for (std::map<RequestParameters, Fetcher*>::iterator iter =
738            pending_fetchers_.begin();
739        iter != pending_fetchers_.end();
740        ++iter) {
741     if (iter->first.account_id == account_id)
742       fetchers_to_cancel.push_back(iter->second);
743   }
744   CancelFetchers(fetchers_to_cancel);
745 }
746
747 void OAuth2TokenService::CancelFetchers(
748     std::vector<Fetcher*> fetchers_to_cancel) {
749   for (std::vector<OAuth2TokenService::Fetcher*>::iterator iter =
750            fetchers_to_cancel.begin();
751        iter != fetchers_to_cancel.end();
752        ++iter) {
753     (*iter)->Cancel();
754   }
755 }
756
757 void OAuth2TokenService::FireRefreshTokenAvailable(
758     const std::string& account_id) {
759   FOR_EACH_OBSERVER(Observer, observer_list_,
760                     OnRefreshTokenAvailable(account_id));
761 }
762
763 void OAuth2TokenService::FireRefreshTokenRevoked(
764     const std::string& account_id) {
765   FOR_EACH_OBSERVER(Observer, observer_list_,
766                     OnRefreshTokenRevoked(account_id));
767 }
768
769 void OAuth2TokenService::FireRefreshTokensLoaded() {
770   FOR_EACH_OBSERVER(Observer, observer_list_, OnRefreshTokensLoaded());
771 }
772
773 void OAuth2TokenService::StartBatchChanges() {
774   ++batch_change_depth_;
775   if (batch_change_depth_ == 1)
776     FOR_EACH_OBSERVER(Observer, observer_list_, OnStartBatchChanges());
777 }
778
779 void OAuth2TokenService::EndBatchChanges() {
780   --batch_change_depth_;
781   DCHECK_LE(0, batch_change_depth_);
782   if (batch_change_depth_ == 0)
783     FOR_EACH_OBSERVER(Observer, observer_list_, OnEndBatchChanges());
784 }
785
786 int OAuth2TokenService::cache_size_for_testing() const {
787   return token_cache_.size();
788 }
789
790 void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing(
791     int max_retries) {
792   DCHECK(CalledOnValidThread());
793   max_fetch_retry_num_ = max_retries;
794 }
795
796 size_t OAuth2TokenService::GetNumPendingRequestsForTesting(
797     const std::string& client_id,
798     const std::string& account_id,
799     const ScopeSet& scopes) const {
800   PendingFetcherMap::const_iterator iter = pending_fetchers_.find(
801       OAuth2TokenService::RequestParameters(
802           client_id,
803           account_id,
804           scopes));
805   return iter == pending_fetchers_.end() ?
806              0 : iter->second->GetWaitingRequestCount();
807 }