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