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