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 // Factory function used to initialize our scope vector below, this is needed |
| 23 // because initializer lists are only supported on C++11 compilers. |
| 24 const std::vector<std::string> MakeAppRemotingScopeVector() { |
| 25 std::vector<std::string> app_remoting_scopes; |
| 26 |
| 27 // Populate the vector with the required permissions for app remoting. |
| 28 app_remoting_scopes.push_back( |
| 29 "https://www.googleapis.com/auth/appremoting.runapplication"); |
| 30 app_remoting_scopes.push_back("https://www.googleapis.com/auth/googletalk"); |
| 31 app_remoting_scopes.push_back( |
| 32 "https://www.googleapis.com/auth/userinfo.email"); |
| 33 app_remoting_scopes.push_back("https://docs.google.com/feeds"); |
| 34 app_remoting_scopes.push_back("https://www.googleapis.com/auth/drive"); |
| 35 |
| 36 return app_remoting_scopes; |
| 37 } |
| 38 |
| 39 const std::vector<std::string> kAppRemotingScopeVector = |
| 40 MakeAppRemotingScopeVector(); |
| 41 |
| 42 } |
| 43 |
| 44 namespace remoting { |
| 45 namespace test { |
| 46 |
| 47 AccessTokenFetcher::AccessTokenFetcher() { |
| 48 oauth_client_info_ = { |
| 49 google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING), |
| 50 google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING), |
| 51 kOauthRedirectUrl}; |
| 52 } |
| 53 |
| 54 AccessTokenFetcher::~AccessTokenFetcher() { |
| 55 } |
| 56 |
| 57 void AccessTokenFetcher::GetAccessTokenFromAuthCode( |
| 58 const std::string& auth_code, |
| 59 const AccessTokenCallback& callback) { |
| 60 DCHECK(!auth_code.empty()); |
| 61 DCHECK(!callback.is_null()); |
| 62 DCHECK(access_token_callback_.is_null()); |
| 63 |
| 64 DVLOG(2) << "Calling GetTokensFromAuthCode to exchange auth_code for token"; |
| 65 |
| 66 access_token_.clear(); |
| 67 refresh_token_.clear(); |
| 68 access_token_callback_ = callback; |
| 69 |
| 70 // Create a new GaiaOAuthClient for each request to GAIA. |
| 71 CreateNewGaiaOAuthClientInstance(); |
| 72 auth_client_->GetTokensFromAuthCode( |
| 73 oauth_client_info_, auth_code, kMaxGetTokensRetries, |
| 74 this); // GaiaOAuthClient::Delegate* delegate |
| 75 } |
| 76 |
| 77 void AccessTokenFetcher::GetAccessTokenFromRefreshToken( |
| 78 const std::string& refresh_token, |
| 79 const AccessTokenCallback& callback) { |
| 80 DCHECK(!refresh_token.empty()); |
| 81 DCHECK(!callback.is_null()); |
| 82 DCHECK(access_token_callback_.is_null()); |
| 83 |
| 84 DVLOG(2) << "Calling RefreshToken to generate a new access token"; |
| 85 |
| 86 access_token_.clear(); |
| 87 refresh_token_ = refresh_token; |
| 88 access_token_callback_ = callback; |
| 89 |
| 90 // Create a new GaiaOAuthClient for each request to GAIA. |
| 91 CreateNewGaiaOAuthClientInstance(); |
| 92 auth_client_->RefreshToken( |
| 93 oauth_client_info_, |
| 94 refresh_token_, |
| 95 kAppRemotingScopeVector, |
| 96 kMaxGetTokensRetries, |
| 97 this); // GaiaOAuthClient::Delegate* delegate |
| 98 } |
| 99 |
| 100 void AccessTokenFetcher::CreateNewGaiaOAuthClientInstance() { |
| 101 scoped_refptr<remoting::URLRequestContextGetter> request_context_getter; |
| 102 request_context_getter = new remoting::URLRequestContextGetter( |
| 103 base::ThreadTaskRunnerHandle::Get(), // network_runner |
| 104 base::ThreadTaskRunnerHandle::Get()); // file_runner |
| 105 |
| 106 auth_client_.reset(new gaia::GaiaOAuthClient(request_context_getter.get())); |
| 107 } |
| 108 |
| 109 void AccessTokenFetcher::OnGetTokensResponse(const std::string& refresh_token, |
| 110 const std::string& access_token, |
| 111 int expires_in_seconds) { |
| 112 DVLOG(1) << "AccessTokenFetcher::OnGetTokensResponse() Called"; |
| 113 DVLOG(1) << "--refresh_token: " << refresh_token; |
| 114 DVLOG(1) << "--access_token: " << access_token; |
| 115 DVLOG(1) << "--expires_in_seconds: " << expires_in_seconds; |
| 116 |
| 117 refresh_token_ = refresh_token; |
| 118 access_token_ = access_token; |
| 119 |
| 120 ValidateAccessToken(); |
| 121 } |
| 122 |
| 123 void AccessTokenFetcher::OnRefreshTokenResponse(const std::string& access_token, |
| 124 int expires_in_seconds) { |
| 125 DVLOG(1) << "AccessTokenFetcher::OnRefreshTokenResponse() Called"; |
| 126 DVLOG(1) << "--access_token: " << access_token; |
| 127 DVLOG(1) << "--expires_in_seconds: " << expires_in_seconds; |
| 128 |
| 129 access_token_ = access_token; |
| 130 |
| 131 ValidateAccessToken(); |
| 132 } |
| 133 |
| 134 void AccessTokenFetcher::OnGetUserEmailResponse(const std::string& user_email) { |
| 135 // This callback should not be called as we do not request the user's email. |
| 136 NOTREACHED(); |
| 137 } |
| 138 |
| 139 void AccessTokenFetcher::OnGetUserIdResponse(const std::string& user_id) { |
| 140 // This callback should not be called as we do not request the user's id. |
| 141 NOTREACHED(); |
| 142 } |
| 143 |
| 144 void AccessTokenFetcher::OnGetUserInfoResponse( |
| 145 scoped_ptr<base::DictionaryValue> user_info) { |
| 146 // This callback should not be called as we do not request user info. |
| 147 NOTREACHED(); |
| 148 } |
| 149 |
| 150 void AccessTokenFetcher::OnGetTokenInfoResponse( |
| 151 scoped_ptr<base::DictionaryValue> token_info) { |
| 152 DVLOG(1) << "AccessTokenFetcher::OnGetTokenInfoResponse() Called"; |
| 153 |
| 154 std::string error_string; |
| 155 std::string error_description; |
| 156 |
| 157 // Check to see if the token_info we received had any errors, |
| 158 // otherwise we will assume that it is valid for our purposes. |
| 159 if (token_info->HasKey("error")) { |
| 160 token_info->GetString("error", &error_string); |
| 161 token_info->GetString("error_description", &error_description); |
| 162 |
| 163 LOG(ERROR) << "OnGetTokenInfoResponse returned an error. " |
| 164 << ", " |
| 165 << "error: " << error_string << ", " |
| 166 << "description: " << error_description; |
| 167 access_token_.clear(); |
| 168 refresh_token_.clear(); |
| 169 } else { |
| 170 DVLOG(1) << "Access Token has been validated"; |
| 171 } |
| 172 |
| 173 access_token_callback_.Run(access_token_, refresh_token_); |
| 174 access_token_callback_.Reset(); |
| 175 } |
| 176 |
| 177 void AccessTokenFetcher::OnOAuthError() { |
| 178 LOG(ERROR) << "AccessTokenFetcher::OnOAuthError() Called"; |
| 179 |
| 180 access_token_.clear(); |
| 181 refresh_token_.clear(); |
| 182 |
| 183 access_token_callback_.Run(access_token_, refresh_token_); |
| 184 access_token_callback_.Reset(); |
| 185 } |
| 186 |
| 187 void AccessTokenFetcher::OnNetworkError(int response_code) { |
| 188 LOG(ERROR) << "AccessTokenFetcher::OnNetworkError() Called"; |
| 189 LOG(ERROR) << "response code: " << response_code; |
| 190 |
| 191 access_token_.clear(); |
| 192 refresh_token_.clear(); |
| 193 |
| 194 access_token_callback_.Run(access_token_, refresh_token_); |
| 195 access_token_callback_.Reset(); |
| 196 } |
| 197 |
| 198 void AccessTokenFetcher::ValidateAccessToken() { |
| 199 DVLOG(2) << "Calling GetTokenInfo to validate access token"; |
| 200 |
| 201 // Create a new GaiaOAuthClient for each request to GAIA. |
| 202 CreateNewGaiaOAuthClientInstance(); |
| 203 auth_client_->GetTokenInfo( |
| 204 access_token_, |
| 205 kMaxGetTokensRetries, |
| 206 this); // GaiaOAuthClient::Delegate* delegate |
| 207 } |
| 208 |
| 209 } // namespace test |
| 210 } // namespace remoting |
OLD | NEW |