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()); | |
Wez
2015/02/19 22:00:23
nit: Typically we leave a blank line between DCHEC
joedow
2015/02/20 02:58:35
Done.
| |
50 if (!access_token_callback_.is_null()) { | |
51 LOG(ERROR) << "Access token request is already in progress"; | |
52 return; | |
53 } | |
54 | |
55 DVLOG(2) << "Calling GetTokensFromAuthCode to exchange auth_code for token"; | |
56 | |
57 access_token_.clear(); | |
58 refresh_token_.clear(); | |
59 access_token_callback_ = callback; | |
60 | |
61 // |auth_client_| objects can only be used for one service call so we need to | |
Wez
2015/02/19 22:00:23
What's a "service call"? Do you mean "request to G
joedow
2015/02/20 02:58:35
Done.
| |
62 // create a new one before each gaia service request. | |
Wez
2015/02/19 22:00:23
Not sure what a "gaia service request" is?
Also,
joedow
2015/02/20 02:58:35
Done.
| |
63 CreateNewGaiaOAuthClientInstance(); | |
64 auth_client_->GetTokensFromAuthCode( | |
65 oauth_client_info_, auth_code, kMaxGetTokensRetries, | |
66 this); // GaiaOAuthClient::Delegate* delegate | |
67 } | |
68 | |
69 void AccessTokenFetcher::GetAccessTokenFromRefreshToken( | |
70 const std::string& refresh_token, | |
71 const AccessTokenCallback& callback) { | |
72 DCHECK(!refresh_token.empty()); | |
73 DCHECK(!callback.is_null()); | |
Wez
2015/02/19 22:00:23
See above
joedow
2015/02/20 02:58:35
Done.
| |
74 if (!access_token_callback_.is_null()) { | |
75 LOG(ERROR) << "Access token request is already in progress"; | |
76 return; | |
77 } | |
78 | |
79 DVLOG(2) << "Calling RefreshToken to generate a new access token"; | |
80 | |
81 access_token_.clear(); | |
82 refresh_token_ = refresh_token; | |
83 access_token_callback_ = callback; | |
84 | |
85 // |auth_client_| objects can only be used for one service call so we need to | |
86 // create a new one before each gaia service request. | |
Wez
2015/02/19 22:00:23
See above
joedow
2015/02/20 02:58:35
Done.
| |
87 CreateNewGaiaOAuthClientInstance(); | |
88 auth_client_->RefreshToken( | |
89 oauth_client_info_, | |
90 refresh_token_, | |
91 kAppRemotingScopeVector, | |
92 kMaxGetTokensRetries, | |
93 this); // GaiaOAuthClient::Delegate* delegate | |
94 } | |
95 | |
96 void AccessTokenFetcher::CreateNewGaiaOAuthClientInstance() { | |
97 scoped_refptr<remoting::URLRequestContextGetter> request_context_getter; | |
98 request_context_getter = new remoting::URLRequestContextGetter( | |
99 base::ThreadTaskRunnerHandle::Get(), // network_runner | |
100 base::ThreadTaskRunnerHandle::Get()); // file_runner | |
101 | |
102 auth_client_.reset(new gaia::GaiaOAuthClient(request_context_getter.get())); | |
Wez
2015/02/19 22:00:23
When you reset this member, any existing GaiaOAuth
joedow
2015/02/20 02:58:35
A caller cannot make two concurrent requests (I ha
Wez
2015/02/23 20:17:14
Agreed; it was really the AccessTokenFetcher calle
| |
103 } | |
104 | |
105 void AccessTokenFetcher::OnGetTokensResponse(const std::string& refresh_token, | |
106 const std::string& access_token, | |
107 int expires_in_seconds) { | |
108 DVLOG(1) << "AccessTokenFetcher::OnGetTokensResponse() Called"; | |
109 DVLOG(1) << "--refresh_token: " << refresh_token; | |
110 DVLOG(1) << "--access_token: " << access_token; | |
111 DVLOG(1) << "--expires_in_seconds: " << expires_in_seconds; | |
112 | |
113 refresh_token_ = refresh_token; | |
114 access_token_ = access_token; | |
115 | |
116 ValidateAccessToken(); | |
117 } | |
118 | |
119 void AccessTokenFetcher::OnRefreshTokenResponse(const std::string& access_token, | |
120 int expires_in_seconds) { | |
121 DVLOG(1) << "AccessTokenFetcher::OnRefreshTokenResponse() Called"; | |
122 DVLOG(1) << "--access_token: " << access_token; | |
123 DVLOG(1) << "--expires_in_seconds: " << expires_in_seconds; | |
124 | |
125 access_token_ = access_token; | |
126 | |
127 ValidateAccessToken(); | |
128 } | |
129 | |
130 void AccessTokenFetcher::OnGetUserEmailResponse(const std::string& user_email) { | |
131 // This callback should not be called as we do not request the user's email. | |
132 NOTREACHED(); | |
133 } | |
134 | |
135 void AccessTokenFetcher::OnGetUserIdResponse(const std::string& user_id) { | |
136 // This callback should not be called as we do not request the user's id. | |
137 NOTREACHED(); | |
138 } | |
139 | |
140 void AccessTokenFetcher::OnGetUserInfoResponse( | |
141 scoped_ptr<base::DictionaryValue> user_info) { | |
142 // This callback should not be called as we do not request user info. | |
143 NOTREACHED(); | |
144 } | |
145 | |
146 void AccessTokenFetcher::OnGetTokenInfoResponse( | |
147 scoped_ptr<base::DictionaryValue> token_info) { | |
148 DVLOG(1) << "AccessTokenFetcher::OnGetTokenInfoResponse() Called"; | |
149 | |
150 std::string error_string; | |
151 std::string error_description; | |
152 | |
153 // Check to see if the token_info we received had any errors, | |
154 // otherwise we will assume that it is valid for our purposes. | |
155 if (token_info->HasKey("error")) { | |
156 token_info->GetString("error", &error_string); | |
157 token_info->GetString("error_description", &error_description); | |
158 | |
159 LOG(ERROR) << "OnGetTokenInfoResponse returned an error. " | |
160 << ", " | |
161 << "error: " << error_string << ", " | |
162 << "description: " << error_description; | |
163 access_token_.clear(); | |
164 refresh_token_.clear(); | |
165 } else { | |
166 DVLOG(1) << "Access Token has been validated"; | |
167 } | |
168 | |
169 access_token_callback_.Run(access_token_, refresh_token_); | |
170 access_token_callback_.Reset(); | |
171 } | |
172 | |
173 void AccessTokenFetcher::OnOAuthError() { | |
174 LOG(ERROR) << "AccessTokenFetcher::OnOAuthError() Called"; | |
175 | |
176 access_token_.clear(); | |
177 refresh_token_.clear(); | |
178 | |
179 access_token_callback_.Run(access_token_, refresh_token_); | |
180 access_token_callback_.Reset(); | |
181 } | |
182 | |
183 void AccessTokenFetcher::OnNetworkError(int response_code) { | |
184 LOG(ERROR) << "AccessTokenFetcher::OnNetworkError() Called"; | |
185 LOG(ERROR) << "response code: " << response_code; | |
186 | |
187 access_token_.clear(); | |
188 refresh_token_.clear(); | |
189 | |
190 access_token_callback_.Run(access_token_, refresh_token_); | |
191 access_token_callback_.Reset(); | |
192 } | |
193 | |
194 void AccessTokenFetcher::ValidateAccessToken() { | |
195 DVLOG(2) << "Calling GetTokenInfo to validate access token"; | |
196 | |
197 // |auth_client_| objects can only be used for one service call so we need to | |
198 // create a new one before each gaia service request. | |
199 CreateNewGaiaOAuthClientInstance(); | |
200 auth_client_->GetTokenInfo( | |
201 access_token_, | |
202 kMaxGetTokensRetries, | |
203 this); // GaiaOAuthClient::Delegate* delegate | |
204 } | |
205 | |
206 } // namespace test | |
207 } // namespace remoting | |
OLD | NEW |