service_resolver_64: Correctly check all the bytes of the service code.
[chromium-blink-merge.git] / google_apis / gaia / oauth2_token_service.cc
blobf2a163dee869effc43b91276187b131f72338af9
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/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),
31 scopes(scopes) {
34 OAuth2TokenService::RequestParameters::~RequestParameters() {
37 bool OAuth2TokenService::RequestParameters::operator<(
38 const RequestParameters& p) const {
39 if (client_id < p.client_id)
40 return true;
41 else if (p.client_id < client_id)
42 return false;
44 if (account_id < p.account_id)
45 return true;
46 else if (p.account_id < account_id)
47 return false;
49 return scopes < p.scopes;
52 OAuth2TokenService::RequestImpl::RequestImpl(
53 const std::string& account_id,
54 OAuth2TokenService::Consumer* consumer)
55 : account_id_(account_id),
56 consumer_(consumer) {
59 OAuth2TokenService::RequestImpl::~RequestImpl() {
60 DCHECK(CalledOnValidThread());
63 std::string OAuth2TokenService::RequestImpl::GetAccountId() const {
64 return account_id_;
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);
78 else
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
93 // scopes.
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 destroyed before it completes fetching; if the Fetcher is destroyed
103 // before it completes fetching, the service will never be called back. The
104 // Fetcher destroys itself after calling back the service when it finishes
105 // fetching.
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 // They will be called back with the result when either the Fetcher completes
114 // fetching or is destroyed, whichever comes first. In the latter case, the
115 // waiting requests will be called back with an error.
117 // The OAuth2TokenService and the waiting requests will never be called back on
118 // the same turn of the message loop as when the fetcher is started, even if an
119 // immediate error occurred.
120 class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer {
121 public:
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);
132 ~Fetcher() override;
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_;
144 void Cancel();
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_; }
153 protected:
154 // OAuth2AccessTokenConsumer
155 void OnGetTokenSuccess(const std::string& access_token,
156 const base::Time& expiration_date) override;
157 void OnGetTokenFailure(const GoogleServiceAuthError& error) override;
159 private:
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);
167 void Start();
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_;
183 int retry_number_;
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
189 // destruction.
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);
201 // static
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,
212 account_id,
213 getter,
214 client_id,
215 client_secret,
216 scopes,
217 waiting_request);
219 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
220 // fixed.
221 tracked_objects::ScopedTracker tracking_profile(
222 FROM_HERE_WITH_EXPLICIT_FUNCTION(
223 "422460 OAuth2TokenService::Fetcher::CreateAndStart"));
225 fetcher->Start();
226 return fetcher;
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),
238 getter_(getter),
239 account_id_(account_id),
240 scopes_(scopes),
241 retry_number_(0),
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));
258 DCHECK(fetcher_);
260 // Stop the timer before starting the fetch, as defense in depth against the
261 // fetcher calling us back synchronously (which might restart the timer).
262 retry_timer_.Stop();
263 fetcher_->Start(client_id_,
264 client_secret_,
265 std::vector<std::string>(scopes_.begin(), scopes_.end()));
268 void OAuth2TokenService::Fetcher::OnGetTokenSuccess(
269 const std::string& access_token,
270 const base::Time& expiration_date) {
271 fetcher_.reset();
273 // Fetch completes.
274 error_ = GoogleServiceAuthError::AuthErrorNone();
275 access_token_ = access_token;
276 expiration_date_ = expiration_date;
278 // Subclasses may override this method to skip caching in some cases, but
279 // we still inform all waiting Consumers of a successful token fetch below.
280 // This is intentional -- some consumers may need the token for cleanup
281 // tasks. https://chromiumcodereview.appspot.com/11312124/
282 oauth2_token_service_->RegisterCacheEntry(client_id_,
283 account_id_,
284 scopes_,
285 access_token_,
286 expiration_date_);
287 InformWaitingRequestsAndDelete();
290 void OAuth2TokenService::Fetcher::OnGetTokenFailure(
291 const GoogleServiceAuthError& error) {
292 fetcher_.reset();
294 if (ShouldRetry(error) && retry_number_ < max_fetch_retry_num_) {
295 base::TimeDelta backoff = base::TimeDelta::FromMilliseconds(
296 ComputeExponentialBackOffMilliseconds(retry_number_));
297 ++retry_number_;
298 UMA_HISTOGRAM_ENUMERATION("Signin.OAuth2TokenGetRetry",
299 error.state(), GoogleServiceAuthError::NUM_STATES);
300 retry_timer_.Stop();
301 retry_timer_.Start(FROM_HERE,
302 backoff,
303 this,
304 &OAuth2TokenService::Fetcher::Start);
305 return;
308 UMA_HISTOGRAM_ENUMERATION("Signin.OAuth2TokenGetFailure",
309 error.state(), GoogleServiceAuthError::NUM_STATES);
310 error_ = error;
311 InformWaitingRequestsAndDelete();
314 // Returns an exponential backoff in milliseconds including randomness less than
315 // 1000 ms when retrying fetching an OAuth2 access token.
316 int64 OAuth2TokenService::Fetcher::ComputeExponentialBackOffMilliseconds(
317 int retry_num) {
318 DCHECK(retry_num < max_fetch_retry_num_);
319 int64 exponential_backoff_in_seconds = 1 << retry_num;
320 // Returns a backoff with randomness < 1000ms
321 return (exponential_backoff_in_seconds + base::RandDouble()) * 1000;
324 // static
325 bool OAuth2TokenService::Fetcher::ShouldRetry(
326 const GoogleServiceAuthError& error) {
327 GoogleServiceAuthError::State error_state = error.state();
328 return error_state == GoogleServiceAuthError::CONNECTION_FAILED ||
329 error_state == GoogleServiceAuthError::REQUEST_CANCELED ||
330 error_state == GoogleServiceAuthError::SERVICE_UNAVAILABLE;
333 void OAuth2TokenService::Fetcher::InformWaitingRequests() {
334 std::vector<base::WeakPtr<RequestImpl> >::const_iterator iter =
335 waiting_requests_.begin();
336 for (; iter != waiting_requests_.end(); ++iter) {
337 base::WeakPtr<RequestImpl> waiting_request = *iter;
338 if (waiting_request.get())
339 waiting_request->InformConsumer(error_, access_token_, expiration_date_);
341 waiting_requests_.clear();
344 void OAuth2TokenService::Fetcher::InformWaitingRequestsAndDelete() {
345 // Deregisters itself from the service to prevent more waiting requests to
346 // be added when it calls back the waiting requests.
347 oauth2_token_service_->OnFetchComplete(this);
348 InformWaitingRequests();
349 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
352 void OAuth2TokenService::Fetcher::AddWaitingRequest(
353 base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) {
354 waiting_requests_.push_back(waiting_request);
357 size_t OAuth2TokenService::Fetcher::GetWaitingRequestCount() const {
358 return waiting_requests_.size();
361 void OAuth2TokenService::Fetcher::Cancel() {
362 if (fetcher_)
363 fetcher_->CancelRequest();
364 fetcher_.reset();
365 retry_timer_.Stop();
366 error_ = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
367 InformWaitingRequestsAndDelete();
370 const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet()
371 const {
372 return scopes_;
375 const std::string& OAuth2TokenService::Fetcher::GetClientId() const {
376 return client_id_;
379 const std::string& OAuth2TokenService::Fetcher::GetAccountId() const {
380 return account_id_;
383 OAuth2TokenService::Request::Request() {
386 OAuth2TokenService::Request::~Request() {
389 OAuth2TokenService::Consumer::Consumer(const std::string& id)
390 : id_(id) {}
392 OAuth2TokenService::Consumer::~Consumer() {
395 OAuth2TokenService::OAuth2TokenService() : batch_change_depth_(0) {
398 OAuth2TokenService::~OAuth2TokenService() {
399 // Release all the pending fetchers.
400 STLDeleteContainerPairSecondPointers(
401 pending_fetchers_.begin(), pending_fetchers_.end());
404 void OAuth2TokenService::AddObserver(Observer* observer) {
405 observer_list_.AddObserver(observer);
408 void OAuth2TokenService::RemoveObserver(Observer* observer) {
409 observer_list_.RemoveObserver(observer);
412 void OAuth2TokenService::AddDiagnosticsObserver(DiagnosticsObserver* observer) {
413 diagnostics_observer_list_.AddObserver(observer);
416 void OAuth2TokenService::RemoveDiagnosticsObserver(
417 DiagnosticsObserver* observer) {
418 diagnostics_observer_list_.RemoveObserver(observer);
421 std::vector<std::string> OAuth2TokenService::GetAccounts() {
422 return std::vector<std::string>();
425 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest(
426 const std::string& account_id,
427 const OAuth2TokenService::ScopeSet& scopes,
428 OAuth2TokenService::Consumer* consumer) {
429 return StartRequestForClientWithContext(
430 account_id,
431 GetRequestContext(),
432 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
433 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
434 scopes,
435 consumer);
438 scoped_ptr<OAuth2TokenService::Request>
439 OAuth2TokenService::StartRequestForClient(
440 const std::string& account_id,
441 const std::string& client_id,
442 const std::string& client_secret,
443 const OAuth2TokenService::ScopeSet& scopes,
444 OAuth2TokenService::Consumer* consumer) {
445 return StartRequestForClientWithContext(
446 account_id,
447 GetRequestContext(),
448 client_id,
449 client_secret,
450 scopes,
451 consumer);
454 scoped_ptr<OAuth2TokenService::Request>
455 OAuth2TokenService::StartRequestWithContext(
456 const std::string& account_id,
457 net::URLRequestContextGetter* getter,
458 const ScopeSet& scopes,
459 Consumer* consumer) {
460 return StartRequestForClientWithContext(
461 account_id,
462 getter,
463 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
464 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
465 scopes,
466 consumer);
469 scoped_ptr<OAuth2TokenService::Request>
470 OAuth2TokenService::StartRequestForClientWithContext(
471 const std::string& account_id,
472 net::URLRequestContextGetter* getter,
473 const std::string& client_id,
474 const std::string& client_secret,
475 const ScopeSet& scopes,
476 Consumer* consumer) {
477 DCHECK(CalledOnValidThread());
479 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
480 // fixed.
481 tracked_objects::ScopedTracker tracking_profile1(
482 FROM_HERE_WITH_EXPLICIT_FUNCTION(
483 "422460 OAuth2TokenService::StartRequestForClientWithContext 1"));
485 scoped_ptr<RequestImpl> request(new RequestImpl(account_id, consumer));
486 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
487 OnAccessTokenRequested(account_id,
488 consumer->id(),
489 scopes));
491 if (!RefreshTokenIsAvailable(account_id)) {
492 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460
493 // is fixed.
494 tracked_objects::ScopedTracker tracking_profile2(
495 FROM_HERE_WITH_EXPLICIT_FUNCTION(
496 "422460 OAuth2TokenService::StartRequestForClientWithContext 2"));
498 GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP);
500 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
501 OnFetchAccessTokenComplete(
502 account_id, consumer->id(), scopes, error,
503 base::Time()));
505 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
506 &RequestImpl::InformConsumer,
507 request->AsWeakPtr(),
508 error,
509 std::string(),
510 base::Time()));
511 return request.Pass();
514 RequestParameters request_parameters(client_id,
515 account_id,
516 scopes);
517 if (HasCacheEntry(request_parameters)) {
518 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460
519 // is fixed.
520 tracked_objects::ScopedTracker tracking_profile3(
521 FROM_HERE_WITH_EXPLICIT_FUNCTION(
522 "422460 OAuth2TokenService::StartRequestForClientWithContext 3"));
524 StartCacheLookupRequest(request.get(), request_parameters, consumer);
525 } else {
526 FetchOAuth2Token(request.get(),
527 account_id,
528 getter,
529 client_id,
530 client_secret,
531 scopes);
533 return request.Pass();
536 void OAuth2TokenService::FetchOAuth2Token(RequestImpl* request,
537 const std::string& account_id,
538 net::URLRequestContextGetter* getter,
539 const std::string& client_id,
540 const std::string& client_secret,
541 const ScopeSet& scopes) {
542 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
543 // fixed.
544 tracked_objects::ScopedTracker tracking_profile(
545 FROM_HERE_WITH_EXPLICIT_FUNCTION(
546 "422460 OAuth2TokenService::FetchOAuth2Token"));
548 // If there is already a pending fetcher for |scopes| and |account_id|,
549 // simply register this |request| for those results rather than starting
550 // a new fetcher.
551 RequestParameters request_parameters = RequestParameters(client_id,
552 account_id,
553 scopes);
554 std::map<RequestParameters, Fetcher*>::iterator iter =
555 pending_fetchers_.find(request_parameters);
556 if (iter != pending_fetchers_.end()) {
557 iter->second->AddWaitingRequest(request->AsWeakPtr());
558 return;
561 pending_fetchers_[request_parameters] =
562 Fetcher::CreateAndStart(this,
563 account_id,
564 getter,
565 client_id,
566 client_secret,
567 scopes,
568 request->AsWeakPtr());
571 void OAuth2TokenService::StartCacheLookupRequest(
572 RequestImpl* request,
573 const OAuth2TokenService::RequestParameters& request_parameters,
574 OAuth2TokenService::Consumer* consumer) {
575 CHECK(HasCacheEntry(request_parameters));
576 const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
577 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
578 OnFetchAccessTokenComplete(
579 request_parameters.account_id,
580 consumer->id(),
581 request_parameters.scopes,
582 GoogleServiceAuthError::AuthErrorNone(),
583 cache_entry->expiration_date));
584 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
585 &RequestImpl::InformConsumer,
586 request->AsWeakPtr(),
587 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
588 cache_entry->access_token,
589 cache_entry->expiration_date));
592 void OAuth2TokenService::InvalidateToken(const std::string& account_id,
593 const ScopeSet& scopes,
594 const std::string& access_token) {
595 InvalidateOAuth2Token(account_id,
596 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
597 scopes,
598 access_token);
601 void OAuth2TokenService::InvalidateTokenForClient(
602 const std::string& account_id,
603 const std::string& client_id,
604 const ScopeSet& scopes,
605 const std::string& access_token) {
606 InvalidateOAuth2Token(account_id, client_id, scopes, access_token);
609 void OAuth2TokenService::InvalidateOAuth2Token(
610 const std::string& account_id,
611 const std::string& client_id,
612 const ScopeSet& scopes,
613 const std::string& access_token) {
614 DCHECK(CalledOnValidThread());
615 RemoveCacheEntry(
616 RequestParameters(client_id,
617 account_id,
618 scopes),
619 access_token);
622 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) {
623 DCHECK(CalledOnValidThread());
625 // Update the auth error state so auth errors are appropriately communicated
626 // to the user.
627 UpdateAuthError(fetcher->GetAccountId(), fetcher->error());
629 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh
630 // token and scope set. This is guaranteed as follows; here a Fetcher is said
631 // to be uncompleted if it has not finished calling back
632 // OAuth2TokenService::OnFetchComplete().
634 // (1) All the live Fetchers are created by this service.
635 // This is because (1) all the live Fetchers are created by a live
636 // service, as all the fetchers created by a service are destructed in the
637 // service's dtor.
639 // (2) All the uncompleted Fetchers created by this service are recorded in
640 // |pending_fetchers_|.
641 // This is because (1) all the created Fetchers are added to
642 // |pending_fetchers_| (in method StartRequest()) and (2) method
643 // OnFetchComplete() is the only place where a Fetcher is erased from
644 // |pending_fetchers_|. Note no Fetcher is erased in method
645 // StartRequest().
647 // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its
648 // refresh token and ScopeSet. This is guaranteed by Fetcher creation in
649 // method StartRequest().
651 // When this method is called, |fetcher| is alive and uncompleted.
652 // By (1), |fetcher| is created by this service.
653 // Then by (2), |fetcher| is recorded in |pending_fetchers_|.
654 // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet.
655 RequestParameters request_param(fetcher->GetClientId(),
656 fetcher->GetAccountId(),
657 fetcher->GetScopeSet());
659 const OAuth2TokenService::CacheEntry* entry = GetCacheEntry(request_param);
660 const std::vector<base::WeakPtr<RequestImpl> >& requests =
661 fetcher->waiting_requests();
662 for (size_t i = 0; i < requests.size(); ++i) {
663 const RequestImpl* req = requests[i].get();
664 if (req) {
665 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
666 OnFetchAccessTokenComplete(
667 req->GetAccountId(), req->GetConsumerId(),
668 fetcher->GetScopeSet(), fetcher->error(),
669 entry ? entry->expiration_date : base::Time()));
673 std::map<RequestParameters, Fetcher*>::iterator iter =
674 pending_fetchers_.find(request_param);
675 DCHECK(iter != pending_fetchers_.end());
676 DCHECK_EQ(fetcher, iter->second);
677 pending_fetchers_.erase(iter);
680 bool OAuth2TokenService::HasCacheEntry(
681 const RequestParameters& request_parameters) {
682 const CacheEntry* cache_entry = GetCacheEntry(request_parameters);
683 return cache_entry && cache_entry->access_token.length();
686 const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry(
687 const RequestParameters& request_parameters) {
688 DCHECK(CalledOnValidThread());
689 TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
690 if (token_iterator == token_cache_.end())
691 return NULL;
692 if (token_iterator->second.expiration_date <= base::Time::Now()) {
693 token_cache_.erase(token_iterator);
694 return NULL;
696 return &token_iterator->second;
699 bool OAuth2TokenService::RemoveCacheEntry(
700 const RequestParameters& request_parameters,
701 const std::string& token_to_remove) {
702 DCHECK(CalledOnValidThread());
703 TokenCache::iterator token_iterator = token_cache_.find(request_parameters);
704 if (token_iterator != token_cache_.end() &&
705 token_iterator->second.access_token == token_to_remove) {
706 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
707 OnTokenRemoved(request_parameters.account_id,
708 request_parameters.scopes));
709 token_cache_.erase(token_iterator);
710 return true;
712 return false;
715 void OAuth2TokenService::RegisterCacheEntry(
716 const std::string& client_id,
717 const std::string& account_id,
718 const OAuth2TokenService::ScopeSet& scopes,
719 const std::string& access_token,
720 const base::Time& expiration_date) {
721 DCHECK(CalledOnValidThread());
723 CacheEntry& token = token_cache_[RequestParameters(client_id,
724 account_id,
725 scopes)];
726 token.access_token = access_token;
727 token.expiration_date = expiration_date;
730 void OAuth2TokenService::UpdateAuthError(
731 const std::string& account_id,
732 const GoogleServiceAuthError& error) {
733 // Default implementation does nothing.
736 void OAuth2TokenService::ClearCache() {
737 DCHECK(CalledOnValidThread());
738 for (TokenCache::iterator iter = token_cache_.begin();
739 iter != token_cache_.end(); ++iter) {
740 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
741 OnTokenRemoved(iter->first.account_id,
742 iter->first.scopes));
745 token_cache_.clear();
748 void OAuth2TokenService::ClearCacheForAccount(const std::string& account_id) {
749 DCHECK(CalledOnValidThread());
750 for (TokenCache::iterator iter = token_cache_.begin();
751 iter != token_cache_.end();
752 /* iter incremented in body */) {
753 if (iter->first.account_id == account_id) {
754 FOR_EACH_OBSERVER(DiagnosticsObserver, diagnostics_observer_list_,
755 OnTokenRemoved(account_id, iter->first.scopes));
756 token_cache_.erase(iter++);
757 } else {
758 ++iter;
763 void OAuth2TokenService::CancelAllRequests() {
764 std::vector<Fetcher*> fetchers_to_cancel;
765 for (std::map<RequestParameters, Fetcher*>::iterator iter =
766 pending_fetchers_.begin();
767 iter != pending_fetchers_.end();
768 ++iter) {
769 fetchers_to_cancel.push_back(iter->second);
771 CancelFetchers(fetchers_to_cancel);
774 void OAuth2TokenService::CancelRequestsForAccount(
775 const std::string& account_id) {
776 std::vector<Fetcher*> fetchers_to_cancel;
777 for (std::map<RequestParameters, Fetcher*>::iterator iter =
778 pending_fetchers_.begin();
779 iter != pending_fetchers_.end();
780 ++iter) {
781 if (iter->first.account_id == account_id)
782 fetchers_to_cancel.push_back(iter->second);
784 CancelFetchers(fetchers_to_cancel);
787 void OAuth2TokenService::CancelFetchers(
788 std::vector<Fetcher*> fetchers_to_cancel) {
789 for (std::vector<OAuth2TokenService::Fetcher*>::iterator iter =
790 fetchers_to_cancel.begin();
791 iter != fetchers_to_cancel.end();
792 ++iter) {
793 (*iter)->Cancel();
797 void OAuth2TokenService::FireRefreshTokenAvailable(
798 const std::string& account_id) {
799 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
800 // fixed.
801 tracked_objects::ScopedTracker tracking_profile(
802 FROM_HERE_WITH_EXPLICIT_FUNCTION(
803 "422460 OAuth2TokenService::FireRefreshTokenAvailable"));
805 FOR_EACH_OBSERVER(Observer, observer_list_,
806 OnRefreshTokenAvailable(account_id));
809 void OAuth2TokenService::FireRefreshTokenRevoked(
810 const std::string& account_id) {
811 FOR_EACH_OBSERVER(Observer, observer_list_,
812 OnRefreshTokenRevoked(account_id));
815 void OAuth2TokenService::FireRefreshTokensLoaded() {
816 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
817 // fixed.
818 tracked_objects::ScopedTracker tracking_profile(
819 FROM_HERE_WITH_EXPLICIT_FUNCTION(
820 "422460 OAuth2TokenService::FireRefreshTokensLoaded"));
822 FOR_EACH_OBSERVER(Observer, observer_list_, OnRefreshTokensLoaded());
825 void OAuth2TokenService::StartBatchChanges() {
826 ++batch_change_depth_;
827 if (batch_change_depth_ == 1)
828 FOR_EACH_OBSERVER(Observer, observer_list_, OnStartBatchChanges());
831 void OAuth2TokenService::EndBatchChanges() {
832 --batch_change_depth_;
833 DCHECK_LE(0, batch_change_depth_);
834 if (batch_change_depth_ == 0)
835 FOR_EACH_OBSERVER(Observer, observer_list_, OnEndBatchChanges());
838 int OAuth2TokenService::cache_size_for_testing() const {
839 return token_cache_.size();
842 void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing(
843 int max_retries) {
844 DCHECK(CalledOnValidThread());
845 max_fetch_retry_num_ = max_retries;
848 size_t OAuth2TokenService::GetNumPendingRequestsForTesting(
849 const std::string& client_id,
850 const std::string& account_id,
851 const ScopeSet& scopes) const {
852 PendingFetcherMap::const_iterator iter = pending_fetchers_.find(
853 OAuth2TokenService::RequestParameters(
854 client_id,
855 account_id,
856 scopes));
857 return iter == pending_fetchers_.end() ?
858 0 : iter->second->GetWaitingRequestCount();