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