OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "remoting/test/access_token_fetcher.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/logging.h" |
| 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/thread_task_runner_handle.h" |
| 11 #include "google_apis/gaia/gaia_constants.h" |
| 12 #include "google_apis/google_api_keys.h" |
| 13 #include "net/url_request/url_fetcher.h" |
| 14 #include "remoting/base/url_request_context_getter.h" |
| 15 |
| 16 namespace { |
| 17 const int kMaxGetTokensRetries = 3; |
| 18 const char kOauthRedirectUrl[] = |
| 19 "https://chromoting-oauth.talkgadget." |
| 20 "google.com/talkgadget/oauth/chrome-remote-desktop/dev"; |
| 21 |
| 22 // Populate a vector with the required permissions for app remoting. |
| 23 const std::vector<std::string> kAppRemotingScopeVector = { |
| 24 "https://www.googleapis.com/auth/appremoting.runapplication", |
| 25 "https://www.googleapis.com/auth/googletalk", |
| 26 "https://www.googleapis.com/auth/userinfo.email", |
| 27 "https://docs.google.com/feeds", |
| 28 "https://www.googleapis.com/auth/drive" |
| 29 }; |
| 30 } |
| 31 |
| 32 namespace remoting { |
| 33 namespace test { |
| 34 |
| 35 AccessTokenFetcher::AccessTokenFetcher() { |
| 36 oauth_client_info_ = { |
| 37 google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING), |
| 38 google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING), |
| 39 kOauthRedirectUrl}; |
| 40 } |
| 41 |
| 42 AccessTokenFetcher::~AccessTokenFetcher() { |
| 43 } |
| 44 |
| 45 void AccessTokenFetcher::GetAccessTokenFromAuthCode( |
| 46 const std::string& auth_code, |
| 47 const AccessTokenCallback& callback) { |
| 48 DCHECK(!auth_code.empty()); |
| 49 DCHECK(!callback.is_null()); |
| 50 DCHECK(access_token_callback_.is_null()); |
| 51 |
| 52 DVLOG(2) << "Calling GetTokensFromAuthCode to exchange auth_code for token"; |
| 53 |
| 54 access_token_.clear(); |
| 55 refresh_token_.clear(); |
| 56 access_token_callback_ = callback; |
| 57 |
| 58 // Create a new GaiaOAuthClient for each request to GAIA. |
| 59 CreateNewGaiaOAuthClientInstance(); |
| 60 auth_client_->GetTokensFromAuthCode( |
| 61 oauth_client_info_, auth_code, kMaxGetTokensRetries, |
| 62 this); // GaiaOAuthClient::Delegate* delegate |
| 63 } |
| 64 |
| 65 void AccessTokenFetcher::GetAccessTokenFromRefreshToken( |
| 66 const std::string& refresh_token, |
| 67 const AccessTokenCallback& callback) { |
| 68 DCHECK(!refresh_token.empty()); |
| 69 DCHECK(!callback.is_null()); |
| 70 DCHECK(access_token_callback_.is_null()); |
| 71 |
| 72 DVLOG(2) << "Calling RefreshToken to generate a new access token"; |
| 73 |
| 74 access_token_.clear(); |
| 75 refresh_token_ = refresh_token; |
| 76 access_token_callback_ = callback; |
| 77 |
| 78 // Create a new GaiaOAuthClient for each request to GAIA. |
| 79 CreateNewGaiaOAuthClientInstance(); |
| 80 auth_client_->RefreshToken( |
| 81 oauth_client_info_, |
| 82 refresh_token_, |
| 83 kAppRemotingScopeVector, |
| 84 kMaxGetTokensRetries, |
| 85 this); // GaiaOAuthClient::Delegate* delegate |
| 86 } |
| 87 |
| 88 void AccessTokenFetcher::CreateNewGaiaOAuthClientInstance() { |
| 89 scoped_refptr<remoting::URLRequestContextGetter> request_context_getter; |
| 90 request_context_getter = new remoting::URLRequestContextGetter( |
| 91 base::ThreadTaskRunnerHandle::Get(), // network_runner |
| 92 base::ThreadTaskRunnerHandle::Get()); // file_runner |
| 93 |
| 94 auth_client_.reset(new gaia::GaiaOAuthClient(request_context_getter.get())); |
| 95 } |
| 96 |
| 97 void AccessTokenFetcher::OnGetTokensResponse(const std::string& refresh_token, |
| 98 const std::string& access_token, |
| 99 int expires_in_seconds) { |
| 100 DVLOG(1) << "AccessTokenFetcher::OnGetTokensResponse() Called"; |
| 101 DVLOG(1) << "--refresh_token: " << refresh_token; |
| 102 DVLOG(1) << "--access_token: " << access_token; |
| 103 DVLOG(1) << "--expires_in_seconds: " << expires_in_seconds; |
| 104 |
| 105 refresh_token_ = refresh_token; |
| 106 access_token_ = access_token; |
| 107 |
| 108 ValidateAccessToken(); |
| 109 } |
| 110 |
| 111 void AccessTokenFetcher::OnRefreshTokenResponse(const std::string& access_token, |
| 112 int expires_in_seconds) { |
| 113 DVLOG(1) << "AccessTokenFetcher::OnRefreshTokenResponse() Called"; |
| 114 DVLOG(1) << "--access_token: " << access_token; |
| 115 DVLOG(1) << "--expires_in_seconds: " << expires_in_seconds; |
| 116 |
| 117 access_token_ = access_token; |
| 118 |
| 119 ValidateAccessToken(); |
| 120 } |
| 121 |
| 122 void AccessTokenFetcher::OnGetUserEmailResponse(const std::string& user_email) { |
| 123 // This callback should not be called as we do not request the user's email. |
| 124 NOTREACHED(); |
| 125 } |
| 126 |
| 127 void AccessTokenFetcher::OnGetUserIdResponse(const std::string& user_id) { |
| 128 // This callback should not be called as we do not request the user's id. |
| 129 NOTREACHED(); |
| 130 } |
| 131 |
| 132 void AccessTokenFetcher::OnGetUserInfoResponse( |
| 133 scoped_ptr<base::DictionaryValue> user_info) { |
| 134 // This callback should not be called as we do not request user info. |
| 135 NOTREACHED(); |
| 136 } |
| 137 |
| 138 void AccessTokenFetcher::OnGetTokenInfoResponse( |
| 139 scoped_ptr<base::DictionaryValue> token_info) { |
| 140 DVLOG(1) << "AccessTokenFetcher::OnGetTokenInfoResponse() Called"; |
| 141 |
| 142 std::string error_string; |
| 143 std::string error_description; |
| 144 |
| 145 // Check to see if the token_info we received had any errors, |
| 146 // otherwise we will assume that it is valid for our purposes. |
| 147 if (token_info->HasKey("error")) { |
| 148 token_info->GetString("error", &error_string); |
| 149 token_info->GetString("error_description", &error_description); |
| 150 |
| 151 LOG(ERROR) << "OnGetTokenInfoResponse returned an error. " |
| 152 << ", " |
| 153 << "error: " << error_string << ", " |
| 154 << "description: " << error_description; |
| 155 access_token_.clear(); |
| 156 refresh_token_.clear(); |
| 157 } else { |
| 158 DVLOG(1) << "Access Token has been validated"; |
| 159 } |
| 160 |
| 161 access_token_callback_.Run(access_token_, refresh_token_); |
| 162 access_token_callback_.Reset(); |
| 163 } |
| 164 |
| 165 void AccessTokenFetcher::OnOAuthError() { |
| 166 LOG(ERROR) << "AccessTokenFetcher::OnOAuthError() Called"; |
| 167 |
| 168 access_token_.clear(); |
| 169 refresh_token_.clear(); |
| 170 |
| 171 access_token_callback_.Run(access_token_, refresh_token_); |
| 172 access_token_callback_.Reset(); |
| 173 } |
| 174 |
| 175 void AccessTokenFetcher::OnNetworkError(int response_code) { |
| 176 LOG(ERROR) << "AccessTokenFetcher::OnNetworkError() Called"; |
| 177 LOG(ERROR) << "response code: " << response_code; |
| 178 |
| 179 access_token_.clear(); |
| 180 refresh_token_.clear(); |
| 181 |
| 182 access_token_callback_.Run(access_token_, refresh_token_); |
| 183 access_token_callback_.Reset(); |
| 184 } |
| 185 |
| 186 void AccessTokenFetcher::ValidateAccessToken() { |
| 187 DVLOG(2) << "Calling GetTokenInfo to validate access token"; |
| 188 |
| 189 // Create a new GaiaOAuthClient for each request to GAIA. |
| 190 CreateNewGaiaOAuthClientInstance(); |
| 191 auth_client_->GetTokenInfo( |
| 192 access_token_, |
| 193 kMaxGetTokensRetries, |
| 194 this); // GaiaOAuthClient::Delegate* delegate |
| 195 } |
| 196 |
| 197 } // namespace test |
| 198 } // namespace remoting |
OLD | NEW |