Index: chrome/browser/net/gaia/gaia_oauth_fetcher.cc |
diff --git a/chrome/browser/net/gaia/gaia_oauth_fetcher.cc b/chrome/browser/net/gaia/gaia_oauth_fetcher.cc |
deleted file mode 100644 |
index 4a8f537394fc09b85a12443ab864d3ef045f7735..0000000000000000000000000000000000000000 |
--- a/chrome/browser/net/gaia/gaia_oauth_fetcher.cc |
+++ /dev/null |
@@ -1,565 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/net/gaia/gaia_oauth_fetcher.h" |
- |
-#include <string> |
-#include <utility> |
-#include <vector> |
- |
-#include "base/json/json_reader.h" |
-#include "base/strings/string_split.h" |
-#include "base/strings/string_util.h" |
-#include "base/values.h" |
-#include "chrome/browser/net/gaia/gaia_oauth_consumer.h" |
-#include "google_apis/gaia/gaia_auth_fetcher.h" |
-#include "google_apis/gaia/gaia_constants.h" |
-#include "google_apis/gaia/gaia_urls.h" |
-#include "google_apis/gaia/oauth_request_signer.h" |
-#include "grit/chromium_strings.h" |
-#include "net/base/load_flags.h" |
-#include "net/cookies/parsed_cookie.h" |
-#include "net/http/http_status_code.h" |
-#include "net/url_request/url_fetcher.h" |
-#include "net/url_request/url_request_context_getter.h" |
-#include "net/url_request/url_request_status.h" |
-#include "ui/base/l10n/l10n_util.h" |
- |
-static const char kOAuthTokenCookie[] = "oauth_token"; |
- |
-GaiaOAuthFetcher::GaiaOAuthFetcher(GaiaOAuthConsumer* consumer, |
- net::URLRequestContextGetter* getter, |
- const std::string& service_scope) |
- : consumer_(consumer), |
- getter_(getter), |
- service_scope_(service_scope), |
- fetch_pending_(false), |
- auto_fetch_limit_(USER_INFO) {} |
- |
-GaiaOAuthFetcher::~GaiaOAuthFetcher() {} |
- |
-bool GaiaOAuthFetcher::HasPendingFetch() const { |
- return fetch_pending_; |
-} |
- |
-void GaiaOAuthFetcher::CancelRequest() { |
- fetcher_.reset(); |
- fetch_pending_ = false; |
-} |
- |
-// static |
-net::URLFetcher* GaiaOAuthFetcher::CreateGaiaFetcher( |
- net::URLRequestContextGetter* getter, |
- const GURL& gaia_gurl, |
- const std::string& body, |
- const std::string& headers, |
- bool send_cookies, |
- net::URLFetcherDelegate* delegate) { |
- bool empty_body = body.empty(); |
- net::URLFetcher* result = net::URLFetcher::Create( |
- 0, gaia_gurl, |
- empty_body ? net::URLFetcher::GET : net::URLFetcher::POST, |
- delegate); |
- result->SetRequestContext(getter); |
- // Fetchers are sometimes cancelled because a network change was detected, |
- // especially at startup and after sign-in on ChromeOS. Retrying once should |
- // be enough in those cases; let the fetcher retry up to 3 times just in case. |
- // http://crbug.com/163710 |
- result->SetAutomaticallyRetryOnNetworkChanges(3); |
- |
- // The Gaia/OAuth token exchange requests do not require any cookie-based |
- // identification as part of requests. We suppress sending any cookies to |
- // maintain a separation between the user's browsing and Chrome's internal |
- // services. Where such mixing is desired (prelogin, autologin |
- // or chromeos login), it will be done explicitly. |
- if (!send_cookies) |
- result->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES); |
- |
- if (!empty_body) |
- result->SetUploadData("application/x-www-form-urlencoded", body); |
- if (!headers.empty()) |
- result->SetExtraRequestHeaders(headers); |
- |
- return result; |
-} |
- |
-// static |
-GURL GaiaOAuthFetcher::MakeGetOAuthTokenUrl( |
- const std::string& oauth1_login_scope, |
- const std::string& product_name) { |
- return GaiaUrls::GetInstance()->get_oauth_token_url().Resolve( |
- "?scope=" + oauth1_login_scope + |
- "&xoauth_display_name=" + |
- OAuthRequestSigner::Encode(product_name)); |
-} |
- |
-// static |
-std::string GaiaOAuthFetcher::MakeOAuthLoginBody( |
- const char* source, |
- const char* service, |
- const std::string& oauth1_access_token, |
- const std::string& oauth1_access_token_secret) { |
- OAuthRequestSigner::Parameters parameters; |
- parameters["service"] = service; |
- parameters["source"] = source; |
- std::string signed_request; |
- bool is_signed = OAuthRequestSigner::SignURL( |
- GaiaUrls::GetInstance()->oauth1_login_url(), |
- parameters, |
- OAuthRequestSigner::HMAC_SHA1_SIGNATURE, |
- OAuthRequestSigner::POST_METHOD, |
- "anonymous", // oauth_consumer_key |
- "anonymous", // consumer secret |
- oauth1_access_token, // oauth_token |
- oauth1_access_token_secret, // token secret |
- &signed_request); |
- DCHECK(is_signed); |
- return signed_request; |
-} |
- |
-// static |
-std::string GaiaOAuthFetcher::MakeOAuthGetAccessTokenBody( |
- const std::string& oauth1_request_token) { |
- OAuthRequestSigner::Parameters empty_parameters; |
- std::string signed_request; |
- bool is_signed = OAuthRequestSigner::SignURL( |
- GaiaUrls::GetInstance()->oauth_get_access_token_url(), |
- empty_parameters, |
- OAuthRequestSigner::HMAC_SHA1_SIGNATURE, |
- OAuthRequestSigner::POST_METHOD, |
- "anonymous", // oauth_consumer_key |
- "anonymous", // consumer secret |
- oauth1_request_token, // oauth_token |
- "", // token secret |
- &signed_request); |
- DCHECK(is_signed); |
- return signed_request; |
-} |
- |
-// static |
-std::string GaiaOAuthFetcher::MakeOAuthWrapBridgeBody( |
- const std::string& oauth1_access_token, |
- const std::string& oauth1_access_token_secret, |
- const std::string& wrap_token_duration, |
- const std::string& oauth2_scope) { |
- OAuthRequestSigner::Parameters parameters; |
- parameters["wrap_token_duration"] = wrap_token_duration; |
- parameters["wrap_scope"] = oauth2_scope; |
- std::string signed_request; |
- bool is_signed = OAuthRequestSigner::SignURL( |
- GaiaUrls::GetInstance()->oauth_wrap_bridge_url(), |
- parameters, |
- OAuthRequestSigner::HMAC_SHA1_SIGNATURE, |
- OAuthRequestSigner::POST_METHOD, |
- "anonymous", // oauth_consumer_key |
- "anonymous", // consumer secret |
- oauth1_access_token, // oauth_token |
- oauth1_access_token_secret, // token secret |
- &signed_request); |
- DCHECK(is_signed); |
- return signed_request; |
-} |
- |
-// Helper method that extracts tokens from a successful reply. |
-// static |
-void GaiaOAuthFetcher::ParseOAuthLoginResponse( |
- const std::string& data, |
- std::string* sid, |
- std::string* lsid, |
- std::string* auth) { |
- using std::vector; |
- using std::pair; |
- using std::string; |
- vector<pair<string, string> > tokens; |
- base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); |
- for (vector<pair<string, string> >::iterator i = tokens.begin(); |
- i != tokens.end(); ++i) { |
- if (i->first == "SID") { |
- *sid = i->second; |
- } else if (i->first == "LSID") { |
- *lsid = i->second; |
- } else if (i->first == "Auth") { |
- *auth = i->second; |
- } |
- } |
-} |
- |
-// Helper method that extracts tokens from a successful reply. |
-// static |
-void GaiaOAuthFetcher::ParseOAuthGetAccessTokenResponse( |
- const std::string& data, |
- std::string* token, |
- std::string* secret) { |
- using std::vector; |
- using std::pair; |
- using std::string; |
- |
- vector<pair<string, string> > tokens; |
- base::SplitStringIntoKeyValuePairs(data, '=', '&', &tokens); |
- for (vector<pair<string, string> >::iterator i = tokens.begin(); |
- i != tokens.end(); ++i) { |
- if (i->first == "oauth_token") { |
- std::string decoded; |
- if (OAuthRequestSigner::Decode(i->second, &decoded)) |
- token->assign(decoded); |
- } else if (i->first == "oauth_token_secret") { |
- std::string decoded; |
- if (OAuthRequestSigner::Decode(i->second, &decoded)) |
- secret->assign(decoded); |
- } |
- } |
-} |
- |
-// Helper method that extracts tokens from a successful reply. |
-// static |
-void GaiaOAuthFetcher::ParseOAuthWrapBridgeResponse(const std::string& data, |
- std::string* token, |
- std::string* expires_in) { |
- using std::vector; |
- using std::pair; |
- using std::string; |
- |
- vector<pair<string, string> > tokens; |
- base::SplitStringIntoKeyValuePairs(data, '=', '&', &tokens); |
- for (vector<pair<string, string> >::iterator i = tokens.begin(); |
- i != tokens.end(); ++i) { |
- if (i->first == "wrap_access_token") { |
- std::string decoded; |
- if (OAuthRequestSigner::Decode(i->second, &decoded)) |
- token->assign(decoded); |
- } else if (i->first == "wrap_access_token_expires_in") { |
- std::string decoded; |
- if (OAuthRequestSigner::Decode(i->second, &decoded)) |
- expires_in->assign(decoded); |
- } |
- } |
-} |
- |
-// Helper method that extracts tokens from a successful reply. |
-// static |
-void GaiaOAuthFetcher::ParseUserInfoResponse(const std::string& data, |
- std::string* email_result) { |
- scoped_ptr<base::Value> value(base::JSONReader::Read(data)); |
- if (value->GetType() == base::Value::TYPE_DICTIONARY) { |
- base::Value* email_value; |
- base::DictionaryValue* dict = |
- static_cast<base::DictionaryValue*>(value.get()); |
- if (dict->Get("email", &email_value)) { |
- if (email_value->GetType() == base::Value::TYPE_STRING) { |
- email_value->GetAsString(email_result); |
- } |
- } |
- } |
-} |
- |
-void GaiaOAuthFetcher::StartOAuthLogin( |
- const char* source, |
- const char* service, |
- const std::string& oauth1_access_token, |
- const std::string& oauth1_access_token_secret) { |
- DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; |
- |
- request_type_ = OAUTH1_LOGIN; |
- // Must outlive fetcher_. |
- request_body_ = MakeOAuthLoginBody(source, service, oauth1_access_token, |
- oauth1_access_token_secret); |
- request_headers_ = ""; |
- GURL url(GaiaUrls::GetInstance()->oauth1_login_url()); |
- fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_, |
- request_headers_, false, this)); |
- fetch_pending_ = true; |
- fetcher_->Start(); |
-} |
- |
-void GaiaOAuthFetcher::StartGetOAuthTokenRequest() { |
- DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; |
- |
- request_type_ = OAUTH1_REQUEST_TOKEN; |
- // Must outlive fetcher_. |
- request_body_ = ""; |
- request_headers_ = ""; |
- fetcher_.reset(CreateGaiaFetcher(getter_, |
- MakeGetOAuthTokenUrl(GaiaUrls::GetInstance()->oauth1_login_scope(), |
- l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)), |
- std::string(), |
- std::string(), |
- true, // send_cookies |
- this)); |
- fetch_pending_ = true; |
- fetcher_->Start(); |
-} |
- |
-void GaiaOAuthFetcher::StartOAuthGetAccessToken( |
- const std::string& oauth1_request_token) { |
- DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; |
- |
- request_type_ = OAUTH1_ALL_ACCESS_TOKEN; |
- // Must outlive fetcher_. |
- request_body_ = MakeOAuthGetAccessTokenBody(oauth1_request_token); |
- request_headers_ = ""; |
- GURL url(GaiaUrls::GetInstance()->oauth_get_access_token_url()); |
- fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_, |
- request_headers_, false, this)); |
- fetch_pending_ = true; |
- fetcher_->Start(); |
-} |
- |
-void GaiaOAuthFetcher::StartOAuthWrapBridge( |
- const std::string& oauth1_access_token, |
- const std::string& oauth1_access_token_secret, |
- const std::string& wrap_token_duration, |
- const std::string& service_scope) { |
- DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; |
- |
- request_type_ = OAUTH2_SERVICE_ACCESS_TOKEN; |
- VLOG(1) << "Starting OAuthWrapBridge for: " << service_scope; |
- std::string combined_scope = service_scope + " " + |
- GaiaUrls::GetInstance()->oauth_wrap_bridge_user_info_scope(); |
- service_scope_ = service_scope; |
- |
- // Must outlive fetcher_. |
- request_body_ = MakeOAuthWrapBridgeBody( |
- oauth1_access_token, |
- oauth1_access_token_secret, |
- wrap_token_duration, |
- combined_scope); |
- |
- request_headers_ = ""; |
- GURL url(GaiaUrls::GetInstance()->oauth_wrap_bridge_url()); |
- fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_, |
- request_headers_, false, this)); |
- fetch_pending_ = true; |
- fetcher_->Start(); |
-} |
- |
-void GaiaOAuthFetcher::StartUserInfo(const std::string& oauth2_access_token) { |
- DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; |
- |
- request_type_ = USER_INFO; |
- // Must outlive fetcher_. |
- request_body_ = ""; |
- request_headers_ = "Authorization: OAuth " + oauth2_access_token; |
- GURL url(GaiaUrls::GetInstance()->oauth_user_info_url()); |
- fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_, |
- request_headers_, false, this)); |
- fetch_pending_ = true; |
- fetcher_->Start(); |
-} |
- |
-void GaiaOAuthFetcher::StartOAuthRevokeAccessToken(const std::string& token, |
- const std::string& secret) { |
- DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; |
- |
- request_type_ = OAUTH2_REVOKE_TOKEN; |
- // Must outlive fetcher_. |
- request_body_ = ""; |
- |
- OAuthRequestSigner::Parameters empty_parameters; |
- std::string auth_header; |
- bool is_signed = OAuthRequestSigner::SignAuthHeader( |
- GaiaUrls::GetInstance()->oauth_revoke_token_url(), |
- empty_parameters, |
- OAuthRequestSigner::HMAC_SHA1_SIGNATURE, |
- OAuthRequestSigner::GET_METHOD, |
- "anonymous", |
- "anonymous", |
- token, |
- secret, |
- &auth_header); |
- DCHECK(is_signed); |
- request_headers_ = "Authorization: " + auth_header; |
- GURL url(GaiaUrls::GetInstance()->oauth_revoke_token_url()); |
- fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_, |
- request_headers_, false, this)); |
- fetch_pending_ = true; |
- fetcher_->Start(); |
-} |
- |
-void GaiaOAuthFetcher::StartOAuthRevokeWrapToken(const std::string& token) { |
- DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; |
- |
- request_type_ = OAUTH2_REVOKE_TOKEN; |
- // Must outlive fetcher_. |
- request_body_ = ""; |
- |
- request_headers_ = "Authorization: Bearer " + token; |
- GURL url(GaiaUrls::GetInstance()->oauth_revoke_token_url()); |
- fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_, |
- request_headers_, false, this)); |
- fetch_pending_ = true; |
- fetcher_->Start(); |
-} |
- |
-// static |
-GoogleServiceAuthError GaiaOAuthFetcher::GenerateAuthError( |
- const std::string& data, |
- const net::URLRequestStatus& status, |
- int response_code) { |
- if (!status.is_success()) { |
- if (status.status() == net::URLRequestStatus::CANCELED) { |
- return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); |
- } else { |
- LOG(WARNING) << "Could not reach Google Accounts servers: errno " |
- << status.error(); |
- return GoogleServiceAuthError::FromConnectionError(status.error()); |
- } |
- } else { |
- LOG(WARNING) << "Unrecognized response from Google Accounts servers " |
- << "code " << response_code << " data " << data; |
- return GoogleServiceAuthError( |
- GoogleServiceAuthError::SERVICE_UNAVAILABLE); |
- } |
- |
- NOTREACHED(); |
- return GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE); |
-} |
- |
-void GaiaOAuthFetcher::OnGetOAuthTokenUrlFetched( |
- const net::ResponseCookies& cookies, |
- const net::URLRequestStatus& status, |
- int response_code) { |
- if (status.is_success() && response_code == net::HTTP_OK) { |
- for (net::ResponseCookies::const_iterator iter = cookies.begin(); |
- iter != cookies.end(); ++iter) { |
- net::ParsedCookie cookie(*iter); |
- if (cookie.Name() == kOAuthTokenCookie) { |
- std::string token = cookie.Value(); |
- consumer_->OnGetOAuthTokenSuccess(token); |
- if (ShouldAutoFetch(OAUTH1_ALL_ACCESS_TOKEN)) |
- StartOAuthGetAccessToken(token); |
- return; |
- } |
- } |
- } |
- consumer_->OnGetOAuthTokenFailure( |
- GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); |
-} |
- |
-void GaiaOAuthFetcher::OnOAuthLoginFetched( |
- const std::string& data, |
- const net::URLRequestStatus& status, |
- int response_code) { |
- if (status.is_success() && response_code == net::HTTP_OK) { |
- std::string sid; |
- std::string lsid; |
- std::string auth; |
- ParseOAuthLoginResponse(data, &sid, &lsid, &auth); |
- if (!sid.empty() && !lsid.empty() && !auth.empty()) { |
- consumer_->OnOAuthLoginSuccess(sid, lsid, auth); |
- return; |
- } |
- } |
- // OAuthLogin returns error messages that are identical to ClientLogin, |
- // so we use GaiaAuthFetcher::GenerateAuthError to parse the response |
- // instead. |
- consumer_->OnOAuthLoginFailure( |
- GaiaAuthFetcher::GenerateOAuthLoginError(data, status)); |
-} |
- |
-void GaiaOAuthFetcher::OnOAuthGetAccessTokenFetched( |
- const std::string& data, |
- const net::URLRequestStatus& status, |
- int response_code) { |
- if (status.is_success() && response_code == net::HTTP_OK) { |
- VLOG(1) << "OAuth1 access token fetched."; |
- std::string secret; |
- std::string token; |
- ParseOAuthGetAccessTokenResponse(data, &token, &secret); |
- if (!token.empty() && !secret.empty()) { |
- consumer_->OnOAuthGetAccessTokenSuccess(token, secret); |
- if (ShouldAutoFetch(OAUTH2_SERVICE_ACCESS_TOKEN)) |
- StartOAuthWrapBridge( |
- token, secret, GaiaConstants::kGaiaOAuthDuration, service_scope_); |
- return; |
- } |
- } |
- consumer_->OnOAuthGetAccessTokenFailure(GenerateAuthError(data, status, |
- response_code)); |
-} |
- |
-void GaiaOAuthFetcher::OnOAuthWrapBridgeFetched( |
- const std::string& data, |
- const net::URLRequestStatus& status, |
- int response_code) { |
- if (status.is_success() && response_code == net::HTTP_OK) { |
- VLOG(1) << "OAuth2 access token fetched."; |
- std::string token; |
- std::string expires_in; |
- ParseOAuthWrapBridgeResponse(data, &token, &expires_in); |
- if (!token.empty() && !expires_in.empty()) { |
- consumer_->OnOAuthWrapBridgeSuccess(service_scope_, token, expires_in); |
- if (ShouldAutoFetch(USER_INFO)) |
- StartUserInfo(token); |
- return; |
- } |
- } |
- consumer_->OnOAuthWrapBridgeFailure(service_scope_, |
- GenerateAuthError(data, status, |
- response_code)); |
-} |
- |
-void GaiaOAuthFetcher::OnOAuthRevokeTokenFetched( |
- const std::string& data, |
- const net::URLRequestStatus& status, |
- int response_code) { |
- if (status.is_success() && response_code == net::HTTP_OK) { |
- consumer_->OnOAuthRevokeTokenSuccess(); |
- } else { |
- LOG(ERROR) << "Token revocation failure " << response_code << ": " << data; |
- consumer_->OnOAuthRevokeTokenFailure(GenerateAuthError(data, status, |
- response_code)); |
- } |
-} |
- |
-void GaiaOAuthFetcher::OnUserInfoFetched( |
- const std::string& data, |
- const net::URLRequestStatus& status, |
- int response_code) { |
- if (status.is_success() && response_code == net::HTTP_OK) { |
- std::string email; |
- ParseUserInfoResponse(data, &email); |
- if (!email.empty()) { |
- VLOG(1) << "GAIA user info fetched for " << email << "."; |
- consumer_->OnUserInfoSuccess(email); |
- return; |
- } |
- } |
- consumer_->OnUserInfoFailure(GenerateAuthError(data, status, |
- response_code)); |
-} |
- |
-void GaiaOAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) { |
- // Keep |fetcher_| around to avoid invalidating its |status| (accessed below). |
- scoped_ptr<net::URLFetcher> current_fetcher(fetcher_.release()); |
- fetch_pending_ = false; |
- std::string data; |
- source->GetResponseAsString(&data); |
- net::URLRequestStatus status = source->GetStatus(); |
- int response_code = source->GetResponseCode(); |
- |
- switch (request_type_) { |
- case OAUTH1_LOGIN: |
- OnOAuthLoginFetched(data, status, response_code); |
- break; |
- case OAUTH1_REQUEST_TOKEN: |
- OnGetOAuthTokenUrlFetched(source->GetCookies(), status, response_code); |
- break; |
- case OAUTH1_ALL_ACCESS_TOKEN: |
- OnOAuthGetAccessTokenFetched(data, status, response_code); |
- break; |
- case OAUTH2_SERVICE_ACCESS_TOKEN: |
- OnOAuthWrapBridgeFetched(data, status, response_code); |
- break; |
- case USER_INFO: |
- OnUserInfoFetched(data, status, response_code); |
- break; |
- case OAUTH2_REVOKE_TOKEN: |
- OnOAuthRevokeTokenFetched(data, status, response_code); |
- break; |
- } |
-} |
- |
-bool GaiaOAuthFetcher::ShouldAutoFetch(RequestType fetch_step) { |
- return fetch_step <= auto_fetch_limit_; |
-} |