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