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