| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/signin/oauth2_token_service.h" | 5 #include "chrome/browser/signin/oauth2_token_service.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/weak_ptr.h" | 10 #include "base/memory/weak_ptr.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "chrome/common/chrome_notification_types.h" | 22 #include "chrome/common/chrome_notification_types.h" |
| 23 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/notification_details.h" | 24 #include "content/public/browser/notification_details.h" |
| 25 #include "content/public/browser/notification_source.h" | 25 #include "content/public/browser/notification_source.h" |
| 26 #include "google_apis/gaia/gaia_constants.h" | 26 #include "google_apis/gaia/gaia_constants.h" |
| 27 #include "google_apis/gaia/gaia_urls.h" | 27 #include "google_apis/gaia/gaia_urls.h" |
| 28 #include "google_apis/gaia/google_service_auth_error.h" | 28 #include "google_apis/gaia/google_service_auth_error.h" |
| 29 #include "google_apis/gaia/oauth2_access_token_consumer.h" | 29 #include "google_apis/gaia/oauth2_access_token_consumer.h" |
| 30 #include "google_apis/gaia/oauth2_access_token_fetcher.h" | 30 #include "google_apis/gaia/oauth2_access_token_fetcher.h" |
| 31 | 31 |
| 32 #if defined(OS_ANDROID) | |
| 33 #include "chrome/browser/sync/profile_sync_service_android.h" | |
| 34 #endif | |
| 35 | |
| 36 namespace { | 32 namespace { |
| 37 | 33 |
| 38 // Maximum number of retries in fetching an OAuth2 access token. | 34 // Maximum number of retries in fetching an OAuth2 access token. |
| 39 const int kMaxFetchRetryNum = 5; | 35 const int kMaxFetchRetryNum = 5; |
| 40 | 36 |
| 41 // Returns an exponential backoff in milliseconds including randomness less than | 37 // Returns an exponential backoff in milliseconds including randomness less than |
| 42 // 1000 ms when retrying fetching an OAuth2 access token. | 38 // 1000 ms when retrying fetching an OAuth2 access token. |
| 43 int64 ComputeExponentialBackOffMilliseconds(int retry_num) { | 39 int64 ComputeExponentialBackOffMilliseconds(int retry_num) { |
| 44 DCHECK(retry_num < kMaxFetchRetryNum); | 40 DCHECK(retry_num < kMaxFetchRetryNum); |
| 45 int64 exponential_backoff_in_seconds = 1 << retry_num; | 41 int64 exponential_backoff_in_seconds = 1 << retry_num; |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 if (profile_) { | 355 if (profile_) { |
| 360 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> | 356 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> |
| 361 RemoveProvider(this); | 357 RemoveProvider(this); |
| 362 } | 358 } |
| 363 } | 359 } |
| 364 | 360 |
| 365 | 361 |
| 366 // static | 362 // static |
| 367 void OAuth2TokenService::InformConsumer( | 363 void OAuth2TokenService::InformConsumer( |
| 368 base::WeakPtr<OAuth2TokenService::RequestImpl> request, | 364 base::WeakPtr<OAuth2TokenService::RequestImpl> request, |
| 369 const GoogleServiceAuthError& error, | 365 GoogleServiceAuthError error, |
| 370 const std::string& access_token, | 366 std::string access_token, |
| 371 const base::Time& expiration_date) { | 367 base::Time expiration_date) { |
| 372 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 368 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 373 | 369 |
| 374 if (request) | 370 if (request) |
| 375 request->InformConsumer(error, access_token, expiration_date); | 371 request->InformConsumer(error, access_token, expiration_date); |
| 376 } | 372 } |
| 377 | 373 |
| 378 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( | 374 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( |
| 379 const OAuth2TokenService::ScopeSet& scopes, | 375 const OAuth2TokenService::ScopeSet& scopes, |
| 380 OAuth2TokenService::Consumer* consumer) { | 376 OAuth2TokenService::Consumer* consumer) { |
| 381 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 377 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 382 | 378 |
| 383 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); | 379 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); |
| 384 | 380 |
| 385 #if !defined(OS_ANDROID) | |
| 386 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 381 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
| 387 if (!token_service || !token_service->HasOAuthLoginToken()) { | 382 if (!token_service || !token_service->HasOAuthLoginToken()) { |
| 388 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 383 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
| 389 &OAuth2TokenService::InformConsumer, | 384 &OAuth2TokenService::InformConsumer, |
| 390 request->AsWeakPtr(), | 385 request->AsWeakPtr(), |
| 391 GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP), | 386 GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP), |
| 392 std::string(), | 387 std::string(), |
| 393 base::Time())); | 388 base::Time())); |
| 394 return request.PassAs<Request>(); | 389 return request.PassAs<Request>(); |
| 395 } | 390 } |
| 396 #endif | |
| 397 | 391 |
| 398 const CacheEntry* cache_entry = GetCacheEntry(scopes); | 392 const CacheEntry* cache_entry = GetCacheEntry(scopes); |
| 399 if (cache_entry && cache_entry->access_token.length()) { | 393 if (cache_entry && cache_entry->access_token.length()) { |
| 400 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 394 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
| 401 &OAuth2TokenService::InformConsumer, | 395 &OAuth2TokenService::InformConsumer, |
| 402 request->AsWeakPtr(), | 396 request->AsWeakPtr(), |
| 403 GoogleServiceAuthError(GoogleServiceAuthError::NONE), | 397 GoogleServiceAuthError(GoogleServiceAuthError::NONE), |
| 404 cache_entry->access_token, | 398 cache_entry->access_token, |
| 405 cache_entry->expiration_date)); | 399 cache_entry->expiration_date)); |
| 406 return request.PassAs<Request>(); | 400 return request.PassAs<Request>(); |
| 407 } | 401 } |
| 408 | 402 |
| 409 #if defined(OS_ANDROID) | |
| 410 DCHECK_EQ(scopes.size(), 1U); | |
| 411 std::vector<std::string> scope_list(scopes.begin(), scopes.end()); | |
| 412 ProfileSyncServiceAndroid* sync_service = | |
| 413 ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid(); | |
| 414 sync_service->FetchOAuth2Token( | |
| 415 scope_list.front(), | |
| 416 base::Bind(&OAuth2TokenService::InformConsumer, | |
| 417 request->AsWeakPtr())); | |
| 418 return request.PassAs<Request>(); | |
| 419 #else | |
| 420 std::string refresh_token = token_service->GetOAuth2LoginRefreshToken(); | 403 std::string refresh_token = token_service->GetOAuth2LoginRefreshToken(); |
| 421 if (!refresh_token.length()) { | 404 if (!refresh_token.length()) { |
| 422 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 405 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
| 423 &OAuth2TokenService::InformConsumer, | 406 &OAuth2TokenService::InformConsumer, |
| 424 request->AsWeakPtr(), | 407 request->AsWeakPtr(), |
| 425 GoogleServiceAuthError( | 408 GoogleServiceAuthError( |
| 426 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), | 409 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), |
| 427 std::string(), | 410 std::string(), |
| 428 base::Time())); | 411 base::Time())); |
| 429 return request.PassAs<Request>(); | 412 return request.PassAs<Request>(); |
| 430 } | 413 } |
| 431 | 414 |
| 432 // Makes sure there is a pending fetcher for |scopes| and |refresh_token|. | 415 // Makes sure there is a pending fetcher for |scopes| and |refresh_token|. |
| 433 // Adds |request| to the waiting request list of this fetcher so |request| | 416 // Adds |request| to the waiting request list of this fetcher so |request| |
| 434 // will be called back when this fetcher finishes fetching. | 417 // will be called back when this fetcher finishes fetching. |
| 435 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); | 418 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); |
| 436 std::map<FetchParameters, Fetcher*>::iterator iter = | 419 std::map<FetchParameters, Fetcher*>::iterator iter = |
| 437 pending_fetchers_.find(fetch_parameters); | 420 pending_fetchers_.find(fetch_parameters); |
| 438 if (iter != pending_fetchers_.end()) { | 421 if (iter != pending_fetchers_.end()) { |
| 439 iter->second->AddWaitingRequest(request->AsWeakPtr()); | 422 iter->second->AddWaitingRequest(request->AsWeakPtr()); |
| 440 return request.PassAs<Request>(); | 423 return request.PassAs<Request>(); |
| 441 } | 424 } |
| 442 pending_fetchers_[fetch_parameters] = Fetcher::CreateAndStart( | 425 pending_fetchers_[fetch_parameters] = Fetcher::CreateAndStart( |
| 443 profile_, getter_, refresh_token, scopes, request->AsWeakPtr()); | 426 profile_, getter_, refresh_token, scopes, request->AsWeakPtr()); |
| 444 return request.PassAs<Request>(); | 427 return request.PassAs<Request>(); |
| 445 #endif // defined(OS_ANDROID) | |
| 446 } | |
| 447 | |
| 448 void OAuth2TokenService::InvalidateToken(const ScopeSet& scopes, | |
| 449 const std::string& invalid_token) { | |
| 450 RemoveCacheEntry(scopes, invalid_token); | |
| 451 | |
| 452 #if defined(OS_ANDROID) | |
| 453 DCHECK_EQ(scopes.size(), 1U); | |
| 454 std::vector<std::string> scope_list(scopes.begin(), scopes.end()); | |
| 455 ProfileSyncServiceAndroid* sync_service = | |
| 456 ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid(); | |
| 457 sync_service->InvalidateOAuth2Token( | |
| 458 scope_list.front(), | |
| 459 invalid_token); | |
| 460 #endif | |
| 461 } | 428 } |
| 462 | 429 |
| 463 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { | 430 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { |
| 464 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 431 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 465 | 432 |
| 466 // Update the auth error state so auth errors are appropriately communicated | 433 // Update the auth error state so auth errors are appropriately communicated |
| 467 // to the user. | 434 // to the user. |
| 468 UpdateAuthError(fetcher->error()); | 435 UpdateAuthError(fetcher->error()); |
| 469 | 436 |
| 470 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh | 437 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 TokenCache::iterator token_iterator = token_cache_.find(scopes); | 475 TokenCache::iterator token_iterator = token_cache_.find(scopes); |
| 509 if (token_iterator == token_cache_.end()) | 476 if (token_iterator == token_cache_.end()) |
| 510 return NULL; | 477 return NULL; |
| 511 if (token_iterator->second.expiration_date <= base::Time::Now()) { | 478 if (token_iterator->second.expiration_date <= base::Time::Now()) { |
| 512 token_cache_.erase(token_iterator); | 479 token_cache_.erase(token_iterator); |
| 513 return NULL; | 480 return NULL; |
| 514 } | 481 } |
| 515 return &token_iterator->second; | 482 return &token_iterator->second; |
| 516 } | 483 } |
| 517 | 484 |
| 518 bool OAuth2TokenService::RemoveCacheEntry( | |
| 519 const OAuth2TokenService::ScopeSet& scopes, | |
| 520 const std::string& token_to_remove) { | |
| 521 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 522 TokenCache::iterator token_iterator = token_cache_.find(scopes); | |
| 523 if (token_iterator == token_cache_.end() && | |
| 524 token_iterator->second.access_token == token_to_remove) { | |
| 525 token_cache_.erase(token_iterator); | |
| 526 return true; | |
| 527 } | |
| 528 return false; | |
| 529 } | |
| 530 | |
| 531 void OAuth2TokenService::RegisterCacheEntry( | 485 void OAuth2TokenService::RegisterCacheEntry( |
| 532 const std::string& refresh_token, | 486 const std::string& refresh_token, |
| 533 const OAuth2TokenService::ScopeSet& scopes, | 487 const OAuth2TokenService::ScopeSet& scopes, |
| 534 const std::string& access_token, | 488 const std::string& access_token, |
| 535 const base::Time& expiration_date) { | 489 const base::Time& expiration_date) { |
| 536 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 490 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 537 | 491 |
| 538 #if !defined(OS_ANDROID) | |
| 539 // Only register OAuth2 access tokens for the refresh token held by | 492 // Only register OAuth2 access tokens for the refresh token held by |
| 540 // TokenService. | 493 // TokenService. |
| 541 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 494 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
| 542 if (!token_service || | 495 if (!token_service || |
| 543 !token_service->HasOAuthLoginToken() || | 496 !token_service->HasOAuthLoginToken() || |
| 544 token_service->GetOAuth2LoginRefreshToken().compare(refresh_token) != 0) { | 497 token_service->GetOAuth2LoginRefreshToken().compare(refresh_token) != 0) { |
| 545 DLOG(INFO) << | 498 DLOG(INFO) << |
| 546 "Received a token with a refresh token not maintained by TokenService."; | 499 "Received a token with a refresh token not maintained by TokenService."; |
| 547 return; | 500 return; |
| 548 } | 501 } |
| 549 #endif | |
| 550 | 502 |
| 551 CacheEntry& token = token_cache_[scopes]; | 503 CacheEntry& token = token_cache_[scopes]; |
| 552 token.access_token = access_token; | 504 token.access_token = access_token; |
| 553 token.expiration_date = expiration_date; | 505 token.expiration_date = expiration_date; |
| 554 } | 506 } |
| 555 | 507 |
| 556 void OAuth2TokenService::Observe(int type, | 508 void OAuth2TokenService::Observe(int type, |
| 557 const content::NotificationSource& source, | 509 const content::NotificationSource& source, |
| 558 const content::NotificationDetails& details) { | 510 const content::NotificationDetails& details) { |
| 559 DCHECK(type == chrome::NOTIFICATION_TOKENS_CLEARED || | 511 DCHECK(type == chrome::NOTIFICATION_TOKENS_CLEARED || |
| (...skipping 21 matching lines...) Expand all Loading... |
| 581 if (error.state() != last_auth_error_.state()) { | 533 if (error.state() != last_auth_error_.state()) { |
| 582 last_auth_error_ = error; | 534 last_auth_error_ = error; |
| 583 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> | 535 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> |
| 584 AuthStatusChanged(); | 536 AuthStatusChanged(); |
| 585 } | 537 } |
| 586 } | 538 } |
| 587 | 539 |
| 588 GoogleServiceAuthError OAuth2TokenService::GetAuthStatus() const { | 540 GoogleServiceAuthError OAuth2TokenService::GetAuthStatus() const { |
| 589 return last_auth_error_; | 541 return last_auth_error_; |
| 590 } | 542 } |
| OLD | NEW |