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