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