Make castv2 performance test work.
[chromium-blink-merge.git] / google_apis / gaia / oauth2_token_service.cc
blob34dfc1bda906b2f52bb2006153a91b17568740ac
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"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/profiler/scoped_tracker.h"
13 #include "base/rand_util.h"
14 #include "base/stl_util.h"
15 #include "base/time/time.h"
16 #include "base/timer/timer.h"
17 #include "google_apis/gaia/gaia_urls.h"
18 #include "google_apis/gaia/google_service_auth_error.h"
19 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
20 #include "net/url_request/url_request_context_getter.h"
22 int OAuth2TokenService::max_fetch_retry_num_ = 5;
24 OAuth2TokenService::RequestParameters::RequestParameters(
25 const std::string& client_id,
26 const std::string& account_id,
27 const ScopeSet& scopes)
28 : client_id(client_id),
29 account_id(account_id),
30 scopes(scopes) {
33 OAuth2TokenService::RequestParameters::~RequestParameters() {
36 bool OAuth2TokenService::RequestParameters::operator<(
37 const RequestParameters& p) const {
38 if (client_id < p.client_id)
39 return true;
40 else if (p.client_id < client_id)
41 return false;
43 if (account_id < p.account_id)
44 return true;
45 else if (p.account_id < account_id)
46 return false;
48 return scopes < p.scopes;
51 OAuth2TokenService::RequestImpl::RequestImpl(
52 const std::string& account_id,
53 OAuth2TokenService::Consumer* consumer)
54 : account_id_(account_id),
55 consumer_(consumer) {
58 OAuth2TokenService::RequestImpl::~RequestImpl() {
59 DCHECK(CalledOnValidThread());
62 std::string OAuth2TokenService::RequestImpl::GetAccountId() const {
63 return account_id_;
66 std::string OAuth2TokenService::RequestImpl::GetConsumerId() const {
67 return consumer_->id();
70 void OAuth2TokenService::RequestImpl::InformConsumer(
71 const GoogleServiceAuthError& error,
72 const std::string& access_token,
73 const base::Time& expiration_date) {
74 DCHECK(CalledOnValidThread());
75 if (error.state() == GoogleServiceAuthError::NONE)
76 consumer_->OnGetTokenSuccess(this, access_token, expiration_date);
77 else
78 consumer_->OnGetTokenFailure(this, error);
81 OAuth2TokenService::ScopedBatchChange::ScopedBatchChange(
82 OAuth2TokenService* token_service) : token_service_(token_service) {
83 DCHECK(token_service_);
84 token_service_->StartBatchChanges();
87 OAuth2TokenService::ScopedBatchChange::~ScopedBatchChange() {
88 token_service_->EndBatchChanges();
91 // Class that fetches an OAuth2 access token for a given account id and set of
92 // scopes.
94 // It aims to meet OAuth2TokenService's requirements on token fetching. Retry
95 // mechanism is used to handle failures.
97 // To use this class, call CreateAndStart() to create and start a Fetcher.
99 // The Fetcher will call back the service by calling
100 // OAuth2TokenService::OnFetchComplete() when it completes fetching, if it is
101 // not destructed before it completes fetching; if the Fetcher is destructed
102 // before it completes fetching, the service will never be called back. The
103 // Fetcher destructs itself after calling back the service when finishes
104 // fetching.
106 // Requests that are waiting for the fetching results of this Fetcher can be
107 // added to the Fetcher by calling
108 // OAuth2TokenService::Fetcher::AddWaitingRequest() before the Fetcher
109 // completes fetching.
111 // The waiting requests are taken as weak pointers and they can be deleted.
112 // The waiting requests will be called back with fetching results if they are
113 // not deleted
114 // - when the Fetcher completes fetching, if the Fetcher is not destructed
115 // before it completes fetching, or
116 // - when the Fetcher is destructed if the Fetcher is destructed before it
117 // completes fetching (in this case, the waiting requests will be called
118 // back with error).
119 class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer {
120 public:
121 // Creates a Fetcher and starts fetching an OAuth2 access token for
122 // |account_id| and |scopes| in the request context obtained by |getter|.
123 // The given |oauth2_token_service| will be informed when fetching is done.
124 static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service,
125 const std::string& account_id,
126 net::URLRequestContextGetter* getter,
127 const std::string& client_id,
128 const std::string& client_secret,
129 const ScopeSet& scopes,
130 base::WeakPtr<RequestImpl> waiting_request);
131 ~Fetcher() override;
133 // Add a request that is waiting for the result of this Fetcher.
134 void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request);
136 // Returns count of waiting requests.
137 size_t GetWaitingRequestCount() const;
139 const std::vector<base::WeakPtr<RequestImpl> >& waiting_requests() const {
140 return waiting_requests_;
143 void Cancel();
145 const ScopeSet& GetScopeSet() const;
146 const std::string& GetClientId() const;
147 const std::string& GetAccountId() const;
149 // The error result from this fetcher.
150 const GoogleServiceAuthError& error() const { return error_; }
152 protected:
153 // OAuth2AccessTokenConsumer
154 void OnGetTokenSuccess(const std::string& access_token,
155 const base::Time& expiration_date) override;
156 void OnGetTokenFailure(const GoogleServiceAuthError& error) override;
158 private:
159 Fetcher(OAuth2TokenService* oauth2_token_service,
160 const std::string& account_id,
161 net::URLRequestContextGetter* getter,
162 const std::string& client_id,
163 const std::string& client_secret,
164 const OAuth2TokenService::ScopeSet& scopes,
165 base::WeakPtr<RequestImpl> waiting_request);
166 void Start();
167 void InformWaitingRequests();
168 void InformWaitingRequestsAndDelete();
169 static bool ShouldRetry(const GoogleServiceAuthError& error);
170 int64 ComputeExponentialBackOffMilliseconds(int retry_num);
172 // |oauth2_token_service_| remains valid for the life of this Fetcher, since
173 // this Fetcher is destructed in the dtor of the OAuth2TokenService or is
174 // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess
175 // (whichever comes first).
176 OAuth2TokenService* const oauth2_token_service_;
177 scoped_refptr<net::URLRequestContextGetter> getter_;
178 const std::string account_id_;
179 const ScopeSet scopes_;
180 std::vector<base::WeakPtr<RequestImpl> > waiting_requests_;
182 int retry_number_;
183 base::OneShotTimer<Fetcher> retry_timer_;
184 scoped_ptr<OAuth2AccessTokenFetcher> fetcher_;
186 // Variables that store fetch results.
187 // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle
188 // destruction.
189 GoogleServiceAuthError error_;
190 std::string access_token_;
191 base::Time expiration_date_;
193 // OAuth2 client id and secret.
194 std::string client_id_;
195 std::string client_secret_;
197 DISALLOW_COPY_AND_ASSIGN(Fetcher);
200 // static
201 OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart(
202 OAuth2TokenService* oauth2_token_service,
203 const std::string& account_id,
204 net::URLRequestContextGetter* getter,
205 const std::string& client_id,
206 const std::string& client_secret,
207 const OAuth2TokenService::ScopeSet& scopes,
208 base::WeakPtr<RequestImpl> waiting_request) {
209 OAuth2TokenService::Fetcher* fetcher = new Fetcher(
210 oauth2_token_service,
211 account_id,
212 getter,
213 client_id,
214 client_secret,
215 scopes,
216 waiting_request);
218 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
219 // fixed.
220 tracked_objects::ScopedTracker tracking_profile(
221 FROM_HERE_WITH_EXPLICIT_FUNCTION(
222 "422460 OAuth2TokenService::Fetcher::CreateAndStart"));
224 fetcher->Start();
225 return fetcher;
228 OAuth2TokenService::Fetcher::Fetcher(
229 OAuth2TokenService* oauth2_token_service,
230 const std::string& account_id,
231 net::URLRequestContextGetter* getter,
232 const std::string& client_id,
233 const std::string& client_secret,
234 const OAuth2TokenService::ScopeSet& scopes,
235 base::WeakPtr<RequestImpl> waiting_request)
236 : oauth2_token_service_(oauth2_token_service),
237 getter_(getter),
238 account_id_(account_id),
239 scopes_(scopes),
240 retry_number_(0),
241 error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE),
242 client_id_(client_id),
243 client_secret_(client_secret) {
244 DCHECK(oauth2_token_service_);
245 waiting_requests_.push_back(waiting_request);
248 OAuth2TokenService::Fetcher::~Fetcher() {
249 // Inform the waiting requests if it has not done so.
250 if (waiting_requests_.size())
251 InformWaitingRequests();
254 void OAuth2TokenService::Fetcher::Start() {
255 fetcher_.reset(oauth2_token_service_->CreateAccessTokenFetcher(
256 account_id_, getter_.get(), this));
257 DCHECK(fetcher_);
258 fetcher_->Start(client_id_,
259 client_secret_,
260 std::vector<std::string>(scopes_.begin(), scopes_.end()));
261 retry_timer_.Stop();
264 void OAuth2TokenService::Fetcher::OnGetTokenSuccess(
265 const std::string& access_token,
266 const base::Time& expiration_date) {
267 fetcher_.reset();
269 // Fetch completes.
270 error_ = GoogleServiceAuthError::AuthErrorNone();
271 access_token_ = access_token;
272 expiration_date_ = expiration_date;
274 // Subclasses may override this method to skip caching in some cases, but
275 // we still inform all waiting Consumers of a successful token fetch below.
276 // This is intentional -- some consumers may need the token for cleanup
277 // tasks. https://chromiumcodereview.appspot.com/11312124/
278 oauth2_token_service_->RegisterCacheEntry(client_id_,
279 account_id_,
280 scopes_,
281 access_token_,
282 expiration_date_);
283 InformWaitingRequestsAndDelete();
286 void OAuth2TokenService::Fetcher::OnGetTokenFailure(
287 const GoogleServiceAuthError& error) {
288 fetcher_.reset();
290 if (ShouldRetry(error) && retry_number_ < max_fetch_retry_num_) {
291 base::TimeDelta backoff = base::TimeDelta::FromMilliseconds(
292 ComputeExponentialBackOffMilliseconds(retry_number_));
293 ++retry_number_;
294 retry_timer_.Stop();
295 retry_timer_.Start(FROM_HERE,
296 backoff,
297 this,
298 &OAuth2TokenService::Fetcher::Start);
299 return;
302 error_ = error;
303 InformWaitingRequestsAndDelete();
306 // Returns an exponential backoff in milliseconds including randomness less than
307 // 1000 ms when retrying fetching an OAuth2 access token.
308 int64 OAuth2TokenService::Fetcher::ComputeExponentialBackOffMilliseconds(
309 int retry_num) {
310 DCHECK(retry_num < max_fetch_retry_num_);
311 int64 exponential_backoff_in_seconds = 1 << retry_num;
312 // Returns a backoff with randomness < 1000ms
313 return (exponential_backoff_in_seconds + base::RandDouble()) * 1000;
316 // static
317 bool OAuth2TokenService::Fetcher::ShouldRetry(
318 const GoogleServiceAuthError& error) {
319 GoogleServiceAuthError::State error_state = error.state();
320 return error_state == GoogleServiceAuthError::CONNECTION_FAILED ||
321 error_state == GoogleServiceAuthError::REQUEST_CANCELED ||
322 error_state == GoogleServiceAuthError::SERVICE_UNAVAILABLE;
325 void OAuth2TokenService::Fetcher::InformWaitingRequests() {
326 std::vector<base::WeakPtr<RequestImpl> >::const_iterator iter =
327 waiting_requests_.begin();
328 for (; iter != waiting_requests_.end(); ++iter) {
329 base::WeakPtr<RequestImpl> waiting_request = *iter;
330 if (waiting_request.get())
331 waiting_request->InformConsumer(error_, access_token_, expiration_date_);
333 waiting_requests_.clear();
336 void OAuth2TokenService::Fetcher::InformWaitingRequestsAndDelete() {
337 // Deregisters itself from the service to prevent more waiting requests to
338 // be added when it calls back the waiting requests.
339 oauth2_token_service_->OnFetchComplete(this);
340 InformWaitingRequests();
341 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
344 void OAuth2TokenService::Fetcher::AddWaitingRequest(
345 base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) {
346 waiting_requests_.push_back(waiting_request);
349 size_t OAuth2TokenService::Fetcher::GetWaitingRequestCount() const {
350 return waiting_requests_.size();
353 void OAuth2TokenService::Fetcher::Cancel() {
354 if (fetcher_)
355 fetcher_->CancelRequest();
356 fetcher_.reset();
357 retry_timer_.Stop();
358 error_ = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
359 InformWaitingRequestsAndDelete();
362 const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet()
363 const {
364 return scopes_;
367 const std::string& OAuth2TokenService::Fetcher::GetClientId() const {
368 return client_id_;
371 const std::string& OAuth2TokenService::Fetcher::GetAccountId() const {
372 return account_id_;
375 OAuth2TokenService::Request::Request() {
378 OAuth2TokenService::Request::~Request() {
381 OAuth2TokenService::Consumer::Consumer(const std::string& id)
382 : id_(id) {}
384 OAuth2TokenService::Consumer::~Consumer() {
387 OAuth2TokenService::OAuth2TokenService() : batch_change_depth_(0) {
390 OAuth2TokenService::~OAuth2TokenService() {
391 // Release all the pending fetchers.
392 STLDeleteContainerPairSecondPointers(
393 pending_fetchers_.begin(), pending_fetchers_.end());
396 void OAuth2TokenService::AddObserver(Observer* observer) {
397 observer_list_.AddObserver(observer);
400 void OAuth2TokenService::RemoveObserver(Observer* observer) {
401 observer_list_.RemoveObserver(observer);
404 void OAuth2TokenService::AddDiagnosticsObserver(DiagnosticsObserver* observer) {
405 diagnostics_observer_list_.AddObserver(observer);
408 void OAuth2TokenService::RemoveDiagnosticsObserver(
409 DiagnosticsObserver* observer) {
410 diagnostics_observer_list_.RemoveObserver(observer);
413 std::vector<std::string> OAuth2TokenService::GetAccounts() {
414 return std::vector<std::string>();
417 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest(
418 const std::string& account_id,
419 const OAuth2TokenService::ScopeSet& scopes,
420 OAuth2TokenService::Consumer* consumer) {
421 return StartRequestForClientWithContext(
422 account_id,
423 GetRequestContext(),
424 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
425 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
426 scopes,
427 consumer);
430 scoped_ptr<OAuth2TokenService::Request>
431 OAuth2TokenService::StartRequestForClient(
432 const std::string& account_id,
433 const std::string& client_id,
434 const std::string& client_secret,
435 const OAuth2TokenService::ScopeSet& scopes,
436 OAuth2TokenService::Consumer* consumer) {
437 return StartRequestForClientWithContext(
438 account_id,
439 GetRequestContext(),
440 client_id,
441 client_secret,
442 scopes,
443 consumer);
446 scoped_ptr<OAuth2TokenService::Request>
447 OAuth2TokenService::StartRequestWithContext(
448 const std::string& account_id,
449 net::URLRequestContextGetter* getter,
450 const ScopeSet& scopes,
451 Consumer* consumer) {
452 return StartRequestForClientWithContext(
453 account_id,
454 getter,
455 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
456 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
457 scopes,
458 consumer);
461 scoped_ptr<OAuth2TokenService::Request>
462 OAuth2TokenService::StartRequestForClientWithContext(
463 const std::string& account_id,
464 net::URLRequestContextGetter* getter,
465 const std::string& client_id,
466 const std::string& client_secret,
467 const ScopeSet& scopes,
468 Consumer* consumer) {
469 DCHECK(CalledOnValidThread());
471 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
472 // fixed.
473 tracked_objects::ScopedTracker tracking_profile1(
474 FROM_HERE_WITH_EXPLICIT_FUNCTION(
475 "422460 OAuth2TokenService::StartRequestForClientWithContext 1"));
477 scoped_ptr<RequestImpl> request(new RequestImpl(account_id, consumer));
478 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
479 OnAccessTokenRequested(account_id,
480 consumer->id(),
481 scopes));
483 if (!RefreshTokenIsAvailable(account_id)) {
484 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460
485 // is fixed.
486 tracked_objects::ScopedTracker tracking_profile2(
487 FROM_HERE_WITH_EXPLICIT_FUNCTION(
488 "422460 OAuth2TokenService::StartRequestForClientWithContext 2"));
490 GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
492 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
493 OnFetchAccessTokenComplete(
494 account_id, consumer->id(), scopes, error,
495 base::Time()));
497 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
498 &RequestImpl::InformConsumer,
499 request->AsWeakPtr(),
500 error,
501 std::string(),
502 base::Time()));
503 return request.Pass();
506 RequestParameters request_parameters(client_id,
507 account_id,
508 scopes);
509 if (HasCacheEntry(request_parameters)) {
510 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460
511 // is fixed.
512 tracked_objects::ScopedTracker tracking_profile3(
513 FROM_HERE_WITH_EXPLICIT_FUNCTION(
514 "422460 OAuth2TokenService::StartRequestForClientWithContext 3"));
516 StartCacheLookupRequest(request.get(), request_parameters, consumer);
517 } else {
518 FetchOAuth2Token(request.get(),
519 account_id,
520 getter,
521 client_id,
522 client_secret,
523 scopes);
525 return request.Pass();
528 void OAuth2TokenService::FetchOAuth2Token(RequestImpl* request,
529 const std::string& account_id,
530 net::URLRequestContextGetter* getter,
531 const std::string& client_id,
532 const std::string& client_secret,
533 const ScopeSet& scopes) {
534 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
535 // fixed.
536 tracked_objects::ScopedTracker tracking_profile(
537 FROM_HERE_WITH_EXPLICIT_FUNCTION(
538 "422460 OAuth2TokenService::FetchOAuth2Token"));
540 // If there is already a pending fetcher for |scopes| and |account_id|,
541 // simply register this |request| for those results rather than starting
542 // a new fetcher.
543 RequestParameters request_parameters = RequestParameters(client_id,
544 account_id,
545 scopes);
546 std::map<RequestParameters, Fetcher*>::iterator iter =
547 pending_fetchers_.find(request_parameters);
548 if (iter != pending_fetchers_.end()) {
549 iter->second->AddWaitingRequest(request->AsWeakPtr());
550 return;
553 pending_fetchers_[request_parameters] =
554 Fetcher::CreateAndStart(this,
555 account_id,
556 getter,
557 client_id,
558 client_secret,
559 scopes,
560 request->AsWeakPtr());
563 void OAuth2TokenService::StartCacheLookupRequest(
564 RequestImpl* request,
565 const OAuth2TokenService::RequestParameters& request_parameters,
566 OAuth2TokenService::Consumer* consumer) {
567 CHECK(HasCacheEntry(request_parameters));
568 const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
569 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
570 OnFetchAccessTokenComplete(
571 request_parameters.account_id,
572 consumer->id(),
573 request_parameters.scopes,
574 GoogleServiceAuthError::AuthErrorNone(),
575 cache_entry->expiration_date));
576 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
577 &RequestImpl::InformConsumer,
578 request->AsWeakPtr(),
579 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
580 cache_entry->access_token,
581 cache_entry->expiration_date));
584 void OAuth2TokenService::InvalidateToken(const std::string& account_id,
585 const ScopeSet& scopes,
586 const std::string& access_token) {
587 InvalidateOAuth2Token(account_id,
588 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
589 scopes,
590 access_token);
593 void OAuth2TokenService::InvalidateTokenForClient(
594 const std::string& account_id,
595 const std::string& client_id,
596 const ScopeSet& scopes,
597 const std::string& access_token) {
598 InvalidateOAuth2Token(account_id, client_id, scopes, access_token);
601 void OAuth2TokenService::InvalidateOAuth2Token(
602 const std::string& account_id,
603 const std::string& client_id,
604 const ScopeSet& scopes,
605 const std::string& access_token) {
606 DCHECK(CalledOnValidThread());
607 RemoveCacheEntry(
608 RequestParameters(client_id,
609 account_id,
610 scopes),
611 access_token);
614 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) {
615 DCHECK(CalledOnValidThread());
617 // Update the auth error state so auth errors are appropriately communicated
618 // to the user.
619 UpdateAuthError(fetcher->GetAccountId(), fetcher->error());
621 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh
622 // token and scope set. This is guaranteed as follows; here a Fetcher is said
623 // to be uncompleted if it has not finished calling back
624 // OAuth2TokenService::OnFetchComplete().
626 // (1) All the live Fetchers are created by this service.
627 // This is because (1) all the live Fetchers are created by a live
628 // service, as all the fetchers created by a service are destructed in the
629 // service's dtor.
631 // (2) All the uncompleted Fetchers created by this service are recorded in
632 // |pending_fetchers_|.
633 // This is because (1) all the created Fetchers are added to
634 // |pending_fetchers_| (in method StartRequest()) and (2) method
635 // OnFetchComplete() is the only place where a Fetcher is erased from
636 // |pending_fetchers_|. Note no Fetcher is erased in method
637 // StartRequest().
639 // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its
640 // refresh token and ScopeSet. This is guaranteed by Fetcher creation in
641 // method StartRequest().
643 // When this method is called, |fetcher| is alive and uncompleted.
644 // By (1), |fetcher| is created by this service.
645 // Then by (2), |fetcher| is recorded in |pending_fetchers_|.
646 // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet.
647 RequestParameters request_param(fetcher->GetClientId(),
648 fetcher->GetAccountId(),
649 fetcher->GetScopeSet());
651 const OAuth2TokenService::CacheEntry* entry = GetCacheEntry(request_param);
652 const std::vector<base::WeakPtr<RequestImpl> >& requests =
653 fetcher->waiting_requests();
654 for (size_t i = 0; i < requests.size(); ++i) {
655 const RequestImpl* req = requests[i].get();
656 if (req) {
657 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
658 OnFetchAccessTokenComplete(
659 req->GetAccountId(), req->GetConsumerId(),
660 fetcher->GetScopeSet(), fetcher->error(),
661 entry ? entry->expiration_date : base::Time()));
665 std::map<RequestParameters, Fetcher*>::iterator iter =
666 pending_fetchers_.find(request_param);
667 DCHECK(iter != pending_fetchers_.end());
668 DCHECK_EQ(fetcher, iter->second);
669 pending_fetchers_.erase(iter);
672 bool OAuth2TokenService::HasCacheEntry(
673 const RequestParameters& request_parameters) {
674 const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
675 return cache_entry && cache_entry->access_token.length();
678 const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry(
679 const RequestParameters& request_parameters) {
680 DCHECK(CalledOnValidThread());
681 TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
682 if (token_iterator == token_cache_.end())
683 return NULL;
684 if (token_iterator->second.expiration_date <= base::Time::Now()) {
685 token_cache_.erase(token_iterator);
686 return NULL;
688 return &token_iterator->second;
691 bool OAuth2TokenService::RemoveCacheEntry(
692 const RequestParameters& request_parameters,
693 const std::string& token_to_remove) {
694 DCHECK(CalledOnValidThread());
695 TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
696 if (token_iterator != token_cache_.end() &&
697 token_iterator->second.access_token == token_to_remove) {
698 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
699 OnTokenRemoved(request_parameters.account_id,
700 request_parameters.scopes));
701 token_cache_.erase(token_iterator);
702 return true;
704 return false;
707 void OAuth2TokenService::RegisterCacheEntry(
708 const std::string& client_id,
709 const std::string& account_id,
710 const OAuth2TokenService::ScopeSet& scopes,
711 const std::string& access_token,
712 const base::Time& expiration_date) {
713 DCHECK(CalledOnValidThread());
715 CacheEntry& token = token_cache_[RequestParameters(client_id,
716 account_id,
717 scopes)];
718 token.access_token = access_token;
719 token.expiration_date = expiration_date;
722 void OAuth2TokenService::UpdateAuthError(
723 const std::string& account_id,
724 const GoogleServiceAuthError& error) {
725 // Default implementation does nothing.
728 void OAuth2TokenService::ClearCache() {
729 DCHECK(CalledOnValidThread());
730 for (TokenCache::iterator iter = token_cache_.begin();
731 iter != token_cache_.end(); ++iter) {
732 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
733 OnTokenRemoved(iter->first.account_id,
734 iter->first.scopes));
737 token_cache_.clear();
740 void OAuth2TokenService::ClearCacheForAccount(const std::string& account_id) {
741 DCHECK(CalledOnValidThread());
742 for (TokenCache::iterator iter = token_cache_.begin();
743 iter != token_cache_.end();
744 /* iter incremented in body */) {
745 if (iter->first.account_id == account_id) {
746 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
747 OnTokenRemoved(account_id, iter->first.scopes));
748 token_cache_.erase(iter++);
749 } else {
750 ++iter;
755 void OAuth2TokenService::CancelAllRequests() {
756 std::vector<Fetcher*> fetchers_to_cancel;
757 for (std::map<RequestParameters, Fetcher*>::iterator iter =
758 pending_fetchers_.begin();
759 iter != pending_fetchers_.end();
760 ++iter) {
761 fetchers_to_cancel.push_back(iter->second);
763 CancelFetchers(fetchers_to_cancel);
766 void OAuth2TokenService::CancelRequestsForAccount(
767 const std::string& account_id) {
768 std::vector<Fetcher*> fetchers_to_cancel;
769 for (std::map<RequestParameters, Fetcher*>::iterator iter =
770 pending_fetchers_.begin();
771 iter != pending_fetchers_.end();
772 ++iter) {
773 if (iter->first.account_id == account_id)
774 fetchers_to_cancel.push_back(iter->second);
776 CancelFetchers(fetchers_to_cancel);
779 void OAuth2TokenService::CancelFetchers(
780 std::vector<Fetcher*> fetchers_to_cancel) {
781 for (std::vector<OAuth2TokenService::Fetcher*>::iterator iter =
782 fetchers_to_cancel.begin();
783 iter != fetchers_to_cancel.end();
784 ++iter) {
785 (*iter)->Cancel();
789 void OAuth2TokenService::FireRefreshTokenAvailable(
790 const std::string& account_id) {
791 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
792 // fixed.
793 tracked_objects::ScopedTracker tracking_profile(
794 FROM_HERE_WITH_EXPLICIT_FUNCTION(
795 "422460 OAuth2TokenService::FireRefreshTokenAvailable"));
797 FOR_EACH_OBSERVER(Observer, observer_list_,
798 OnRefreshTokenAvailable(account_id));
801 void OAuth2TokenService::FireRefreshTokenRevoked(
802 const std::string& account_id) {
803 FOR_EACH_OBSERVER(Observer, observer_list_,
804 OnRefreshTokenRevoked(account_id));
807 void OAuth2TokenService::FireRefreshTokensLoaded() {
808 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
809 // fixed.
810 tracked_objects::ScopedTracker tracking_profile(
811 FROM_HERE_WITH_EXPLICIT_FUNCTION(
812 "422460 OAuth2TokenService::FireRefreshTokensLoaded"));
814 FOR_EACH_OBSERVER(Observer, observer_list_, OnRefreshTokensLoaded());
817 void OAuth2TokenService::StartBatchChanges() {
818 ++batch_change_depth_;
819 if (batch_change_depth_ == 1)
820 FOR_EACH_OBSERVER(Observer, observer_list_, OnStartBatchChanges());
823 void OAuth2TokenService::EndBatchChanges() {
824 --batch_change_depth_;
825 DCHECK_LE(0, batch_change_depth_);
826 if (batch_change_depth_ == 0)
827 FOR_EACH_OBSERVER(Observer, observer_list_, OnEndBatchChanges());
830 int OAuth2TokenService::cache_size_for_testing() const {
831 return token_cache_.size();
834 void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing(
835 int max_retries) {
836 DCHECK(CalledOnValidThread());
837 max_fetch_retry_num_ = max_retries;
840 size_t OAuth2TokenService::GetNumPendingRequestsForTesting(
841 const std::string& client_id,
842 const std::string& account_id,
843 const ScopeSet& scopes) const {
844 PendingFetcherMap::const_iterator iter = pending_fetchers_.find(
845 OAuth2TokenService::RequestParameters(
846 client_id,
847 account_id,
848 scopes));
849 return iter == pending_fetchers_.end() ?
850 0 : iter->second->GetWaitingRequestCount();