gaia_oauth_client.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_oauth_client.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_status_code.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAccessTokenValue[] = "access_token"; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRefreshTokenValue[] = "refresh_token"; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kExpiresInValue[] = "expires_in"; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gaia { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use a non-zero number, so unit tests can differentiate the URLFetcher used by 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// this class from other fetchers (most other code just hardcodes the ID to 0). 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int GaiaOAuthClient::kUrlFetcherId = 17109006; 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GaiaOAuthClient::Core 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public base::RefCountedThreadSafe<GaiaOAuthClient::Core>, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public net::URLFetcherDelegate { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Core(net::URLRequestContextGetter* request_context_getter) 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : num_retries_(0), 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request_context_getter_(request_context_getter), 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_(NULL), 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request_type_(NO_PENDING_REQUEST) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GetTokensFromAuthCode(const OAuthClientInfo& oauth_client_info, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_code, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_retries, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaOAuthClient::Delegate* delegate); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RefreshToken(const OAuthClientInfo& oauth_client_info, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& refresh_token, 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::vector<std::string>& scopes, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_retries, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaOAuthClient::Delegate* delegate); 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void GetUserEmail(const std::string& oauth_access_token, 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int max_retries, 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Delegate* delegate); 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void GetTokenInfo(const std::string& oauth_access_token, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_retries, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // net::URLFetcherDelegate implementation. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<Core>; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum RequestType { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_PENDING_REQUEST, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TOKENS_FROM_AUTH_CODE, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REFRESH_TOKEN, 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TOKEN_INFO, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) USER_INFO, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Core() {} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void MakeGaiaRequest(const GURL& url, 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& post_body, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_retries, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaOAuthClient::Delegate* delegate); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HandleResponse(const net::URLFetcher* source, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* should_retry_request); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_retries_; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaOAuthClient::Delegate* delegate_; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<net::URLFetcher> request_; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestType request_type_; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::GetTokensFromAuthCode( 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OAuthClientInfo& oauth_client_info, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_code, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_retries, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaOAuthClient::Delegate* delegate) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(request_type_, NO_PENDING_REQUEST); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_type_ = TOKENS_FROM_AUTH_CODE; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string post_body = 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "code=" + net::EscapeUrlEncodedData(auth_code, true) + 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "&client_id=" + net::EscapeUrlEncodedData(oauth_client_info.client_id, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true) + 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "&client_secret=" + 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::EscapeUrlEncodedData(oauth_client_info.client_secret, true) + 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "&redirect_uri=" + 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::EscapeUrlEncodedData(oauth_client_info.redirect_uri, true) + 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "&grant_type=authorization_code"; 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MakeGaiaRequest(GURL(GaiaUrls::GetInstance()->oauth2_token_url()), 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch post_body, max_retries, delegate); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::RefreshToken( 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OAuthClientInfo& oauth_client_info, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& refresh_token, 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::vector<std::string>& scopes, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_retries, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaOAuthClient::Delegate* delegate) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(request_type_, NO_PENDING_REQUEST); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_type_ = REFRESH_TOKEN; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string post_body = 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "refresh_token=" + net::EscapeUrlEncodedData(refresh_token, true) + 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "&client_id=" + net::EscapeUrlEncodedData(oauth_client_info.client_id, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true) + 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "&client_secret=" + 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::EscapeUrlEncodedData(oauth_client_info.client_secret, true) + 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "&grant_type=refresh_token"; 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!scopes.empty()) { 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string scopes_string = JoinString(scopes, ' '); 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch post_body += "&scope=" + net::EscapeUrlEncodedData(scopes_string, true); 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MakeGaiaRequest(GURL(GaiaUrls::GetInstance()->oauth2_token_url()), 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch post_body, max_retries, delegate); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid GaiaOAuthClient::Core::GetUserEmail(const std::string& oauth_access_token, 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int max_retries, 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Delegate* delegate) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(request_type_, NO_PENDING_REQUEST); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!request_.get()); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_type_ = USER_INFO; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_ = delegate; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_retries_ = 0; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.reset(net::URLFetcher::Create( 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kUrlFetcherId, GURL(GaiaUrls::GetInstance()->oauth_user_info_url()), 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher::GET, this)); 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_->SetRequestContext(request_context_getter_.get()); 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_->AddExtraRequestHeader("Authorization: OAuth " + oauth_access_token); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_->SetMaxRetriesOn5xx(max_retries); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Fetchers are sometimes cancelled because a network change was detected, 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // especially at startup and after sign-in on ChromeOS. Retrying once should 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // be enough in those cases; let the fetcher retry up to 3 times just in case. 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // http://crbug.com/163710 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_->SetAutomaticallyRetryOnNetworkChanges(3); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->Start(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid GaiaOAuthClient::Core::GetTokenInfo(const std::string& oauth_access_token, 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int max_retries, 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Delegate* delegate) { 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_EQ(request_type_, NO_PENDING_REQUEST); 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!request_.get()); 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request_type_ = TOKEN_INFO; 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string post_body = 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "access_token=" + net::EscapeUrlEncodedData(oauth_access_token, true); 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MakeGaiaRequest(GURL(GaiaUrls::GetInstance()->oauth2_token_info_url()), 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch post_body, 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch max_retries, 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate); 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::MakeGaiaRequest( 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const GURL& url, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& post_body, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_retries, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaOAuthClient::Delegate* delegate) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!request_.get()) << "Tried to fetch two things at once!"; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_ = delegate; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_retries_ = 0; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.reset(net::URLFetcher::Create( 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kUrlFetcherId, url, net::URLFetcher::POST, this)); 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_->SetRequestContext(request_context_getter_.get()); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->SetUploadData("application/x-www-form-urlencoded", post_body); 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_->SetMaxRetriesOn5xx(max_retries); 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See comment on SetAutomaticallyRetryOnNetworkChanges() above. 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_->SetAutomaticallyRetryOnNetworkChanges(3); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->Start(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// URLFetcher::Delegate implementation. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::OnURLFetchComplete( 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLFetcher* source) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool should_retry = false; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleResponse(source, &should_retry); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (should_retry) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Explicitly call ReceivedContentWasMalformed() to ensure the current 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // request gets counted as a failure for calculation of the back-off 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // period. If it was already a failure by status code, this call will 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be ignored. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->ReceivedContentWasMalformed(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_retries_++; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We must set our request_context_getter_ again because 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URLFetcher::Core::RetryOrCompleteUrlFetch resets it to NULL... 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_->SetRequestContext(request_context_getter_.get()); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_->Start(); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::HandleResponse( 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLFetcher* source, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* should_retry_request) { 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Move ownership of the request fetcher into a local scoped_ptr which 211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // will be nuked when we're done handling the request, unless we need 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // to retry, in which case ownership will be returned to request_. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<net::URLFetcher> old_request = request_.Pass(); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(source, old_request.get()); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RC_BAD_REQUEST means the arguments are invalid. No point retrying. We are 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // done here. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source->GetResponseCode() == net::HTTP_BAD_REQUEST) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnOAuthError(); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::DictionaryValue> response_dict; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source->GetResponseCode() == net::HTTP_OK) { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string data; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source->GetResponseAsString(&data); 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::Value> message_value(base::JSONReader::Read(data)); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message_value.get() && 229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message_value->IsType(base::Value::TYPE_DICTIONARY)) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_dict.reset( 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static_cast<base::DictionaryValue*>(message_value.release())); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response_dict.get()) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have an access token yet and the the error was not 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RC_BAD_REQUEST, we may need to retry. 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((source->GetMaxRetriesOn5xx() != -1) && 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (num_retries_ >= source->GetMaxRetriesOn5xx())) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retry limit reached. Give up. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnNetworkError(source->GetResponseCode()); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_ = old_request.Pass(); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *should_retry_request = true; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestType type = request_type_; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_type_ = NO_PENDING_REQUEST; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case USER_INFO: { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string email; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_dict->GetString("email", &email); 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->OnGetUserEmailResponse(email); 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case TOKEN_INFO: { 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->OnGetTokenInfoResponse(response_dict.Pass()); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TOKENS_FROM_AUTH_CODE: 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case REFRESH_TOKEN: { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string access_token; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string refresh_token; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int expires_in_seconds = 0; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_dict->GetString(kAccessTokenValue, &access_token); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_dict->GetString(kRefreshTokenValue, &refresh_token); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_dict->GetInteger(kExpiresInValue, &expires_in_seconds); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (access_token.empty()) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnOAuthError(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == REFRESH_TOKEN) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnRefreshTokenResponse(access_token, expires_in_seconds); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->OnGetTokensResponse(refresh_token, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) access_token, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expires_in_seconds); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochGaiaOAuthClient::GaiaOAuthClient(net::URLRequestContextGetter* context_getter) { 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch core_ = new Core(context_getter); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GaiaOAuthClient::~GaiaOAuthClient() { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::GetTokensFromAuthCode( 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OAuthClientInfo& oauth_client_info, 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_code, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_retries, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return core_->GetTokensFromAuthCode(oauth_client_info, 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_code, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_retries, 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid GaiaOAuthClient::RefreshToken( 313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const OAuthClientInfo& oauth_client_info, 314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& refresh_token, 315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::vector<std::string>& scopes, 316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int max_retries, 317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Delegate* delegate) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return core_->RefreshToken(oauth_client_info, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) refresh_token, 320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scopes, 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_retries, 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid GaiaOAuthClient::GetUserEmail(const std::string& access_token, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_retries, 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate) { 328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return core_->GetUserEmail(access_token, max_retries, delegate); 329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid GaiaOAuthClient::GetTokenInfo(const std::string& access_token, 332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int max_retries, 333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Delegate* delegate) { 334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return core_->GetTokenInfo(access_token, max_retries, delegate); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gaia 338