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.
5 #include "google_apis/gaia/oauth2_token_service.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/metrics/histogram_macros.h"
13 #include "base/profiler/scoped_tracker.h"
14 #include "base/rand_util.h"
15 #include "base/stl_util.h"
16 #include "base/time/time.h"
17 #include "base/timer/timer.h"
18 #include "google_apis/gaia/gaia_urls.h"
19 #include "google_apis/gaia/google_service_auth_error.h"
20 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
21 #include "net/url_request/url_request_context_getter.h"
23 int OAuth2TokenService::max_fetch_retry_num_
= 5;
25 OAuth2TokenService::RequestParameters::RequestParameters(
26 const std::string
& client_id
,
27 const std::string
& account_id
,
28 const ScopeSet
& scopes
)
29 : client_id(client_id
),
30 account_id(account_id
),
34 OAuth2TokenService::RequestParameters::~RequestParameters() {
37 bool OAuth2TokenService::RequestParameters::operator<(
38 const RequestParameters
& p
) const {
39 if (client_id
< p
.client_id
)
41 else if (p
.client_id
< client_id
)
44 if (account_id
< p
.account_id
)
46 else if (p
.account_id
< account_id
)
49 return scopes
< p
.scopes
;
52 OAuth2TokenService::RequestImpl::RequestImpl(
53 const std::string
& account_id
,
54 OAuth2TokenService::Consumer
* consumer
)
55 : account_id_(account_id
),
59 OAuth2TokenService::RequestImpl::~RequestImpl() {
60 DCHECK(CalledOnValidThread());
63 std::string
OAuth2TokenService::RequestImpl::GetAccountId() const {
67 std::string
OAuth2TokenService::RequestImpl::GetConsumerId() const {
68 return consumer_
->id();
71 void OAuth2TokenService::RequestImpl::InformConsumer(
72 const GoogleServiceAuthError
& error
,
73 const std::string
& access_token
,
74 const base::Time
& expiration_date
) {
75 DCHECK(CalledOnValidThread());
76 if (error
.state() == GoogleServiceAuthError::NONE
)
77 consumer_
->OnGetTokenSuccess(this, access_token
, expiration_date
);
79 consumer_
->OnGetTokenFailure(this, error
);
82 OAuth2TokenService::ScopedBatchChange::ScopedBatchChange(
83 OAuth2TokenService
* token_service
) : token_service_(token_service
) {
84 DCHECK(token_service_
);
85 token_service_
->StartBatchChanges();
88 OAuth2TokenService::ScopedBatchChange::~ScopedBatchChange() {
89 token_service_
->EndBatchChanges();
92 // Class that fetches an OAuth2 access token for a given account id and set of
95 // It aims to meet OAuth2TokenService's requirements on token fetching. Retry
96 // mechanism is used to handle failures.
98 // To use this class, call CreateAndStart() to create and start a Fetcher.
100 // The Fetcher will call back the service by calling
101 // OAuth2TokenService::OnFetchComplete() when it completes fetching, if it is
102 // not destructed before it completes fetching; if the Fetcher is destructed
103 // before it completes fetching, the service will never be called back. The
104 // Fetcher destructs itself after calling back the service when finishes
107 // Requests that are waiting for the fetching results of this Fetcher can be
108 // added to the Fetcher by calling
109 // OAuth2TokenService::Fetcher::AddWaitingRequest() before the Fetcher
110 // completes fetching.
112 // The waiting requests are taken as weak pointers and they can be deleted.
113 // The waiting requests will be called back with fetching results if they are
115 // - when the Fetcher completes fetching, if the Fetcher is not destructed
116 // before it completes fetching, or
117 // - when the Fetcher is destructed if the Fetcher is destructed before it
118 // completes fetching (in this case, the waiting requests will be called
120 class OAuth2TokenService::Fetcher
: public OAuth2AccessTokenConsumer
{
122 // Creates a Fetcher and starts fetching an OAuth2 access token for
123 // |account_id| and |scopes| in the request context obtained by |getter|.
124 // The given |oauth2_token_service| will be informed when fetching is done.
125 static Fetcher
* CreateAndStart(OAuth2TokenService
* oauth2_token_service
,
126 const std::string
& account_id
,
127 net::URLRequestContextGetter
* getter
,
128 const std::string
& client_id
,
129 const std::string
& client_secret
,
130 const ScopeSet
& scopes
,
131 base::WeakPtr
<RequestImpl
> waiting_request
);
134 // Add a request that is waiting for the result of this Fetcher.
135 void AddWaitingRequest(base::WeakPtr
<RequestImpl
> waiting_request
);
137 // Returns count of waiting requests.
138 size_t GetWaitingRequestCount() const;
140 const std::vector
<base::WeakPtr
<RequestImpl
> >& waiting_requests() const {
141 return waiting_requests_
;
146 const ScopeSet
& GetScopeSet() const;
147 const std::string
& GetClientId() const;
148 const std::string
& GetAccountId() const;
150 // The error result from this fetcher.
151 const GoogleServiceAuthError
& error() const { return error_
; }
154 // OAuth2AccessTokenConsumer
155 void OnGetTokenSuccess(const std::string
& access_token
,
156 const base::Time
& expiration_date
) override
;
157 void OnGetTokenFailure(const GoogleServiceAuthError
& error
) override
;
160 Fetcher(OAuth2TokenService
* oauth2_token_service
,
161 const std::string
& account_id
,
162 net::URLRequestContextGetter
* getter
,
163 const std::string
& client_id
,
164 const std::string
& client_secret
,
165 const OAuth2TokenService::ScopeSet
& scopes
,
166 base::WeakPtr
<RequestImpl
> waiting_request
);
168 void InformWaitingRequests();
169 void InformWaitingRequestsAndDelete();
170 static bool ShouldRetry(const GoogleServiceAuthError
& error
);
171 int64
ComputeExponentialBackOffMilliseconds(int retry_num
);
173 // |oauth2_token_service_| remains valid for the life of this Fetcher, since
174 // this Fetcher is destructed in the dtor of the OAuth2TokenService or is
175 // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess
176 // (whichever comes first).
177 OAuth2TokenService
* const oauth2_token_service_
;
178 scoped_refptr
<net::URLRequestContextGetter
> getter_
;
179 const std::string account_id_
;
180 const ScopeSet scopes_
;
181 std::vector
<base::WeakPtr
<RequestImpl
> > waiting_requests_
;
184 base::OneShotTimer
<Fetcher
> retry_timer_
;
185 scoped_ptr
<OAuth2AccessTokenFetcher
> fetcher_
;
187 // Variables that store fetch results.
188 // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle
190 GoogleServiceAuthError error_
;
191 std::string access_token_
;
192 base::Time expiration_date_
;
194 // OAuth2 client id and secret.
195 std::string client_id_
;
196 std::string client_secret_
;
198 DISALLOW_COPY_AND_ASSIGN(Fetcher
);
202 OAuth2TokenService::Fetcher
* OAuth2TokenService::Fetcher::CreateAndStart(
203 OAuth2TokenService
* oauth2_token_service
,
204 const std::string
& account_id
,
205 net::URLRequestContextGetter
* getter
,
206 const std::string
& client_id
,
207 const std::string
& client_secret
,
208 const OAuth2TokenService::ScopeSet
& scopes
,
209 base::WeakPtr
<RequestImpl
> waiting_request
) {
210 OAuth2TokenService::Fetcher
* fetcher
= new Fetcher(
211 oauth2_token_service
,
219 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
221 tracked_objects::ScopedTracker
tracking_profile(
222 FROM_HERE_WITH_EXPLICIT_FUNCTION(
223 "422460 OAuth2TokenService::Fetcher::CreateAndStart"));
229 OAuth2TokenService::Fetcher::Fetcher(
230 OAuth2TokenService
* oauth2_token_service
,
231 const std::string
& account_id
,
232 net::URLRequestContextGetter
* getter
,
233 const std::string
& client_id
,
234 const std::string
& client_secret
,
235 const OAuth2TokenService::ScopeSet
& scopes
,
236 base::WeakPtr
<RequestImpl
> waiting_request
)
237 : oauth2_token_service_(oauth2_token_service
),
239 account_id_(account_id
),
242 error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE
),
243 client_id_(client_id
),
244 client_secret_(client_secret
) {
245 DCHECK(oauth2_token_service_
);
246 waiting_requests_
.push_back(waiting_request
);
249 OAuth2TokenService::Fetcher::~Fetcher() {
250 // Inform the waiting requests if it has not done so.
251 if (waiting_requests_
.size())
252 InformWaitingRequests();
255 void OAuth2TokenService::Fetcher::Start() {
256 fetcher_
.reset(oauth2_token_service_
->CreateAccessTokenFetcher(
257 account_id_
, getter_
.get(), this));
259 fetcher_
->Start(client_id_
,
261 std::vector
<std::string
>(scopes_
.begin(), scopes_
.end()));
265 void OAuth2TokenService::Fetcher::OnGetTokenSuccess(
266 const std::string
& access_token
,
267 const base::Time
& expiration_date
) {
271 error_
= GoogleServiceAuthError::AuthErrorNone();
272 access_token_
= access_token
;
273 expiration_date_
= expiration_date
;
275 // Subclasses may override this method to skip caching in some cases, but
276 // we still inform all waiting Consumers of a successful token fetch below.
277 // This is intentional -- some consumers may need the token for cleanup
278 // tasks. https://chromiumcodereview.appspot.com/11312124/
279 oauth2_token_service_
->RegisterCacheEntry(client_id_
,
284 InformWaitingRequestsAndDelete();
287 void OAuth2TokenService::Fetcher::OnGetTokenFailure(
288 const GoogleServiceAuthError
& error
) {
291 if (ShouldRetry(error
) && retry_number_
< max_fetch_retry_num_
) {
292 base::TimeDelta backoff
= base::TimeDelta::FromMilliseconds(
293 ComputeExponentialBackOffMilliseconds(retry_number_
));
295 UMA_HISTOGRAM_ENUMERATION("Signin.OAuth2TokenGetRetry",
296 error
.state(), GoogleServiceAuthError::NUM_STATES
);
298 retry_timer_
.Start(FROM_HERE
,
301 &OAuth2TokenService::Fetcher::Start
);
305 UMA_HISTOGRAM_ENUMERATION("Signin.OAuth2TokenGetFailure",
306 error
.state(), GoogleServiceAuthError::NUM_STATES
);
308 InformWaitingRequestsAndDelete();
311 // Returns an exponential backoff in milliseconds including randomness less than
312 // 1000 ms when retrying fetching an OAuth2 access token.
313 int64
OAuth2TokenService::Fetcher::ComputeExponentialBackOffMilliseconds(
315 DCHECK(retry_num
< max_fetch_retry_num_
);
316 int64 exponential_backoff_in_seconds
= 1 << retry_num
;
317 // Returns a backoff with randomness < 1000ms
318 return (exponential_backoff_in_seconds
+ base::RandDouble()) * 1000;
322 bool OAuth2TokenService::Fetcher::ShouldRetry(
323 const GoogleServiceAuthError
& error
) {
324 GoogleServiceAuthError::State error_state
= error
.state();
325 return error_state
== GoogleServiceAuthError::CONNECTION_FAILED
||
326 error_state
== GoogleServiceAuthError::REQUEST_CANCELED
||
327 error_state
== GoogleServiceAuthError::SERVICE_UNAVAILABLE
;
330 void OAuth2TokenService::Fetcher::InformWaitingRequests() {
331 std::vector
<base::WeakPtr
<RequestImpl
> >::const_iterator iter
=
332 waiting_requests_
.begin();
333 for (; iter
!= waiting_requests_
.end(); ++iter
) {
334 base::WeakPtr
<RequestImpl
> waiting_request
= *iter
;
335 if (waiting_request
.get())
336 waiting_request
->InformConsumer(error_
, access_token_
, expiration_date_
);
338 waiting_requests_
.clear();
341 void OAuth2TokenService::Fetcher::InformWaitingRequestsAndDelete() {
342 // Deregisters itself from the service to prevent more waiting requests to
343 // be added when it calls back the waiting requests.
344 oauth2_token_service_
->OnFetchComplete(this);
345 InformWaitingRequests();
346 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
349 void OAuth2TokenService::Fetcher::AddWaitingRequest(
350 base::WeakPtr
<OAuth2TokenService::RequestImpl
> waiting_request
) {
351 waiting_requests_
.push_back(waiting_request
);
354 size_t OAuth2TokenService::Fetcher::GetWaitingRequestCount() const {
355 return waiting_requests_
.size();
358 void OAuth2TokenService::Fetcher::Cancel() {
360 fetcher_
->CancelRequest();
363 error_
= GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED
);
364 InformWaitingRequestsAndDelete();
367 const OAuth2TokenService::ScopeSet
& OAuth2TokenService::Fetcher::GetScopeSet()
372 const std::string
& OAuth2TokenService::Fetcher::GetClientId() const {
376 const std::string
& OAuth2TokenService::Fetcher::GetAccountId() const {
380 OAuth2TokenService::Request::Request() {
383 OAuth2TokenService::Request::~Request() {
386 OAuth2TokenService::Consumer::Consumer(const std::string
& id
)
389 OAuth2TokenService::Consumer::~Consumer() {
392 OAuth2TokenService::OAuth2TokenService() : batch_change_depth_(0) {
395 OAuth2TokenService::~OAuth2TokenService() {
396 // Release all the pending fetchers.
397 STLDeleteContainerPairSecondPointers(
398 pending_fetchers_
.begin(), pending_fetchers_
.end());
401 void OAuth2TokenService::AddObserver(Observer
* observer
) {
402 observer_list_
.AddObserver(observer
);
405 void OAuth2TokenService::RemoveObserver(Observer
* observer
) {
406 observer_list_
.RemoveObserver(observer
);
409 void OAuth2TokenService::AddDiagnosticsObserver(DiagnosticsObserver
* observer
) {
410 diagnostics_observer_list_
.AddObserver(observer
);
413 void OAuth2TokenService::RemoveDiagnosticsObserver(
414 DiagnosticsObserver
* observer
) {
415 diagnostics_observer_list_
.RemoveObserver(observer
);
418 std::vector
<std::string
> OAuth2TokenService::GetAccounts() {
419 return std::vector
<std::string
>();
422 scoped_ptr
<OAuth2TokenService::Request
> OAuth2TokenService::StartRequest(
423 const std::string
& account_id
,
424 const OAuth2TokenService::ScopeSet
& scopes
,
425 OAuth2TokenService::Consumer
* consumer
) {
426 return StartRequestForClientWithContext(
429 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
430 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
435 scoped_ptr
<OAuth2TokenService::Request
>
436 OAuth2TokenService::StartRequestForClient(
437 const std::string
& account_id
,
438 const std::string
& client_id
,
439 const std::string
& client_secret
,
440 const OAuth2TokenService::ScopeSet
& scopes
,
441 OAuth2TokenService::Consumer
* consumer
) {
442 return StartRequestForClientWithContext(
451 scoped_ptr
<OAuth2TokenService::Request
>
452 OAuth2TokenService::StartRequestWithContext(
453 const std::string
& account_id
,
454 net::URLRequestContextGetter
* getter
,
455 const ScopeSet
& scopes
,
456 Consumer
* consumer
) {
457 return StartRequestForClientWithContext(
460 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
461 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
466 scoped_ptr
<OAuth2TokenService::Request
>
467 OAuth2TokenService::StartRequestForClientWithContext(
468 const std::string
& account_id
,
469 net::URLRequestContextGetter
* getter
,
470 const std::string
& client_id
,
471 const std::string
& client_secret
,
472 const ScopeSet
& scopes
,
473 Consumer
* consumer
) {
474 DCHECK(CalledOnValidThread());
476 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
478 tracked_objects::ScopedTracker
tracking_profile1(
479 FROM_HERE_WITH_EXPLICIT_FUNCTION(
480 "422460 OAuth2TokenService::StartRequestForClientWithContext 1"));
482 scoped_ptr
<RequestImpl
> request(new RequestImpl(account_id
, consumer
));
483 FOR_EACH_OBSERVER(DiagnosticsObserver
, diagnostics_observer_list_
,
484 OnAccessTokenRequested(account_id
,
488 if (!RefreshTokenIsAvailable(account_id
)) {
489 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460
491 tracked_objects::ScopedTracker
tracking_profile2(
492 FROM_HERE_WITH_EXPLICIT_FUNCTION(
493 "422460 OAuth2TokenService::StartRequestForClientWithContext 2"));
495 GoogleServiceAuthError
error(GoogleServiceAuthError::USER_NOT_SIGNED_UP
);
497 FOR_EACH_OBSERVER(DiagnosticsObserver
, diagnostics_observer_list_
,
498 OnFetchAccessTokenComplete(
499 account_id
, consumer
->id(), scopes
, error
,
502 base::MessageLoop::current()->PostTask(FROM_HERE
, base::Bind(
503 &RequestImpl::InformConsumer
,
504 request
->AsWeakPtr(),
508 return request
.Pass();
511 RequestParameters
request_parameters(client_id
,
514 if (HasCacheEntry(request_parameters
)) {
515 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460
517 tracked_objects::ScopedTracker
tracking_profile3(
518 FROM_HERE_WITH_EXPLICIT_FUNCTION(
519 "422460 OAuth2TokenService::StartRequestForClientWithContext 3"));
521 StartCacheLookupRequest(request
.get(), request_parameters
, consumer
);
523 FetchOAuth2Token(request
.get(),
530 return request
.Pass();
533 void OAuth2TokenService::FetchOAuth2Token(RequestImpl
* request
,
534 const std::string
& account_id
,
535 net::URLRequestContextGetter
* getter
,
536 const std::string
& client_id
,
537 const std::string
& client_secret
,
538 const ScopeSet
& scopes
) {
539 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
541 tracked_objects::ScopedTracker
tracking_profile(
542 FROM_HERE_WITH_EXPLICIT_FUNCTION(
543 "422460 OAuth2TokenService::FetchOAuth2Token"));
545 // If there is already a pending fetcher for |scopes| and |account_id|,
546 // simply register this |request| for those results rather than starting
548 RequestParameters request_parameters
= RequestParameters(client_id
,
551 std::map
<RequestParameters
, Fetcher
*>::iterator iter
=
552 pending_fetchers_
.find(request_parameters
);
553 if (iter
!= pending_fetchers_
.end()) {
554 iter
->second
->AddWaitingRequest(request
->AsWeakPtr());
558 pending_fetchers_
[request_parameters
] =
559 Fetcher::CreateAndStart(this,
565 request
->AsWeakPtr());
568 void OAuth2TokenService::StartCacheLookupRequest(
569 RequestImpl
* request
,
570 const OAuth2TokenService::RequestParameters
& request_parameters
,
571 OAuth2TokenService::Consumer
* consumer
) {
572 CHECK(HasCacheEntry(request_parameters
));
573 const CacheEntry
* cache_entry
= GetCacheEntry(request_parameters
);
574 FOR_EACH_OBSERVER(DiagnosticsObserver
, diagnostics_observer_list_
,
575 OnFetchAccessTokenComplete(
576 request_parameters
.account_id
,
578 request_parameters
.scopes
,
579 GoogleServiceAuthError::AuthErrorNone(),
580 cache_entry
->expiration_date
));
581 base::MessageLoop::current()->PostTask(FROM_HERE
, base::Bind(
582 &RequestImpl::InformConsumer
,
583 request
->AsWeakPtr(),
584 GoogleServiceAuthError(GoogleServiceAuthError::NONE
),
585 cache_entry
->access_token
,
586 cache_entry
->expiration_date
));
589 void OAuth2TokenService::InvalidateToken(const std::string
& account_id
,
590 const ScopeSet
& scopes
,
591 const std::string
& access_token
) {
592 InvalidateOAuth2Token(account_id
,
593 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
598 void OAuth2TokenService::InvalidateTokenForClient(
599 const std::string
& account_id
,
600 const std::string
& client_id
,
601 const ScopeSet
& scopes
,
602 const std::string
& access_token
) {
603 InvalidateOAuth2Token(account_id
, client_id
, scopes
, access_token
);
606 void OAuth2TokenService::InvalidateOAuth2Token(
607 const std::string
& account_id
,
608 const std::string
& client_id
,
609 const ScopeSet
& scopes
,
610 const std::string
& access_token
) {
611 DCHECK(CalledOnValidThread());
613 RequestParameters(client_id
,
619 void OAuth2TokenService::OnFetchComplete(Fetcher
* fetcher
) {
620 DCHECK(CalledOnValidThread());
622 // Update the auth error state so auth errors are appropriately communicated
624 UpdateAuthError(fetcher
->GetAccountId(), fetcher
->error());
626 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh
627 // token and scope set. This is guaranteed as follows; here a Fetcher is said
628 // to be uncompleted if it has not finished calling back
629 // OAuth2TokenService::OnFetchComplete().
631 // (1) All the live Fetchers are created by this service.
632 // This is because (1) all the live Fetchers are created by a live
633 // service, as all the fetchers created by a service are destructed in the
636 // (2) All the uncompleted Fetchers created by this service are recorded in
637 // |pending_fetchers_|.
638 // This is because (1) all the created Fetchers are added to
639 // |pending_fetchers_| (in method StartRequest()) and (2) method
640 // OnFetchComplete() is the only place where a Fetcher is erased from
641 // |pending_fetchers_|. Note no Fetcher is erased in method
644 // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its
645 // refresh token and ScopeSet. This is guaranteed by Fetcher creation in
646 // method StartRequest().
648 // When this method is called, |fetcher| is alive and uncompleted.
649 // By (1), |fetcher| is created by this service.
650 // Then by (2), |fetcher| is recorded in |pending_fetchers_|.
651 // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet.
652 RequestParameters
request_param(fetcher
->GetClientId(),
653 fetcher
->GetAccountId(),
654 fetcher
->GetScopeSet());
656 const OAuth2TokenService::CacheEntry
* entry
= GetCacheEntry(request_param
);
657 const std::vector
<base::WeakPtr
<RequestImpl
> >& requests
=
658 fetcher
->waiting_requests();
659 for (size_t i
= 0; i
< requests
.size(); ++i
) {
660 const RequestImpl
* req
= requests
[i
].get();
662 FOR_EACH_OBSERVER(DiagnosticsObserver
, diagnostics_observer_list_
,
663 OnFetchAccessTokenComplete(
664 req
->GetAccountId(), req
->GetConsumerId(),
665 fetcher
->GetScopeSet(), fetcher
->error(),
666 entry
? entry
->expiration_date
: base::Time()));
670 std::map
<RequestParameters
, Fetcher
*>::iterator iter
=
671 pending_fetchers_
.find(request_param
);
672 DCHECK(iter
!= pending_fetchers_
.end());
673 DCHECK_EQ(fetcher
, iter
->second
);
674 pending_fetchers_
.erase(iter
);
677 bool OAuth2TokenService::HasCacheEntry(
678 const RequestParameters
& request_parameters
) {
679 const CacheEntry
* cache_entry
= GetCacheEntry(request_parameters
);
680 return cache_entry
&& cache_entry
->access_token
.length();
683 const OAuth2TokenService::CacheEntry
* OAuth2TokenService::GetCacheEntry(
684 const RequestParameters
& request_parameters
) {
685 DCHECK(CalledOnValidThread());
686 TokenCache::iterator token_iterator
= token_cache_
.find(request_parameters
);
687 if (token_iterator
== token_cache_
.end())
689 if (token_iterator
->second
.expiration_date
<= base::Time::Now()) {
690 token_cache_
.erase(token_iterator
);
693 return &token_iterator
->second
;
696 bool OAuth2TokenService::RemoveCacheEntry(
697 const RequestParameters
& request_parameters
,
698 const std::string
& token_to_remove
) {
699 DCHECK(CalledOnValidThread());
700 TokenCache::iterator token_iterator
= token_cache_
.find(request_parameters
);
701 if (token_iterator
!= token_cache_
.end() &&
702 token_iterator
->second
.access_token
== token_to_remove
) {
703 FOR_EACH_OBSERVER(DiagnosticsObserver
, diagnostics_observer_list_
,
704 OnTokenRemoved(request_parameters
.account_id
,
705 request_parameters
.scopes
));
706 token_cache_
.erase(token_iterator
);
712 void OAuth2TokenService::RegisterCacheEntry(
713 const std::string
& client_id
,
714 const std::string
& account_id
,
715 const OAuth2TokenService::ScopeSet
& scopes
,
716 const std::string
& access_token
,
717 const base::Time
& expiration_date
) {
718 DCHECK(CalledOnValidThread());
720 CacheEntry
& token
= token_cache_
[RequestParameters(client_id
,
723 token
.access_token
= access_token
;
724 token
.expiration_date
= expiration_date
;
727 void OAuth2TokenService::UpdateAuthError(
728 const std::string
& account_id
,
729 const GoogleServiceAuthError
& error
) {
730 // Default implementation does nothing.
733 void OAuth2TokenService::ClearCache() {
734 DCHECK(CalledOnValidThread());
735 for (TokenCache::iterator iter
= token_cache_
.begin();
736 iter
!= token_cache_
.end(); ++iter
) {
737 FOR_EACH_OBSERVER(DiagnosticsObserver
, diagnostics_observer_list_
,
738 OnTokenRemoved(iter
->first
.account_id
,
739 iter
->first
.scopes
));
742 token_cache_
.clear();
745 void OAuth2TokenService::ClearCacheForAccount(const std::string
& account_id
) {
746 DCHECK(CalledOnValidThread());
747 for (TokenCache::iterator iter
= token_cache_
.begin();
748 iter
!= token_cache_
.end();
749 /* iter incremented in body */) {
750 if (iter
->first
.account_id
== account_id
) {
751 FOR_EACH_OBSERVER(DiagnosticsObserver
, diagnostics_observer_list_
,
752 OnTokenRemoved(account_id
, iter
->first
.scopes
));
753 token_cache_
.erase(iter
++);
760 void OAuth2TokenService::CancelAllRequests() {
761 std::vector
<Fetcher
*> fetchers_to_cancel
;
762 for (std::map
<RequestParameters
, Fetcher
*>::iterator iter
=
763 pending_fetchers_
.begin();
764 iter
!= pending_fetchers_
.end();
766 fetchers_to_cancel
.push_back(iter
->second
);
768 CancelFetchers(fetchers_to_cancel
);
771 void OAuth2TokenService::CancelRequestsForAccount(
772 const std::string
& account_id
) {
773 std::vector
<Fetcher
*> fetchers_to_cancel
;
774 for (std::map
<RequestParameters
, Fetcher
*>::iterator iter
=
775 pending_fetchers_
.begin();
776 iter
!= pending_fetchers_
.end();
778 if (iter
->first
.account_id
== account_id
)
779 fetchers_to_cancel
.push_back(iter
->second
);
781 CancelFetchers(fetchers_to_cancel
);
784 void OAuth2TokenService::CancelFetchers(
785 std::vector
<Fetcher
*> fetchers_to_cancel
) {
786 for (std::vector
<OAuth2TokenService::Fetcher
*>::iterator iter
=
787 fetchers_to_cancel
.begin();
788 iter
!= fetchers_to_cancel
.end();
794 void OAuth2TokenService::FireRefreshTokenAvailable(
795 const std::string
& account_id
) {
796 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
798 tracked_objects::ScopedTracker
tracking_profile(
799 FROM_HERE_WITH_EXPLICIT_FUNCTION(
800 "422460 OAuth2TokenService::FireRefreshTokenAvailable"));
802 FOR_EACH_OBSERVER(Observer
, observer_list_
,
803 OnRefreshTokenAvailable(account_id
));
806 void OAuth2TokenService::FireRefreshTokenRevoked(
807 const std::string
& account_id
) {
808 FOR_EACH_OBSERVER(Observer
, observer_list_
,
809 OnRefreshTokenRevoked(account_id
));
812 void OAuth2TokenService::FireRefreshTokensLoaded() {
813 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
815 tracked_objects::ScopedTracker
tracking_profile(
816 FROM_HERE_WITH_EXPLICIT_FUNCTION(
817 "422460 OAuth2TokenService::FireRefreshTokensLoaded"));
819 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnRefreshTokensLoaded());
822 void OAuth2TokenService::StartBatchChanges() {
823 ++batch_change_depth_
;
824 if (batch_change_depth_
== 1)
825 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnStartBatchChanges());
828 void OAuth2TokenService::EndBatchChanges() {
829 --batch_change_depth_
;
830 DCHECK_LE(0, batch_change_depth_
);
831 if (batch_change_depth_
== 0)
832 FOR_EACH_OBSERVER(Observer
, observer_list_
, OnEndBatchChanges());
835 int OAuth2TokenService::cache_size_for_testing() const {
836 return token_cache_
.size();
839 void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing(
841 DCHECK(CalledOnValidThread());
842 max_fetch_retry_num_
= max_retries
;
845 size_t OAuth2TokenService::GetNumPendingRequestsForTesting(
846 const std::string
& client_id
,
847 const std::string
& account_id
,
848 const ScopeSet
& scopes
) const {
849 PendingFetcherMap::const_iterator iter
= pending_fetchers_
.find(
850 OAuth2TokenService::RequestParameters(
854 return iter
== pending_fetchers_
.end() ?
855 0 : iter
->second
->GetWaitingRequestCount();