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 |
32 namespace { | 36 namespace { |
33 | 37 |
34 // Maximum number of retries in fetching an OAuth2 access token. | 38 // Maximum number of retries in fetching an OAuth2 access token. |
35 const int kMaxFetchRetryNum = 5; | 39 const int kMaxFetchRetryNum = 5; |
36 | 40 |
37 // Returns an exponential backoff in milliseconds including randomness less than | 41 // Returns an exponential backoff in milliseconds including randomness less than |
38 // 1000 ms when retrying fetching an OAuth2 access token. | 42 // 1000 ms when retrying fetching an OAuth2 access token. |
39 int64 ComputeExponentialBackOffMilliseconds(int retry_num) { | 43 int64 ComputeExponentialBackOffMilliseconds(int retry_num) { |
40 DCHECK(retry_num < kMaxFetchRetryNum); | 44 DCHECK(retry_num < kMaxFetchRetryNum); |
41 int64 exponential_backoff_in_seconds = 1 << retry_num; | 45 int64 exponential_backoff_in_seconds = 1 << retry_num; |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 if (profile_) { | 359 if (profile_) { |
356 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> | 360 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> |
357 RemoveProvider(this); | 361 RemoveProvider(this); |
358 } | 362 } |
359 } | 363 } |
360 | 364 |
361 | 365 |
362 // static | 366 // static |
363 void OAuth2TokenService::InformConsumer( | 367 void OAuth2TokenService::InformConsumer( |
364 base::WeakPtr<OAuth2TokenService::RequestImpl> request, | 368 base::WeakPtr<OAuth2TokenService::RequestImpl> request, |
365 GoogleServiceAuthError error, | 369 const GoogleServiceAuthError& error, |
366 std::string access_token, | 370 const std::string& access_token, |
367 base::Time expiration_date) { | 371 const base::Time& expiration_date) { |
368 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 372 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
369 | 373 |
370 if (request) | 374 if (request) |
371 request->InformConsumer(error, access_token, expiration_date); | 375 request->InformConsumer(error, access_token, expiration_date); |
372 } | 376 } |
373 | 377 |
374 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( | 378 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( |
375 const OAuth2TokenService::ScopeSet& scopes, | 379 const OAuth2TokenService::ScopeSet& scopes, |
376 OAuth2TokenService::Consumer* consumer) { | 380 OAuth2TokenService::Consumer* consumer) { |
377 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 381 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
378 | 382 |
379 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); | 383 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); |
380 | 384 |
| 385 #if !defined(OS_ANDROID) |
381 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 386 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
382 if (!token_service || !token_service->HasOAuthLoginToken()) { | 387 if (!token_service || !token_service->HasOAuthLoginToken()) { |
383 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 388 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
384 &OAuth2TokenService::InformConsumer, | 389 &OAuth2TokenService::InformConsumer, |
385 request->AsWeakPtr(), | 390 request->AsWeakPtr(), |
386 GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP), | 391 GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP), |
387 std::string(), | 392 std::string(), |
388 base::Time())); | 393 base::Time())); |
389 return request.PassAs<Request>(); | 394 return request.PassAs<Request>(); |
390 } | 395 } |
| 396 #endif |
391 | 397 |
392 const CacheEntry* cache_entry = GetCacheEntry(scopes); | 398 const CacheEntry* cache_entry = GetCacheEntry(scopes); |
393 if (cache_entry && cache_entry->access_token.length()) { | 399 if (cache_entry && cache_entry->access_token.length()) { |
394 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 400 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
395 &OAuth2TokenService::InformConsumer, | 401 &OAuth2TokenService::InformConsumer, |
396 request->AsWeakPtr(), | 402 request->AsWeakPtr(), |
397 GoogleServiceAuthError(GoogleServiceAuthError::NONE), | 403 GoogleServiceAuthError(GoogleServiceAuthError::NONE), |
398 cache_entry->access_token, | 404 cache_entry->access_token, |
399 cache_entry->expiration_date)); | 405 cache_entry->expiration_date)); |
400 return request.PassAs<Request>(); | 406 return request.PassAs<Request>(); |
401 } | 407 } |
402 | 408 |
| 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 |
403 std::string refresh_token = token_service->GetOAuth2LoginRefreshToken(); | 420 std::string refresh_token = token_service->GetOAuth2LoginRefreshToken(); |
404 if (!refresh_token.length()) { | 421 if (!refresh_token.length()) { |
405 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 422 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
406 &OAuth2TokenService::InformConsumer, | 423 &OAuth2TokenService::InformConsumer, |
407 request->AsWeakPtr(), | 424 request->AsWeakPtr(), |
408 GoogleServiceAuthError( | 425 GoogleServiceAuthError( |
409 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), | 426 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), |
410 std::string(), | 427 std::string(), |
411 base::Time())); | 428 base::Time())); |
412 return request.PassAs<Request>(); | 429 return request.PassAs<Request>(); |
413 } | 430 } |
414 | 431 |
415 // Makes sure there is a pending fetcher for |scopes| and |refresh_token|. | 432 // Makes sure there is a pending fetcher for |scopes| and |refresh_token|. |
416 // Adds |request| to the waiting request list of this fetcher so |request| | 433 // Adds |request| to the waiting request list of this fetcher so |request| |
417 // will be called back when this fetcher finishes fetching. | 434 // will be called back when this fetcher finishes fetching. |
418 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); | 435 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); |
419 std::map<FetchParameters, Fetcher*>::iterator iter = | 436 std::map<FetchParameters, Fetcher*>::iterator iter = |
420 pending_fetchers_.find(fetch_parameters); | 437 pending_fetchers_.find(fetch_parameters); |
421 if (iter != pending_fetchers_.end()) { | 438 if (iter != pending_fetchers_.end()) { |
422 iter->second->AddWaitingRequest(request->AsWeakPtr()); | 439 iter->second->AddWaitingRequest(request->AsWeakPtr()); |
423 return request.PassAs<Request>(); | 440 return request.PassAs<Request>(); |
424 } | 441 } |
425 pending_fetchers_[fetch_parameters] = Fetcher::CreateAndStart( | 442 pending_fetchers_[fetch_parameters] = Fetcher::CreateAndStart( |
426 profile_, getter_, refresh_token, scopes, request->AsWeakPtr()); | 443 profile_, getter_, refresh_token, scopes, request->AsWeakPtr()); |
427 return request.PassAs<Request>(); | 444 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 |
428 } | 461 } |
429 | 462 |
430 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { | 463 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { |
431 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 464 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
432 | 465 |
433 // Update the auth error state so auth errors are appropriately communicated | 466 // Update the auth error state so auth errors are appropriately communicated |
434 // to the user. | 467 // to the user. |
435 UpdateAuthError(fetcher->error()); | 468 UpdateAuthError(fetcher->error()); |
436 | 469 |
437 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh | 470 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 TokenCache::iterator token_iterator = token_cache_.find(scopes); | 508 TokenCache::iterator token_iterator = token_cache_.find(scopes); |
476 if (token_iterator == token_cache_.end()) | 509 if (token_iterator == token_cache_.end()) |
477 return NULL; | 510 return NULL; |
478 if (token_iterator->second.expiration_date <= base::Time::Now()) { | 511 if (token_iterator->second.expiration_date <= base::Time::Now()) { |
479 token_cache_.erase(token_iterator); | 512 token_cache_.erase(token_iterator); |
480 return NULL; | 513 return NULL; |
481 } | 514 } |
482 return &token_iterator->second; | 515 return &token_iterator->second; |
483 } | 516 } |
484 | 517 |
| 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 |
485 void OAuth2TokenService::RegisterCacheEntry( | 531 void OAuth2TokenService::RegisterCacheEntry( |
486 const std::string& refresh_token, | 532 const std::string& refresh_token, |
487 const OAuth2TokenService::ScopeSet& scopes, | 533 const OAuth2TokenService::ScopeSet& scopes, |
488 const std::string& access_token, | 534 const std::string& access_token, |
489 const base::Time& expiration_date) { | 535 const base::Time& expiration_date) { |
490 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 536 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
491 | 537 |
| 538 #if !defined(OS_ANDROID) |
492 // Only register OAuth2 access tokens for the refresh token held by | 539 // Only register OAuth2 access tokens for the refresh token held by |
493 // TokenService. | 540 // TokenService. |
494 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 541 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); |
495 if (!token_service || | 542 if (!token_service || |
496 !token_service->HasOAuthLoginToken() || | 543 !token_service->HasOAuthLoginToken() || |
497 token_service->GetOAuth2LoginRefreshToken().compare(refresh_token) != 0) { | 544 token_service->GetOAuth2LoginRefreshToken().compare(refresh_token) != 0) { |
498 DLOG(INFO) << | 545 DLOG(INFO) << |
499 "Received a token with a refresh token not maintained by TokenService."; | 546 "Received a token with a refresh token not maintained by TokenService."; |
500 return; | 547 return; |
501 } | 548 } |
| 549 #endif |
502 | 550 |
503 CacheEntry& token = token_cache_[scopes]; | 551 CacheEntry& token = token_cache_[scopes]; |
504 token.access_token = access_token; | 552 token.access_token = access_token; |
505 token.expiration_date = expiration_date; | 553 token.expiration_date = expiration_date; |
506 } | 554 } |
507 | 555 |
508 void OAuth2TokenService::Observe(int type, | 556 void OAuth2TokenService::Observe(int type, |
509 const content::NotificationSource& source, | 557 const content::NotificationSource& source, |
510 const content::NotificationDetails& details) { | 558 const content::NotificationDetails& details) { |
511 DCHECK(type == chrome::NOTIFICATION_TOKENS_CLEARED || | 559 DCHECK(type == chrome::NOTIFICATION_TOKENS_CLEARED || |
(...skipping 21 matching lines...) Expand all Loading... |
533 if (error.state() != last_auth_error_.state()) { | 581 if (error.state() != last_auth_error_.state()) { |
534 last_auth_error_ = error; | 582 last_auth_error_ = error; |
535 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> | 583 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> |
536 AuthStatusChanged(); | 584 AuthStatusChanged(); |
537 } | 585 } |
538 } | 586 } |
539 | 587 |
540 GoogleServiceAuthError OAuth2TokenService::GetAuthStatus() const { | 588 GoogleServiceAuthError OAuth2TokenService::GetAuthStatus() const { |
541 return last_auth_error_; | 589 return last_auth_error_; |
542 } | 590 } |
OLD | NEW |