supervised_user_refresh_token_fetcher.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_refresh_token_fetcher.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/callback.h" 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/json/json_reader.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/values.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "google_apis/gaia/gaia_constants.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "google_apis/gaia/gaia_oauth_client.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "google_apis/gaia/oauth2_api_call_flow.h" 17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "google_apis/gaia/oauth2_token_service.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/base/escape.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/base/load_flags.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/base/net_errors.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/http/http_status_code.h" 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/url_request/url_request_status.h" 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using GaiaConstants::kChromeSyncSupervisedOAuth2Scope; 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::Time; 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using gaia::GaiaOAuthClient; 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using net::URLFetcher; 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using net::URLFetcherDelegate; 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using net::URLRequestContextGetter; 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace { 33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kNumRetries = 1; 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kIssueTokenBodyFormat[] = 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "client_id=%s" 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "&scope=%s" 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "&response_type=code" 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "&profile_id=%s" 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "&device_name=%s"; 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// kIssueTokenBodyFormatDeviceIdAddendum is appended to kIssueTokenBodyFormat 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// if device_id is provided. 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const char kIssueTokenBodyFormatDeviceIdAddendum[] = "&device_id=%s"; 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kAuthorizationHeaderFormat[] = 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Authorization: Bearer %s"; 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char kCodeKey[] = "code"; 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class SupervisedUserRefreshTokenFetcherImpl 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : public SupervisedUserRefreshTokenFetcher, 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public OAuth2TokenService::Consumer, 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public URLFetcherDelegate, 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public GaiaOAuthClient::Delegate { 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SupervisedUserRefreshTokenFetcherImpl( 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OAuth2TokenService* oauth2_token_service, 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& account_id, 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& device_id, 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) URLRequestContextGetter* context); 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual ~SupervisedUserRefreshTokenFetcherImpl(); 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // SupervisedUserRefreshTokenFetcher implementation: 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void Start(const std::string& supervised_user_id, 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& device_name, 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const TokenCallback& callback) OVERRIDE; 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protected: 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // OAuth2TokenService::Consumer implementation: 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& access_token, 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const Time& expiration_time) OVERRIDE; 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const GoogleServiceAuthError& error) OVERRIDE; 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // net::URLFetcherDelegate implementation. 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void OnURLFetchComplete(const URLFetcher* source) OVERRIDE; 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // GaiaOAuthClient::Delegate implementation: 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void OnGetTokensResponse(const std::string& refresh_token, 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& access_token, 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int expires_in_seconds) OVERRIDE; 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void OnRefreshTokenResponse(const std::string& access_token, 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int expires_in_seconds) OVERRIDE; 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void OnOAuthError() OVERRIDE; 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void OnNetworkError(int response_code) OVERRIDE; 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Requests an access token, which is the first thing we need. This is where 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // we restart when the returned access token has expired. 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void StartFetching(); 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void DispatchNetworkError(int error_code); 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void DispatchGoogleServiceAuthError(const GoogleServiceAuthError& error, 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& token); 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) OAuth2TokenService* oauth2_token_service_; 9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string account_id_; 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string device_id_; 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) URLRequestContextGetter* context_; 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string device_name_; 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string supervised_user_id_; 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TokenCallback callback_; 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<OAuth2TokenService::Request> access_token_request_; 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string access_token_; 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool access_token_expired_; 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<URLFetcher> url_fetcher_; 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<GaiaOAuthClient> gaia_oauth_client_; 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserRefreshTokenFetcherImpl::SupervisedUserRefreshTokenFetcherImpl( 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) OAuth2TokenService* oauth2_token_service, 11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& account_id, 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& device_id, 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) URLRequestContextGetter* context) 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : OAuth2TokenService::Consumer("supervised_user"), 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) oauth2_token_service_(oauth2_token_service), 12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) account_id_(account_id), 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_id_(device_id), 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context_(context), 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) access_token_expired_(false) {} 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserRefreshTokenFetcherImpl:: 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)~SupervisedUserRefreshTokenFetcherImpl() {} 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::Start( 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& supervised_user_id, 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& device_name, 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const TokenCallback& callback) { 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(callback_.is_null()); 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) supervised_user_id_ = supervised_user_id; 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) device_name_ = device_name; 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) callback_ = callback; 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) StartFetching(); 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::StartFetching() { 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) OAuth2TokenService::ScopeSet scopes; 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scopes.insert(GaiaConstants::kOAuth1LoginScope); 14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) access_token_request_ = oauth2_token_service_->StartRequest( 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) account_id_, scopes, this); 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::OnGetTokenSuccess( 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const OAuth2TokenService::Request* request, 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& access_token, 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const Time& expiration_time) { 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(access_token_request_.get(), request); 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) access_token_ = access_token; 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GURL url(GaiaUrls::GetInstance()->oauth2_issue_token_url()); 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // GaiaOAuthClient uses id 0, so we use 1 to distinguish the requests in 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // unit tests. 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const int id = 1; 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) url_fetcher_.reset(URLFetcher::Create(id, url, URLFetcher::POST, this)); 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) url_fetcher_->SetRequestContext(context_); 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) net::LOAD_DO_NOT_SAVE_COOKIES); 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(kNumRetries); 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) url_fetcher_->AddExtraRequestHeader( 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str())); 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string body = base::StringPrintf( 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kIssueTokenBodyFormat, 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) net::EscapeUrlEncodedData( 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id(), true).c_str(), 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) net::EscapeUrlEncodedData(kChromeSyncSupervisedOAuth2Scope, true).c_str(), 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) net::EscapeUrlEncodedData(supervised_user_id_, true).c_str(), 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) net::EscapeUrlEncodedData(device_name_, true).c_str()); 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!device_id_.empty()) { 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body.append(base::StringPrintf( 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kIssueTokenBodyFormatDeviceIdAddendum, 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::EscapeUrlEncodedData(device_id_, true).c_str())); 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) url_fetcher_->SetUploadData("application/x-www-form-urlencoded", body); 181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) url_fetcher_->Start(); 183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::OnGetTokenFailure( 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const OAuth2TokenService::Request* request, 187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const GoogleServiceAuthError& error) { 188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(access_token_request_.get(), request); 189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) callback_.Run(error, std::string()); 190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) callback_.Reset(); 191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::OnURLFetchComplete( 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const URLFetcher* source) { 195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const net::URLRequestStatus& status = source->GetStatus(); 196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!status.is_success()) { 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DispatchNetworkError(status.error()); 198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int response_code = source->GetResponseCode(); 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (response_code == net::HTTP_UNAUTHORIZED && !access_token_expired_) { 203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) access_token_expired_ = true; 20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) oauth2_token_service_->InvalidateToken(account_id_, 20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) OAuth2TokenService::ScopeSet(), 206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) access_token_); 207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) StartFetching(); 208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (response_code != net::HTTP_OK) { 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(bauerb): We should return the HTTP response code somehow. 213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DLOG(WARNING) << "HTTP error " << response_code; 214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DispatchGoogleServiceAuthError( 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED), 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string()); 217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string response_body; 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source->GetResponseAsString(&response_body); 222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(response_body)); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* dict = NULL; 224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!value.get() || !value->GetAsDictionary(&dict)) { 225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DispatchNetworkError(net::ERR_INVALID_RESPONSE); 226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string auth_code; 229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!dict->GetString(kCodeKey, &auth_code)) { 230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DispatchNetworkError(net::ERR_INVALID_RESPONSE); 231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gaia::OAuthClientInfo client_info; 235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GaiaUrls* urls = GaiaUrls::GetInstance(); 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) client_info.client_id = urls->oauth2_chrome_client_id(); 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) client_info.client_secret = urls->oauth2_chrome_client_secret(); 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(context_)); 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gaia_oauth_client_->GetTokensFromAuthCode(client_info, auth_code, kNumRetries, 240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) this); 241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::OnGetTokensResponse( 244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& refresh_token, 245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& access_token, 246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int expires_in_seconds) { 247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(bauerb): It would be nice if we could pass the access token as well, 248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // so we don't need to fetch another one immediately. 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DispatchGoogleServiceAuthError(GoogleServiceAuthError::AuthErrorNone(), 250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) refresh_token); 251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::OnRefreshTokenResponse( 254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& access_token, 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int expires_in_seconds) { 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NOTREACHED(); 257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::OnOAuthError() { 260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DispatchGoogleServiceAuthError( 261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED), 262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string()); 263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::OnNetworkError(int response_code) { 266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(bauerb): We should return the HTTP response code somehow. 267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DLOG(WARNING) << "HTTP error " << response_code; 268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DispatchGoogleServiceAuthError( 269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED), 270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string()); 271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::DispatchNetworkError( 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int error_code) { 275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DispatchGoogleServiceAuthError( 276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GoogleServiceAuthError::FromConnectionError(error_code), std::string()); 277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SupervisedUserRefreshTokenFetcherImpl::DispatchGoogleServiceAuthError( 280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const GoogleServiceAuthError& error, 281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& token) { 282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) callback_.Run(error, token); 283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) callback_.Reset(); 284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)scoped_ptr<SupervisedUserRefreshTokenFetcher> 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserRefreshTokenFetcher::Create( 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OAuth2TokenService* oauth2_token_service, 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& account_id, 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& device_id, 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) URLRequestContextGetter* context) { 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<SupervisedUserRefreshTokenFetcher> fetcher( 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new SupervisedUserRefreshTokenFetcherImpl(oauth2_token_service, 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) account_id, 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_id, 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) context)); 300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return fetcher.Pass(); 301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SupervisedUserRefreshTokenFetcher::~SupervisedUserRefreshTokenFetcher() {} 304