diff options
author | rogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 23:27:20 +0000 |
---|---|---|
committer | rogerta@chromium.org <rogerta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 23:27:20 +0000 |
commit | 431a075a671f8c7f1f31a90282f76af6e0cc94ff (patch) | |
tree | 0d0f540ddb318688b1613408c72030fc6700d094 | |
parent | fca61dc53df4dbb46c2ee4bf075f662632418d61 (diff) | |
download | chromium_src-431a075a671f8c7f1f31a90282f76af6e0cc94ff.zip chromium_src-431a075a671f8c7f1f31a90282f76af6e0cc94ff.tar.gz chromium_src-431a075a671f8c7f1f31a90282f76af6e0cc94ff.tar.bz2 |
Use new people.get api instead of oauth2/v1/userinfo.
Consolidate all uses into main helper class.
Details about new api: https://developers.google.com/+/api/latest/people/get
Format of returned response: https://developers.google.com/+/api/latest/people#resource
BUG=320354
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=267068
Review URL: https://codereview.chromium.org/257773002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267374 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 290 insertions, 216 deletions
diff --git a/chrome/browser/chromeos/login/user_image_manager_browsertest.cc b/chrome/browser/chromeos/login/user_image_manager_browsertest.cc index 796998b..0bb9730 100644 --- a/chrome/browser/chromeos/login/user_image_manager_browsertest.cc +++ b/chrome/browser/chromeos/login/user_image_manager_browsertest.cc @@ -56,6 +56,7 @@ #include "content/public/browser/notification_source.h" #include "content/public/test/test_utils.h" #include "crypto/rsa_private_key.h" +#include "google_apis/gaia/gaia_oauth_client.h" #include "google_apis/gaia/oauth2_token_service.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/url_request/test_url_fetcher_factory.h" @@ -229,13 +230,15 @@ class UserImageManagerTest : public LoginManagerTest, static_cast<OAuth2TokenService::Consumer*>(profile_downloader)-> OnGetTokenSuccess(NULL, - std::string(), + "token", base::Time::Now() + base::TimeDelta::FromDays(1)); - net::TestURLFetcher* fetcher = url_fetcher_factory->GetFetcherByID(0); + net::TestURLFetcher* fetcher = + url_fetcher_factory->GetFetcherByID( + gaia::GaiaOAuthClient::kUrlFetcherId); ASSERT_TRUE(fetcher); fetcher->SetResponseString( - "{ \"picture\": \"http://localhost/avatar.jpg\" }"); + "{ \"image\": {\"url\": \"http://localhost/avatar.jpg\"} }"); fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, net::OK)); fetcher->set_response_code(200); diff --git a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc index abbab93..006b18e 100644 --- a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc +++ b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc @@ -58,6 +58,8 @@ void PolicyOAuth2TokenFetcher::StartFetchingAccessToken() { std::vector<std::string> scopes; scopes.push_back(GaiaConstants::kDeviceManagementServiceOAuth); scopes.push_back(GaiaConstants::kOAuthWrapBridgeUserInfoScope); + scopes.push_back(GaiaConstants::kGoogleUserInfoEmail); + scopes.push_back(GaiaConstants::kGoogleUserInfoProfile); access_token_fetcher_.reset( new OAuth2AccessTokenFetcherImpl(this, system_context_getter_.get(), diff --git a/chrome/browser/chromeos/policy/wildcard_login_checker.cc b/chrome/browser/chromeos/policy/wildcard_login_checker.cc index 7fa0253..7c2bd2e 100644 --- a/chrome/browser/chromeos/policy/wildcard_login_checker.cc +++ b/chrome/browser/chromeos/policy/wildcard_login_checker.cc @@ -18,7 +18,7 @@ namespace { // Presence of this key in the userinfo response indicates whether the user is // on a hosted domain. -const char kHostedDomainKey[] = "hd"; +const char kHostedDomainKey[] = "domain"; // UMA histogram names. const char kUMADelayPolicyTokenFetch[] = diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc index f9e490c..c80c62e 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc @@ -36,6 +36,7 @@ #include "content/public/browser/notification_source.h" #include "content/public/test/test_browser_thread_bundle.h" #include "google_apis/gaia/gaia_constants.h" +#include "google_apis/gaia/gaia_oauth_client.h" #include "google_apis/gaia/google_service_auth_error.h" #include "net/http/http_status_code.h" #include "net/url_request/test_url_fetcher_factory.h" @@ -74,7 +75,7 @@ const char kValidTokenResponse[] = const char kHostedDomainResponse[] = "{" - " \"hd\": \"test.com\"" + " \"domain\": \"test.com\"" "}"; class SigninManagerFake : public FakeSigninManager { @@ -231,10 +232,15 @@ class UserPolicySigninServiceTest : public testing::Test { return static_cast<FakeProfileOAuth2TokenService*>(service); } + // Returns true if a request for policy information is active. A request + // is considered active if there is an active fetcher for an access token + // hosted domain information (i.e. the gaia oauth client) or some other + // fecther used in the code (id 0). bool IsRequestActive() { if (!GetTokenService()->GetPendingRequests().empty()) return true; - return url_factory_.GetFetcherByID(0); + return url_factory_.GetFetcherByID(0) || + url_factory_.GetFetcherByID(gaia::GaiaOAuthClient::kUrlFetcherId); } void MakeOAuthTokenFetchSucceed() { @@ -252,7 +258,8 @@ class UserPolicySigninServiceTest : public testing::Test { void ReportHostedDomainStatus(bool is_hosted_domain) { ASSERT_TRUE(IsRequestActive()); - net::TestURLFetcher* fetcher = url_factory_.GetFetcherByID(0); + net::TestURLFetcher* fetcher = + url_factory_.GetFetcherByID(gaia::GaiaOAuthClient::kUrlFetcherId); fetcher->set_response_code(net::HTTP_OK); fetcher->SetResponseString(is_hosted_domain ? kHostedDomainResponse : "{}"); fetcher->delegate()->OnURLFetchComplete(fetcher); diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc index 15e8cee..5d08ffe 100644 --- a/chrome/browser/profiles/profile_downloader.cc +++ b/chrome/browser/profiles/profile_downloader.cc @@ -38,24 +38,16 @@ namespace { const char kAuthorizationHeader[] = "Authorization: Bearer %s"; -// URL requesting user info. -const char kUserEntryURL[] = - "https://www.googleapis.com/oauth2/v1/userinfo?alt=json"; - -// OAuth scope for the user info API. -// For more info, see https://developers.google.com/accounts/docs/OAuth2LoginV1. -const char kAPIScope[] = "https://www.googleapis.com/auth/userinfo.profile"; - // Path in JSON dictionary to user's photo thumbnail URL. -const char kPhotoThumbnailURLPath[] = "picture"; +const char kPhotoThumbnailURLPath[] = "image.url"; // From the user info API, this field corresponds to the full name of the user. -const char kFullNamePath[] = "name"; +const char kFullNamePath[] = "displayName"; -const char kGivenNamePath[] = "given_name"; +const char kGivenNamePath[] = "name.givenName"; // Path in JSON dictionary to user's preferred locale. -const char kLocalePath[] = "locale"; +const char kLocalePath[] = "language"; // Path format for specifying thumbnail's size. const char kThumbnailSizeFormat[] = "s%d-c"; @@ -133,7 +125,7 @@ bool GetImageURLWithSize(const GURL& old_url, int size, GURL* new_url) { // Parses the entry response and gets the name and profile image URL. // |data| should be the JSON formatted data return by the response. // Returns false to indicate a parsing error. -bool ProfileDownloader::ParseProfileJSON(const std::string& data, +bool ProfileDownloader::ParseProfileJSON(base::DictionaryValue* root_dictionary, base::string16* full_name, base::string16* given_name, std::string* url, @@ -149,23 +141,6 @@ bool ProfileDownloader::ParseProfileJSON(const std::string& data, *url = std::string(); *profile_locale = std::string(); - int error_code = -1; - std::string error_message; - scoped_ptr<base::Value> root_value(base::JSONReader::ReadAndReturnError( - data, base::JSON_PARSE_RFC, &error_code, &error_message)); - if (!root_value) { - LOG(ERROR) << "Error while parsing user entry response: " - << error_message; - return false; - } - if (!root_value->IsType(base::Value::TYPE_DICTIONARY)) { - LOG(ERROR) << "JSON root is not a dictionary: " - << root_value->GetType(); - return false; - } - base::DictionaryValue* root_dictionary = - static_cast<base::DictionaryValue*>(root_value.get()); - root_dictionary->GetString(kFullNamePath, full_name); root_dictionary->GetString(kGivenNamePath, given_name); root_dictionary->GetString(kLocalePath, profile_locale); @@ -273,24 +248,17 @@ std::string ProfileDownloader::GetProfilePictureURL() const { } void ProfileDownloader::StartFetchingImage() { + DCHECK(!auth_token_.empty()); VLOG(1) << "Fetching user entry with token: " << auth_token_; - user_entry_fetcher_.reset(net::URLFetcher::Create( - GURL(kUserEntryURL), net::URLFetcher::GET, this)); - user_entry_fetcher_->SetRequestContext( - delegate_->GetBrowserProfile()->GetRequestContext()); - user_entry_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | - net::LOAD_DO_NOT_SAVE_COOKIES); - if (!auth_token_.empty()) { - user_entry_fetcher_->SetExtraRequestHeaders( - base::StringPrintf(kAuthorizationHeader, auth_token_.c_str())); - } - user_entry_fetcher_->Start(); + gaia_client_.reset(new gaia::GaiaOAuthClient( + delegate_->GetBrowserProfile()->GetRequestContext())); + gaia_client_->GetUserInfo(auth_token_, 0, this); } void ProfileDownloader::StartFetchingOAuth2AccessToken() { Profile* profile = delegate_->GetBrowserProfile(); OAuth2TokenService::ScopeSet scopes; - scopes.insert(kAPIScope); + scopes.insert(GaiaConstants::kGoogleUserInfoProfile); ProfileOAuth2TokenService* token_service = ProfileOAuth2TokenServiceFactory::GetForProfile(profile); oauth2_access_token_request_ = token_service->StartRequest( @@ -307,27 +275,10 @@ ProfileDownloader::~ProfileDownloader() { service->RemoveObserver(this); } -void ProfileDownloader::OnURLFetchComplete(const net::URLFetcher* source) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - std::string data; - source->GetResponseAsString(&data); - bool network_error = - source->GetStatus().status() != net::URLRequestStatus::SUCCESS; - if (network_error || source->GetResponseCode() != 200) { - LOG(WARNING) << "Fetching profile data failed"; - DVLOG(1) << " Status: " << source->GetStatus().status(); - DVLOG(1) << " Error: " << source->GetStatus().error(); - DVLOG(1) << " Response code: " << source->GetResponseCode(); - DVLOG(1) << " Url: " << source->GetURL().spec(); - delegate_->OnProfileDownloadFailure(this, network_error ? - ProfileDownloaderDelegate::NETWORK_ERROR : - ProfileDownloaderDelegate::SERVICE_ERROR); - return; - } - - if (source == user_entry_fetcher_.get()) { +void ProfileDownloader::OnGetUserInfoResponse( + scoped_ptr<base::DictionaryValue> user_info) { std::string image_url; - if (!ParseProfileJSON(data, + if (!ParseProfileJSON(user_info.get(), &profile_full_name_, &profile_given_name_, &image_url, @@ -367,14 +318,45 @@ void ProfileDownloader::OnURLFetchComplete(const net::URLFetcher* source) { base::StringPrintf(kAuthorizationHeader, auth_token_.c_str())); } profile_image_fetcher_->Start(); - } else if (source == profile_image_fetcher_.get()) { - VLOG(1) << "Decoding the image..."; - scoped_refptr<ImageDecoder> image_decoder = new ImageDecoder( - this, data, ImageDecoder::DEFAULT_CODEC); - scoped_refptr<base::MessageLoopProxy> task_runner = - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); - image_decoder->Start(task_runner); +} + +void ProfileDownloader::OnOAuthError() { + LOG(WARNING) << "OnOAuthError: Fetching profile data failed"; + delegate_->OnProfileDownloadFailure( + this, ProfileDownloaderDelegate::SERVICE_ERROR); +} + +void ProfileDownloader::OnNetworkError(int response_code) { + LOG(WARNING) << "OnNetworkError: Fetching profile data failed"; + DVLOG(1) << " Response code: " << response_code; + delegate_->OnProfileDownloadFailure( + this, ProfileDownloaderDelegate::NETWORK_ERROR); +} + +void ProfileDownloader::OnURLFetchComplete(const net::URLFetcher* source) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::string data; + source->GetResponseAsString(&data); + bool network_error = + source->GetStatus().status() != net::URLRequestStatus::SUCCESS; + if (network_error || source->GetResponseCode() != 200) { + LOG(WARNING) << "Fetching profile data failed"; + DVLOG(1) << " Status: " << source->GetStatus().status(); + DVLOG(1) << " Error: " << source->GetStatus().error(); + DVLOG(1) << " Response code: " << source->GetResponseCode(); + DVLOG(1) << " Url: " << source->GetURL().spec(); + delegate_->OnProfileDownloadFailure(this, network_error ? + ProfileDownloaderDelegate::NETWORK_ERROR : + ProfileDownloaderDelegate::SERVICE_ERROR); + return; } + + VLOG(1) << "Decoding the image..."; + scoped_refptr<ImageDecoder> image_decoder = new ImageDecoder( + this, data, ImageDecoder::DEFAULT_CODEC); + scoped_refptr<base::MessageLoopProxy> task_runner = + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); + image_decoder->Start(task_runner); } void ProfileDownloader::OnImageDecoded(const ImageDecoder* decoder, diff --git a/chrome/browser/profiles/profile_downloader.h b/chrome/browser/profiles/profile_downloader.h index 8faf26d..a178773 100644 --- a/chrome/browser/profiles/profile_downloader.h +++ b/chrome/browser/profiles/profile_downloader.h @@ -12,6 +12,7 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "chrome/browser/image_decoder.h" +#include "google_apis/gaia/gaia_oauth_client.h" #include "google_apis/gaia/oauth2_token_service.h" #include "net/url_request/url_fetcher_delegate.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -26,7 +27,8 @@ class URLFetcher; // Downloads user profile information. The profile picture is decoded in a // sandboxed process. -class ProfileDownloader : public net::URLFetcherDelegate, +class ProfileDownloader : public gaia::GaiaOAuthClient::Delegate, + public net::URLFetcherDelegate, public ImageDecoder::Delegate, public OAuth2TokenService::Observer, public OAuth2TokenService::Consumer { @@ -80,6 +82,12 @@ class ProfileDownloader : public net::URLFetcherDelegate, FRIEND_TEST_ALL_PREFIXES(ProfileDownloaderTest, ParseData); FRIEND_TEST_ALL_PREFIXES(ProfileDownloaderTest, DefaultURL); + // gaia::GaiaOAuthClient::Delegate implementation. + virtual void OnGetUserInfoResponse( + scoped_ptr<base::DictionaryValue> user_info) OVERRIDE; + virtual void OnOAuthError() OVERRIDE; + virtual void OnNetworkError(int response_code) OVERRIDE; + // Overriden from net::URLFetcherDelegate: virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; @@ -101,7 +109,7 @@ class ProfileDownloader : public net::URLFetcherDelegate, // Parses the entry response and gets the name, profile image URL and locale. // |data| should be the JSON formatted data return by the response. // Returns false to indicate a parsing error. - static bool ParseProfileJSON(const std::string& data, + static bool ParseProfileJSON(base::DictionaryValue* root_dictionary, base::string16* full_name, base::string16* given_name, std::string* url, @@ -123,7 +131,7 @@ class ProfileDownloader : public net::URLFetcherDelegate, ProfileDownloaderDelegate* delegate_; std::string account_id_; std::string auth_token_; - scoped_ptr<net::URLFetcher> user_entry_fetcher_; + scoped_ptr<gaia::GaiaOAuthClient> gaia_client_; scoped_ptr<net::URLFetcher> profile_image_fetcher_; scoped_ptr<OAuth2TokenService::Request> oauth2_access_token_request_; base::string16 profile_full_name_; diff --git a/chrome/browser/profiles/profile_downloader_unittest.cc b/chrome/browser/profiles/profile_downloader_unittest.cc index 3761c77..c7c1312 100644 --- a/chrome/browser/profiles/profile_downloader_unittest.cc +++ b/chrome/browser/profiles/profile_downloader_unittest.cc @@ -4,38 +4,31 @@ #include "chrome/browser/profiles/profile_downloader.h" +#include "base/json/json_reader.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" +#include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" namespace { -std::string GetJSonData(const std::string& full_name, - const std::string& given_name, - const std::string& url, - const std::string& locale) { - std::stringstream stream; - bool started = false; - - stream << "{ "; - if (!full_name.empty()) { - stream << "\"name\": \"" << full_name << "\""; - started = true; - } - if (!given_name.empty()) { - stream << (started ? ", " : "") << "\"given_name\": \"" << given_name - << "\""; - started = true; - } - if (!url.empty()) { - stream << (started ? ", " : "") << "\"picture\": \"" << url << "\""; - started = true; - } +void GetJSonData(const std::string& full_name, + const std::string& given_name, + const std::string& url, + const std::string& locale, + base::DictionaryValue* dict) { + if (!full_name.empty()) + dict->SetString("displayName", full_name); - if (!locale.empty()) - stream << (started ? ", " : "") << "\"locale\": \"" << locale << "\""; + if (!given_name.empty()) + dict->SetString("name.givenName", given_name); + + if (!url.empty()) + dict->SetString("image.url", url); - stream << " }"; - return stream.str(); + if (!locale.empty()) + dict->SetString("language", locale); } } // namespace @@ -58,8 +51,10 @@ class ProfileDownloaderTest : public testing::Test { base::string16 parsed_given_name; std::string parsed_url; std::string parsed_locale; + scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); + GetJSonData(full_name, given_name, url, locale, dict.get()); bool result = ProfileDownloader::ParseProfileJSON( - GetJSonData(full_name, given_name, url, locale), + dict.get(), &parsed_full_name, &parsed_given_name, &parsed_url, diff --git a/chrome/browser/signin/account_reconcilor_unittest.cc b/chrome/browser/signin/account_reconcilor_unittest.cc index ca312d5..9da0f1d 100644 --- a/chrome/browser/signin/account_reconcilor_unittest.cc +++ b/chrome/browser/signin/account_reconcilor_unittest.cc @@ -262,7 +262,7 @@ TEST_F(AccountReconcilorTest, ValidateAccountsFromTokens) { reconcilor->ValidateAccountsFromTokenService(); ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked()); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS); token_service()->IssueTokenForAllPendingRequests("access_token", base::Time::Now() + base::TimeDelta::FromHours(1)); @@ -284,7 +284,7 @@ TEST_F(AccountReconcilorTest, ValidateAccountsFromTokensFailedUserInfo) { reconcilor->ValidateAccountsFromTokenService(); ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked()); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "", net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS); token_service()->IssueTokenForAllPendingRequests("access_token", base::Time::Now() + base::TimeDelta::FromHours(1)); @@ -326,7 +326,7 @@ TEST_F(AccountReconcilorTest, StartReconcileNoop) { SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", net::HTTP_OK, net::URLRequestStatus::SUCCESS); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS); reconcilor->StartReconcile(); @@ -365,7 +365,7 @@ TEST_F(AccountReconcilorTest, StartReconcileNoopWithDots) { SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), "[\"f\", [[\"b\", 0, \"n\", \"dot.s@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", net::HTTP_OK, net::URLRequestStatus::SUCCESS); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS); reconcilor->StartReconcile(); @@ -400,7 +400,7 @@ TEST_F(AccountReconcilorTest, StartReconcileNoopMultiple) { "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], " "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", net::HTTP_OK, net::URLRequestStatus::SUCCESS); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS); reconcilor->StartReconcile(); @@ -436,7 +436,7 @@ TEST_F(AccountReconcilorTest, StartReconcileAddToCookie) { SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", net::HTTP_OK, net::URLRequestStatus::SUCCESS); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS); AccountReconcilor* reconcilor = GetMockReconcilor(); @@ -464,7 +464,7 @@ TEST_F(AccountReconcilorTest, StartReconcileAddToChrome) { "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], " "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", net::HTTP_OK, net::URLRequestStatus::SUCCESS); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS); AccountReconcilor* reconcilor = GetMockReconcilor(); @@ -491,7 +491,7 @@ TEST_F(AccountReconcilorTest, StartReconcileBadPrimary) { "[\"f\", [[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1], " "[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", net::HTTP_OK, net::URLRequestStatus::SUCCESS); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS); AccountReconcilor* reconcilor = GetMockReconcilor(); @@ -522,7 +522,7 @@ TEST_F(AccountReconcilorTest, StartReconcileOnlyOnce) { SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", net::HTTP_OK, net::URLRequestStatus::SUCCESS); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS); ASSERT_FALSE(reconcilor->is_reconcile_started_); @@ -547,7 +547,7 @@ TEST_F(AccountReconcilorTest, StartReconcileWithSessionInfoExpiredDefault) { "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]," "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", net::HTTP_OK, net::URLRequestStatus::SUCCESS); - SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo", + SetFakeResponse(GaiaUrls::GetInstance()->people_get_url().spec(), "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS); AccountReconcilor* reconcilor = diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc index dea47a9..3c8b63a 100644 --- a/chrome/browser/sync/test/integration/sync_test.cc +++ b/chrome/browser/sync/test/integration/sync_test.cc @@ -515,7 +515,7 @@ void SyncTest::SetupMockGaiaResponses() { net::HTTP_OK, net::URLRequestStatus::SUCCESS); fake_factory_->SetFakeResponse( - GaiaUrls::GetInstance()->oauth_user_info_url(), + GaiaUrls::GetInstance()->people_get_url(), "{" " \"id\": \"12345\"" "}", diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc index b293e67..44b5281 100644 --- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc +++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc @@ -411,13 +411,13 @@ class LocalDiscoveryUITest : public WebUIBrowserTest { .Times(AnyNumber()); fake_fetcher_factory().SetFakeResponse( - GaiaUrls::GetInstance()->oauth_user_info_url(), + GaiaUrls::GetInstance()->people_get_url(), kResponseGaiaId, net::HTTP_OK, net::URLRequestStatus::SUCCESS); EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher( - GaiaUrls::GetInstance()->oauth_user_info_url().spec())) + GaiaUrls::GetInstance()->people_get_url().spec())) .Times(AnyNumber()); ProfileOAuth2TokenService* token_service = diff --git a/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc b/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc index c7b184b..b390ffb 100644 --- a/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc +++ b/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc @@ -24,7 +24,7 @@ namespace policy { // The key under which the hosted-domain value is stored in the UserInfo // response. -const char kGetHostedDomainKey[] = "hd"; +const char kGetHostedDomainKey[] = "domain"; typedef base::Callback<void(const std::string&)> StringCallback; diff --git a/components/policy/core/common/cloud/user_info_fetcher.cc b/components/policy/core/common/cloud/user_info_fetcher.cc index b8f9f74d..978e4c8 100644 --- a/components/policy/core/common/cloud/user_info_fetcher.cc +++ b/components/policy/core/common/cloud/user_info_fetcher.cc @@ -16,23 +16,11 @@ #include "net/url_request/url_request_status.h" #include "url/gurl.h" -namespace { - -static const char kAuthorizationHeaderFormat[] = - "Authorization: Bearer %s"; - -static std::string MakeAuthorizationHeader(const std::string& auth_token) { - return base::StringPrintf(kAuthorizationHeaderFormat, auth_token.c_str()); -} - -} // namespace - namespace policy { UserInfoFetcher::UserInfoFetcher(Delegate* delegate, net::URLRequestContextGetter* context) - : delegate_(delegate), - context_(context) { + : delegate_(delegate), gaia_client_(context) { DCHECK(delegate); } @@ -41,49 +29,28 @@ UserInfoFetcher::~UserInfoFetcher() { void UserInfoFetcher::Start(const std::string& access_token) { // Create a URLFetcher and start it. - url_fetcher_.reset(net::URLFetcher::Create( - 0, GaiaUrls::GetInstance()->oauth_user_info_url(), - net::URLFetcher::GET, this)); - url_fetcher_->SetRequestContext(context_); - url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | - net::LOAD_DO_NOT_SAVE_COOKIES); - url_fetcher_->AddExtraRequestHeader(MakeAuthorizationHeader(access_token)); - url_fetcher_->Start(); // Results in a call to OnURLFetchComplete(). + gaia_client_.GetUserInfo(access_token, 0, &delegate_); } -void UserInfoFetcher::OnURLFetchComplete(const net::URLFetcher* source) { - net::URLRequestStatus status = source->GetStatus(); - GoogleServiceAuthError error = GoogleServiceAuthError::AuthErrorNone(); - if (!status.is_success()) { - if (status.status() == net::URLRequestStatus::CANCELED) - error = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); - else - error = GoogleServiceAuthError::FromConnectionError(status.error()); - } else if (source->GetResponseCode() != net::HTTP_OK) { - DLOG(WARNING) << "UserInfo request failed with HTTP code: " - << source->GetResponseCode(); - error = GoogleServiceAuthError( - GoogleServiceAuthError::CONNECTION_FAILED); - } - if (error.state() != GoogleServiceAuthError::NONE) { - delegate_->OnGetUserInfoFailure(error); - return; - } +UserInfoFetcher::GaiaDelegate::GaiaDelegate(UserInfoFetcher::Delegate* delegate) + : delegate_(delegate) { +} + +void UserInfoFetcher::GaiaDelegate::OnGetUserInfoResponse( + scoped_ptr<base::DictionaryValue> user_info) { + delegate_->OnGetUserInfoSuccess(user_info.get()); +} + +void UserInfoFetcher::GaiaDelegate::OnOAuthError() { + GoogleServiceAuthError error = + GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); + delegate_->OnGetUserInfoFailure(error); +} - // Successfully fetched userinfo from the server - parse it and hand it off - // to the delegate. - std::string unparsed_data; - source->GetResponseAsString(&unparsed_data); - DVLOG(1) << "Received UserInfo response: " << unparsed_data; - scoped_ptr<base::Value> parsed_value(base::JSONReader::Read(unparsed_data)); - base::DictionaryValue* dict; - if (parsed_value.get() && parsed_value->GetAsDictionary(&dict)) { - delegate_->OnGetUserInfoSuccess(dict); - } else { - NOTREACHED() << "Could not parse userinfo response from server"; - delegate_->OnGetUserInfoFailure(GoogleServiceAuthError( - GoogleServiceAuthError::CONNECTION_FAILED)); - } +void UserInfoFetcher::GaiaDelegate::OnNetworkError(int response_code) { + GoogleServiceAuthError error = + GoogleServiceAuthError::FromConnectionError(response_code); + delegate_->OnGetUserInfoFailure(error); } }; // namespace policy diff --git a/components/policy/core/common/cloud/user_info_fetcher.h b/components/policy/core/common/cloud/user_info_fetcher.h index c248d81..0f4c25f 100644 --- a/components/policy/core/common/cloud/user_info_fetcher.h +++ b/components/policy/core/common/cloud/user_info_fetcher.h @@ -8,6 +8,7 @@ #include <string> #include "base/memory/scoped_ptr.h" #include "components/policy/policy_export.h" +#include "google_apis/gaia/gaia_oauth_client.h" #include "net/url_request/url_fetcher_delegate.h" class GoogleServiceAuthError; @@ -25,7 +26,7 @@ namespace policy { // Class that makes a UserInfo request, parses the response, and notifies // a provided Delegate when the request is complete. -class POLICY_EXPORT UserInfoFetcher : public net::URLFetcherDelegate { +class POLICY_EXPORT UserInfoFetcher { public: class POLICY_EXPORT Delegate { public: @@ -48,13 +49,25 @@ class POLICY_EXPORT UserInfoFetcher : public net::URLFetcherDelegate { // Starts the UserInfo request, using the passed OAuth2 |access_token|. void Start(const std::string& access_token); - // net::URLFetcherDelegate implementation. - virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; - private: - Delegate* delegate_; - net::URLRequestContextGetter* context_; - scoped_ptr<net::URLFetcher> url_fetcher_; + class GaiaDelegate : public gaia::GaiaOAuthClient::Delegate { + public: + explicit GaiaDelegate(UserInfoFetcher::Delegate* delegate); + + private: + // gaia::GaiaOAuthClient::Delegate implementation. + virtual void OnGetUserInfoResponse( + scoped_ptr<base::DictionaryValue> user_info) OVERRIDE; + virtual void OnOAuthError() OVERRIDE; + virtual void OnNetworkError(int response_code) OVERRIDE; + + UserInfoFetcher::Delegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(GaiaDelegate); + }; + + GaiaDelegate delegate_; + gaia::GaiaOAuthClient gaia_client_; DISALLOW_COPY_AND_ASSIGN(UserInfoFetcher); }; diff --git a/components/policy/core/common/cloud/user_info_fetcher_unittest.cc b/components/policy/core/common/cloud/user_info_fetcher_unittest.cc index 8649427..5c8a24b 100644 --- a/components/policy/core/common/cloud/user_info_fetcher_unittest.cc +++ b/components/policy/core/common/cloud/user_info_fetcher_unittest.cc @@ -4,6 +4,7 @@ #include "base/values.h" #include "components/policy/core/common/cloud/user_info_fetcher.h" +#include "google_apis/gaia/gaia_oauth_client.h" #include "google_apis/gaia/google_service_auth_error.h" #include "net/http/http_status_code.h" #include "net/url_request/test_url_fetcher_factory.h" @@ -20,7 +21,7 @@ static const char kUserInfoResponse[] = "{" " \"email\": \"test_user@test.com\"," " \"verified_email\": true," - " \"hd\": \"test.com\"" + " \"domain\": \"test.com\"" "}"; class MockUserInfoFetcherDelegate : public UserInfoFetcher::Delegate { @@ -49,7 +50,8 @@ TEST_F(UserInfoFetcherTest, FailedFetch) { // Fake a failed fetch - should result in the failure callback being invoked. EXPECT_CALL(delegate, OnGetUserInfoFailure(_)); - net::TestURLFetcher* url_fetcher = url_factory_.GetFetcherByID(0); + net::TestURLFetcher* url_fetcher = + url_factory_.GetFetcherByID(gaia::GaiaOAuthClient::kUrlFetcherId); url_fetcher->set_status(net::URLRequestStatus( net::URLRequestStatus::FAILED, -1)); url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); @@ -65,12 +67,13 @@ TEST_F(UserInfoFetcherTest, SuccessfulFetch) { scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); dict->SetString("email", "test_user@test.com"); dict->SetBoolean("verified_email", true); - dict->SetString("hd", "test.com"); + dict->SetString("domain", "test.com"); // Fake a successful fetch - should result in the data being parsed and // the values passed off to the success callback. EXPECT_CALL(delegate, OnGetUserInfoSuccess(MatchDict(dict.get()))); - net::TestURLFetcher* url_fetcher = url_factory_.GetFetcherByID(0); + net::TestURLFetcher* url_fetcher = + url_factory_.GetFetcherByID(gaia::GaiaOAuthClient::kUrlFetcherId); url_fetcher->set_response_code(net::HTTP_OK); url_fetcher->SetResponseString(kUserInfoResponse); url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); diff --git a/google_apis/gaia/gaia_constants.cc b/google_apis/gaia/gaia_constants.cc index 60546bf..14a41c9 100644 --- a/google_apis/gaia/gaia_constants.cc +++ b/google_apis/gaia/gaia_constants.cc @@ -45,6 +45,11 @@ const char kChromeSyncManagedOAuth2Scope[] = const char kGoogleTalkOAuth2Scope[] = "https://www.googleapis.com/auth/googletalk"; +const char kGoogleUserInfoEmail[] = + "https://www.googleapis.com/auth/userinfo.email"; +const char kGoogleUserInfoProfile[] = + "https://www.googleapis.com/auth/userinfo.profile"; + // Used to mint uber auth tokens when needed. const char kGaiaSid[] = "sid"; const char kGaiaLsid[] = "lsid"; diff --git a/google_apis/gaia/gaia_constants.h b/google_apis/gaia/gaia_constants.h index 406298c..7adc130 100644 --- a/google_apis/gaia/gaia_constants.h +++ b/google_apis/gaia/gaia_constants.h @@ -18,6 +18,8 @@ extern const char kGaiaService[]; // uber token extern const char kPicasaService[]; extern const char kSyncService[]; extern const char kRemotingService[]; + +// OAuth2 scopes. extern const char kOAuth1LoginScope[]; extern const char kOAuthWrapBridgeUserInfoScope[]; extern const char kDeviceManagementServiceOAuth[]; @@ -25,6 +27,8 @@ extern const char kAnyApiOAuth2Scope[]; extern const char kChromeSyncOAuth2Scope[]; extern const char kChromeSyncManagedOAuth2Scope[]; extern const char kGoogleTalkOAuth2Scope[]; +extern const char kGoogleUserInfoEmail[]; +extern const char kGoogleUserInfoProfile[]; // Used with uber auth tokens when needed. extern const char kGaiaSid[]; diff --git a/google_apis/gaia/gaia_oauth_client.cc b/google_apis/gaia/gaia_oauth_client.cc index 1113ff6..1d5f9eb 100644 --- a/google_apis/gaia/gaia_oauth_client.cc +++ b/google_apis/gaia/gaia_oauth_client.cc @@ -56,6 +56,9 @@ class GaiaOAuthClient::Core void GetUserId(const std::string& oauth_access_token, int max_retries, Delegate* delegate); + void GetUserInfo(const std::string& oauth_access_token, + int max_retries, + Delegate* delegate); void GetTokenInfo(const std::string& oauth_access_token, int max_retries, Delegate* delegate); @@ -73,13 +76,14 @@ class GaiaOAuthClient::Core TOKEN_INFO, USER_EMAIL, USER_ID, + USER_INFO, }; virtual ~Core() {} - void GetUserInfo(const std::string& oauth_access_token, - int max_retries, - Delegate* delegate); + void PeopleGet(const std::string& oauth_access_token, + int max_retries, + Delegate* delegate); void MakeGaiaRequest(const GURL& url, const std::string& post_body, int max_retries, @@ -145,7 +149,7 @@ void GaiaOAuthClient::Core::GetUserEmail(const std::string& oauth_access_token, DCHECK_EQ(request_type_, NO_PENDING_REQUEST); DCHECK(!request_.get()); request_type_ = USER_EMAIL; - GetUserInfo(oauth_access_token, max_retries, delegate); + PeopleGet(oauth_access_token, max_retries, delegate); } void GaiaOAuthClient::Core::GetUserId(const std::string& oauth_access_token, @@ -154,16 +158,25 @@ void GaiaOAuthClient::Core::GetUserId(const std::string& oauth_access_token, DCHECK_EQ(request_type_, NO_PENDING_REQUEST); DCHECK(!request_.get()); request_type_ = USER_ID; - GetUserInfo(oauth_access_token, max_retries, delegate); + PeopleGet(oauth_access_token, max_retries, delegate); } void GaiaOAuthClient::Core::GetUserInfo(const std::string& oauth_access_token, int max_retries, Delegate* delegate) { + DCHECK_EQ(request_type_, NO_PENDING_REQUEST); + DCHECK(!request_.get()); + request_type_ = USER_INFO; + PeopleGet(oauth_access_token, max_retries, delegate); +} + +void GaiaOAuthClient::Core::PeopleGet(const std::string& oauth_access_token, + int max_retries, + Delegate* delegate) { delegate_ = delegate; num_retries_ = 0; request_.reset(net::URLFetcher::Create( - kUrlFetcherId, GURL(GaiaUrls::GetInstance()->oauth_user_info_url()), + kUrlFetcherId, GURL(GaiaUrls::GetInstance()->people_get_url()), net::URLFetcher::GET, this)); request_->SetRequestContext(request_context_getter_.get()); request_->AddExtraRequestHeader("Authorization: OAuth " + oauth_access_token); @@ -282,9 +295,27 @@ void GaiaOAuthClient::Core::HandleResponse( switch (type) { case USER_EMAIL: { - std::string email; - response_dict->GetString("email", &email); - delegate_->OnGetUserEmailResponse(email); + // Use first email of type "account" as the user's email. + const base::ListValue* emails_list; + bool email_found = false; + if (response_dict->GetList("emails", &emails_list)) { + for (size_t i = 0; i < emails_list->GetSize(); ++i) { + const base::DictionaryValue* email_dict; + if (emails_list->GetDictionary(i, &email_dict)) { + std::string email; + std::string type; + if (email_dict->GetString("type", &type) && + type == "account" && + email_dict->GetString("value", &email)) { + delegate_->OnGetUserEmailResponse(email); + email_found = true; + break; + } + } + } + } + if (!email_found) + delegate_->OnNetworkError(net::URLFetcher::RESPONSE_CODE_INVALID); break; } @@ -295,6 +326,11 @@ void GaiaOAuthClient::Core::HandleResponse( break; } + case USER_INFO: { + delegate_->OnGetUserInfoResponse(response_dict.Pass()); + break; + } + case TOKEN_INFO: { delegate_->OnGetTokenInfoResponse(response_dict.Pass()); break; @@ -372,6 +408,12 @@ void GaiaOAuthClient::GetUserId(const std::string& access_token, return core_->GetUserId(access_token, max_retries, delegate); } +void GaiaOAuthClient::GetUserInfo(const std::string& access_token, + int max_retries, + Delegate* delegate) { + return core_->GetUserInfo(access_token, max_retries, delegate); +} + void GaiaOAuthClient::GetTokenInfo(const std::string& access_token, int max_retries, Delegate* delegate) { diff --git a/google_apis/gaia/gaia_oauth_client.h b/google_apis/gaia/gaia_oauth_client.h index 8e01ef6..fd13f46 100644 --- a/google_apis/gaia/gaia_oauth_client.h +++ b/google_apis/gaia/gaia_oauth_client.h @@ -47,6 +47,9 @@ class GaiaOAuthClient { virtual void OnGetUserEmailResponse(const std::string& user_email) {} // Invoked on a successful response to the GetUserId request. virtual void OnGetUserIdResponse(const std::string& user_id) {} + // Invoked on a successful response to the GetUserInfo request. + virtual void OnGetUserInfoResponse( + scoped_ptr<base::DictionaryValue> user_info) {} // Invoked on a successful response to the GetTokenInfo request. virtual void OnGetTokenInfoResponse( scoped_ptr<base::DictionaryValue> token_info) {} @@ -88,7 +91,7 @@ class GaiaOAuthClient { int max_retries, Delegate* delegate); - // Call the userinfo API, returning the user email address associated + // Call the people.get API, returning the user email address associated // with the given access token. The provided access token must have // https://www.googleapis.com/auth/userinfo.email as one of its scopes. // See |max_retries| docs above. @@ -96,14 +99,23 @@ class GaiaOAuthClient { int max_retries, Delegate* delegate); - // Call the userinfo API, returning the user gaia ID associated + // Call the people.get API, returning the user gaia ID associated // with the given access token. The provided access token must have - // https://www.googleapis.com/auth/userinfo as one of its scopes. + // https://www.googleapis.com/auth/userinfo.profile as one of its scopes. // See |max_retries| docs above. void GetUserId(const std::string& oauth_access_token, int max_retries, Delegate* delegate); + // Call the people.get API, returning the user info associated + // with the given access token. The provided access token must have + // https://www.googleapis.com/auth/userinfo.email and + // https://www.googleapis.com/auth/userinfo.profile as its scopes. + // See |max_retries| docs above. + void GetUserInfo(const std::string& oauth_access_token, + int max_retries, + Delegate* delegate); + // Call the tokeninfo API, returning a dictionary of response values. The // provided access token may have any scope, and basic results will be // returned: issued_to, audience, scope, expires_in, access_type. In diff --git a/google_apis/gaia/gaia_oauth_client_unittest.cc b/google_apis/gaia/gaia_oauth_client_unittest.cc index d4014f7..338578e 100644 --- a/google_apis/gaia/gaia_oauth_client_unittest.cc +++ b/google_apis/gaia/gaia_oauth_client_unittest.cc @@ -134,25 +134,22 @@ const std::string kTestUserId = "8675309"; const int kTestExpiresIn = 3920; const std::string kDummyGetTokensResult = - "{\"access_token\":\"" + kTestAccessToken + "\"," - "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "," - "\"refresh_token\":\"" + kTestRefreshToken + "\"}"; + "{\"access_token\":\"" + kTestAccessToken + "\"," + "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "," + "\"refresh_token\":\"" + kTestRefreshToken + "\"}"; const std::string kDummyRefreshTokenResult = - "{\"access_token\":\"" + kTestAccessToken + "\"," - "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}"; - -const std::string kDummyUserInfoResult = - "{\"email\":\"" + kTestUserEmail + "\"}"; + "{\"access_token\":\"" + kTestAccessToken + "\"," + "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}"; const std::string kDummyUserIdResult = - "{\"id\":\"" + kTestUserId + "\"}"; + "{\"id\":\"" + kTestUserId + "\"}"; const std::string kDummyTokenInfoResult = - "{\"issued_to\": \"1234567890.apps.googleusercontent.com\"," - "\"audience\": \"1234567890.apps.googleusercontent.com\"," - "\"scope\": \"https://googleapis.com/oauth2/v2/tokeninfo\"," - "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}"; + "{\"issued_to\": \"1234567890.apps.googleusercontent.com\"," + "\"audience\": \"1234567890.apps.googleusercontent.com\"," + "\"scope\": \"https://googleapis.com/oauth2/v2/tokeninfo\"," + "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}"; } namespace gaia { @@ -304,11 +301,45 @@ TEST_F(GaiaOAuthClientTest, RefreshTokenDownscopingSuccess) { factory.get_url_fetcher()->Finish(); } - TEST_F(GaiaOAuthClientTest, GetUserEmail) { MockGaiaOAuthClientDelegate delegate; EXPECT_CALL(delegate, OnGetUserEmailResponse(kTestUserEmail)).Times(1); + const std::string kDummyUserInfoResult = + "{\"emails\": [{\"value\":\"" + kTestUserEmail + + "\", \"type\":\"account\"}]}"; + + MockOAuthFetcherFactory factory; + factory.set_results(kDummyUserInfoResult); + + GaiaOAuthClient auth(GetRequestContext()); + auth.GetUserEmail("access_token", 1, &delegate); +} + +TEST_F(GaiaOAuthClientTest, GetUserEmailSecondItemValid) { + MockGaiaOAuthClientDelegate delegate; + EXPECT_CALL(delegate, OnGetUserEmailResponse(kTestUserEmail)).Times(1); + + const std::string kDummyUserInfoResult = + "{\"emails\": [{\"value\":\"foo\"}," + "{\"value\":\"" + kTestUserEmail + + "\", \"type\":\"account\"}]}"; + + MockOAuthFetcherFactory factory; + factory.set_results(kDummyUserInfoResult); + + GaiaOAuthClient auth(GetRequestContext()); + auth.GetUserEmail("access_token", 1, &delegate); +} + +TEST_F(GaiaOAuthClientTest, GetUserEmailNoValidItems) { + MockGaiaOAuthClientDelegate delegate; + EXPECT_CALL(delegate, OnNetworkError(_)).Times(1); + + const std::string kDummyUserInfoResult = + "{\"emails\": [{\"value\":\"" + kTestUserEmail + + "\", \"type\":\"foo\"}]}"; + MockOAuthFetcherFactory factory; factory.set_results(kDummyUserInfoResult); diff --git a/google_apis/gaia/gaia_urls.cc b/google_apis/gaia/gaia_urls.cc index 0b44a91..5abff9c 100644 --- a/google_apis/gaia/gaia_urls.cc +++ b/google_apis/gaia/gaia_urls.cc @@ -42,7 +42,7 @@ const char kOAuth2TokenUrlSuffix[] = "o/oauth2/token"; // API calls from www.googleapis.com const char kOAuth2IssueTokenUrlSuffix[] = "oauth2/v2/IssueToken"; const char kOAuth2TokenInfoUrlSuffix[] = "oauth2/v2/tokeninfo"; -const char kOAuthUserInfoUrlSuffix[] = "oauth2/v1/userinfo"; +const char kPeopleGetUrlSuffix[] = "plus/v1/people/me"; void GetSwitchValueWithDefault(const char* switch_value, const char* default_value, @@ -118,8 +118,8 @@ GaiaUrls::GaiaUrls() { google_apis_origin_url_.Resolve(kOAuth2IssueTokenUrlSuffix); oauth2_token_info_url_ = google_apis_origin_url_.Resolve(kOAuth2TokenInfoUrlSuffix); - oauth_user_info_url_ = - google_apis_origin_url_.Resolve(kOAuthUserInfoUrlSuffix); + people_get_url_ = + google_apis_origin_url_.Resolve(kPeopleGetUrlSuffix); gaia_login_form_realm_ = gaia_url_; } @@ -179,8 +179,8 @@ const GURL& GaiaUrls::oauth_wrap_bridge_url() const { return oauth_wrap_bridge_url_; } -const GURL& GaiaUrls::oauth_user_info_url() const { - return oauth_user_info_url_; +const GURL& GaiaUrls::people_get_url() const { + return people_get_url_; } const GURL& GaiaUrls::oauth_revoke_token_url() const { diff --git a/google_apis/gaia/gaia_urls.h b/google_apis/gaia/gaia_urls.h index f96e89c..7a41ebf 100644 --- a/google_apis/gaia/gaia_urls.h +++ b/google_apis/gaia/gaia_urls.h @@ -24,12 +24,12 @@ class GaiaUrls { const GURL& service_logout_url() const; const GURL& issue_auth_token_url() const; const GURL& get_user_info_url() const; + const GURL& people_get_url() const; const GURL& token_auth_url() const; const GURL& merge_session_url() const; const GURL& get_oauth_token_url() const; const GURL& oauth_get_access_token_url() const; const GURL& oauth_wrap_bridge_url() const; - const GURL& oauth_user_info_url() const; const GURL& oauth_revoke_token_url() const; const GURL& oauth1_login_url() const; const GURL& list_accounts_url() const; @@ -65,12 +65,12 @@ class GaiaUrls { GURL service_logout_url_; GURL issue_auth_token_url_; GURL get_user_info_url_; + GURL people_get_url_; GURL token_auth_url_; GURL merge_session_url_; GURL get_oauth_token_url_; GURL oauth_get_access_token_url_; GURL oauth_wrap_bridge_url_; - GURL oauth_user_info_url_; GURL oauth_revoke_token_url_; GURL oauth1_login_url_; GURL list_accounts_url_; |