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