Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(727)

Side by Side Diff: chrome/browser/net/gaia/gaia_oauth_fetcher.cc

Issue 139153011: Remove unused code (gaia_oauth_fetcher). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chrome/browser/net/gaia/gaia_oauth_fetcher.h"
6
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include "base/json/json_reader.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/string_util.h"
14 #include "base/values.h"
15 #include "chrome/browser/net/gaia/gaia_oauth_consumer.h"
16 #include "google_apis/gaia/gaia_auth_fetcher.h"
17 #include "google_apis/gaia/gaia_constants.h"
18 #include "google_apis/gaia/gaia_urls.h"
19 #include "google_apis/gaia/oauth_request_signer.h"
20 #include "grit/chromium_strings.h"
21 #include "net/base/load_flags.h"
22 #include "net/cookies/parsed_cookie.h"
23 #include "net/http/http_status_code.h"
24 #include "net/url_request/url_fetcher.h"
25 #include "net/url_request/url_request_context_getter.h"
26 #include "net/url_request/url_request_status.h"
27 #include "ui/base/l10n/l10n_util.h"
28
29 static const char kOAuthTokenCookie[] = "oauth_token";
30
31 GaiaOAuthFetcher::GaiaOAuthFetcher(GaiaOAuthConsumer* consumer,
32 net::URLRequestContextGetter* getter,
33 const std::string& service_scope)
34 : consumer_(consumer),
35 getter_(getter),
36 service_scope_(service_scope),
37 fetch_pending_(false),
38 auto_fetch_limit_(USER_INFO) {}
39
40 GaiaOAuthFetcher::~GaiaOAuthFetcher() {}
41
42 bool GaiaOAuthFetcher::HasPendingFetch() const {
43 return fetch_pending_;
44 }
45
46 void GaiaOAuthFetcher::CancelRequest() {
47 fetcher_.reset();
48 fetch_pending_ = false;
49 }
50
51 // static
52 net::URLFetcher* GaiaOAuthFetcher::CreateGaiaFetcher(
53 net::URLRequestContextGetter* getter,
54 const GURL& gaia_gurl,
55 const std::string& body,
56 const std::string& headers,
57 bool send_cookies,
58 net::URLFetcherDelegate* delegate) {
59 bool empty_body = body.empty();
60 net::URLFetcher* result = net::URLFetcher::Create(
61 0, gaia_gurl,
62 empty_body ? net::URLFetcher::GET : net::URLFetcher::POST,
63 delegate);
64 result->SetRequestContext(getter);
65 // Fetchers are sometimes cancelled because a network change was detected,
66 // especially at startup and after sign-in on ChromeOS. Retrying once should
67 // be enough in those cases; let the fetcher retry up to 3 times just in case.
68 // http://crbug.com/163710
69 result->SetAutomaticallyRetryOnNetworkChanges(3);
70
71 // The Gaia/OAuth token exchange requests do not require any cookie-based
72 // identification as part of requests. We suppress sending any cookies to
73 // maintain a separation between the user's browsing and Chrome's internal
74 // services. Where such mixing is desired (prelogin, autologin
75 // or chromeos login), it will be done explicitly.
76 if (!send_cookies)
77 result->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES);
78
79 if (!empty_body)
80 result->SetUploadData("application/x-www-form-urlencoded", body);
81 if (!headers.empty())
82 result->SetExtraRequestHeaders(headers);
83
84 return result;
85 }
86
87 // static
88 GURL GaiaOAuthFetcher::MakeGetOAuthTokenUrl(
89 const std::string& oauth1_login_scope,
90 const std::string& product_name) {
91 return GaiaUrls::GetInstance()->get_oauth_token_url().Resolve(
92 "?scope=" + oauth1_login_scope +
93 "&xoauth_display_name=" +
94 OAuthRequestSigner::Encode(product_name));
95 }
96
97 // static
98 std::string GaiaOAuthFetcher::MakeOAuthLoginBody(
99 const char* source,
100 const char* service,
101 const std::string& oauth1_access_token,
102 const std::string& oauth1_access_token_secret) {
103 OAuthRequestSigner::Parameters parameters;
104 parameters["service"] = service;
105 parameters["source"] = source;
106 std::string signed_request;
107 bool is_signed = OAuthRequestSigner::SignURL(
108 GaiaUrls::GetInstance()->oauth1_login_url(),
109 parameters,
110 OAuthRequestSigner::HMAC_SHA1_SIGNATURE,
111 OAuthRequestSigner::POST_METHOD,
112 "anonymous", // oauth_consumer_key
113 "anonymous", // consumer secret
114 oauth1_access_token, // oauth_token
115 oauth1_access_token_secret, // token secret
116 &signed_request);
117 DCHECK(is_signed);
118 return signed_request;
119 }
120
121 // static
122 std::string GaiaOAuthFetcher::MakeOAuthGetAccessTokenBody(
123 const std::string& oauth1_request_token) {
124 OAuthRequestSigner::Parameters empty_parameters;
125 std::string signed_request;
126 bool is_signed = OAuthRequestSigner::SignURL(
127 GaiaUrls::GetInstance()->oauth_get_access_token_url(),
128 empty_parameters,
129 OAuthRequestSigner::HMAC_SHA1_SIGNATURE,
130 OAuthRequestSigner::POST_METHOD,
131 "anonymous", // oauth_consumer_key
132 "anonymous", // consumer secret
133 oauth1_request_token, // oauth_token
134 "", // token secret
135 &signed_request);
136 DCHECK(is_signed);
137 return signed_request;
138 }
139
140 // static
141 std::string GaiaOAuthFetcher::MakeOAuthWrapBridgeBody(
142 const std::string& oauth1_access_token,
143 const std::string& oauth1_access_token_secret,
144 const std::string& wrap_token_duration,
145 const std::string& oauth2_scope) {
146 OAuthRequestSigner::Parameters parameters;
147 parameters["wrap_token_duration"] = wrap_token_duration;
148 parameters["wrap_scope"] = oauth2_scope;
149 std::string signed_request;
150 bool is_signed = OAuthRequestSigner::SignURL(
151 GaiaUrls::GetInstance()->oauth_wrap_bridge_url(),
152 parameters,
153 OAuthRequestSigner::HMAC_SHA1_SIGNATURE,
154 OAuthRequestSigner::POST_METHOD,
155 "anonymous", // oauth_consumer_key
156 "anonymous", // consumer secret
157 oauth1_access_token, // oauth_token
158 oauth1_access_token_secret, // token secret
159 &signed_request);
160 DCHECK(is_signed);
161 return signed_request;
162 }
163
164 // Helper method that extracts tokens from a successful reply.
165 // static
166 void GaiaOAuthFetcher::ParseOAuthLoginResponse(
167 const std::string& data,
168 std::string* sid,
169 std::string* lsid,
170 std::string* auth) {
171 using std::vector;
172 using std::pair;
173 using std::string;
174 vector<pair<string, string> > tokens;
175 base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens);
176 for (vector<pair<string, string> >::iterator i = tokens.begin();
177 i != tokens.end(); ++i) {
178 if (i->first == "SID") {
179 *sid = i->second;
180 } else if (i->first == "LSID") {
181 *lsid = i->second;
182 } else if (i->first == "Auth") {
183 *auth = i->second;
184 }
185 }
186 }
187
188 // Helper method that extracts tokens from a successful reply.
189 // static
190 void GaiaOAuthFetcher::ParseOAuthGetAccessTokenResponse(
191 const std::string& data,
192 std::string* token,
193 std::string* secret) {
194 using std::vector;
195 using std::pair;
196 using std::string;
197
198 vector<pair<string, string> > tokens;
199 base::SplitStringIntoKeyValuePairs(data, '=', '&', &tokens);
200 for (vector<pair<string, string> >::iterator i = tokens.begin();
201 i != tokens.end(); ++i) {
202 if (i->first == "oauth_token") {
203 std::string decoded;
204 if (OAuthRequestSigner::Decode(i->second, &decoded))
205 token->assign(decoded);
206 } else if (i->first == "oauth_token_secret") {
207 std::string decoded;
208 if (OAuthRequestSigner::Decode(i->second, &decoded))
209 secret->assign(decoded);
210 }
211 }
212 }
213
214 // Helper method that extracts tokens from a successful reply.
215 // static
216 void GaiaOAuthFetcher::ParseOAuthWrapBridgeResponse(const std::string& data,
217 std::string* token,
218 std::string* expires_in) {
219 using std::vector;
220 using std::pair;
221 using std::string;
222
223 vector<pair<string, string> > tokens;
224 base::SplitStringIntoKeyValuePairs(data, '=', '&', &tokens);
225 for (vector<pair<string, string> >::iterator i = tokens.begin();
226 i != tokens.end(); ++i) {
227 if (i->first == "wrap_access_token") {
228 std::string decoded;
229 if (OAuthRequestSigner::Decode(i->second, &decoded))
230 token->assign(decoded);
231 } else if (i->first == "wrap_access_token_expires_in") {
232 std::string decoded;
233 if (OAuthRequestSigner::Decode(i->second, &decoded))
234 expires_in->assign(decoded);
235 }
236 }
237 }
238
239 // Helper method that extracts tokens from a successful reply.
240 // static
241 void GaiaOAuthFetcher::ParseUserInfoResponse(const std::string& data,
242 std::string* email_result) {
243 scoped_ptr<base::Value> value(base::JSONReader::Read(data));
244 if (value->GetType() == base::Value::TYPE_DICTIONARY) {
245 base::Value* email_value;
246 base::DictionaryValue* dict =
247 static_cast<base::DictionaryValue*>(value.get());
248 if (dict->Get("email", &email_value)) {
249 if (email_value->GetType() == base::Value::TYPE_STRING) {
250 email_value->GetAsString(email_result);
251 }
252 }
253 }
254 }
255
256 void GaiaOAuthFetcher::StartOAuthLogin(
257 const char* source,
258 const char* service,
259 const std::string& oauth1_access_token,
260 const std::string& oauth1_access_token_secret) {
261 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
262
263 request_type_ = OAUTH1_LOGIN;
264 // Must outlive fetcher_.
265 request_body_ = MakeOAuthLoginBody(source, service, oauth1_access_token,
266 oauth1_access_token_secret);
267 request_headers_ = "";
268 GURL url(GaiaUrls::GetInstance()->oauth1_login_url());
269 fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
270 request_headers_, false, this));
271 fetch_pending_ = true;
272 fetcher_->Start();
273 }
274
275 void GaiaOAuthFetcher::StartGetOAuthTokenRequest() {
276 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
277
278 request_type_ = OAUTH1_REQUEST_TOKEN;
279 // Must outlive fetcher_.
280 request_body_ = "";
281 request_headers_ = "";
282 fetcher_.reset(CreateGaiaFetcher(getter_,
283 MakeGetOAuthTokenUrl(GaiaUrls::GetInstance()->oauth1_login_scope(),
284 l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)),
285 std::string(),
286 std::string(),
287 true, // send_cookies
288 this));
289 fetch_pending_ = true;
290 fetcher_->Start();
291 }
292
293 void GaiaOAuthFetcher::StartOAuthGetAccessToken(
294 const std::string& oauth1_request_token) {
295 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
296
297 request_type_ = OAUTH1_ALL_ACCESS_TOKEN;
298 // Must outlive fetcher_.
299 request_body_ = MakeOAuthGetAccessTokenBody(oauth1_request_token);
300 request_headers_ = "";
301 GURL url(GaiaUrls::GetInstance()->oauth_get_access_token_url());
302 fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
303 request_headers_, false, this));
304 fetch_pending_ = true;
305 fetcher_->Start();
306 }
307
308 void GaiaOAuthFetcher::StartOAuthWrapBridge(
309 const std::string& oauth1_access_token,
310 const std::string& oauth1_access_token_secret,
311 const std::string& wrap_token_duration,
312 const std::string& service_scope) {
313 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
314
315 request_type_ = OAUTH2_SERVICE_ACCESS_TOKEN;
316 VLOG(1) << "Starting OAuthWrapBridge for: " << service_scope;
317 std::string combined_scope = service_scope + " " +
318 GaiaUrls::GetInstance()->oauth_wrap_bridge_user_info_scope();
319 service_scope_ = service_scope;
320
321 // Must outlive fetcher_.
322 request_body_ = MakeOAuthWrapBridgeBody(
323 oauth1_access_token,
324 oauth1_access_token_secret,
325 wrap_token_duration,
326 combined_scope);
327
328 request_headers_ = "";
329 GURL url(GaiaUrls::GetInstance()->oauth_wrap_bridge_url());
330 fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
331 request_headers_, false, this));
332 fetch_pending_ = true;
333 fetcher_->Start();
334 }
335
336 void GaiaOAuthFetcher::StartUserInfo(const std::string& oauth2_access_token) {
337 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
338
339 request_type_ = USER_INFO;
340 // Must outlive fetcher_.
341 request_body_ = "";
342 request_headers_ = "Authorization: OAuth " + oauth2_access_token;
343 GURL url(GaiaUrls::GetInstance()->oauth_user_info_url());
344 fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
345 request_headers_, false, this));
346 fetch_pending_ = true;
347 fetcher_->Start();
348 }
349
350 void GaiaOAuthFetcher::StartOAuthRevokeAccessToken(const std::string& token,
351 const std::string& secret) {
352 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
353
354 request_type_ = OAUTH2_REVOKE_TOKEN;
355 // Must outlive fetcher_.
356 request_body_ = "";
357
358 OAuthRequestSigner::Parameters empty_parameters;
359 std::string auth_header;
360 bool is_signed = OAuthRequestSigner::SignAuthHeader(
361 GaiaUrls::GetInstance()->oauth_revoke_token_url(),
362 empty_parameters,
363 OAuthRequestSigner::HMAC_SHA1_SIGNATURE,
364 OAuthRequestSigner::GET_METHOD,
365 "anonymous",
366 "anonymous",
367 token,
368 secret,
369 &auth_header);
370 DCHECK(is_signed);
371 request_headers_ = "Authorization: " + auth_header;
372 GURL url(GaiaUrls::GetInstance()->oauth_revoke_token_url());
373 fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
374 request_headers_, false, this));
375 fetch_pending_ = true;
376 fetcher_->Start();
377 }
378
379 void GaiaOAuthFetcher::StartOAuthRevokeWrapToken(const std::string& token) {
380 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
381
382 request_type_ = OAUTH2_REVOKE_TOKEN;
383 // Must outlive fetcher_.
384 request_body_ = "";
385
386 request_headers_ = "Authorization: Bearer " + token;
387 GURL url(GaiaUrls::GetInstance()->oauth_revoke_token_url());
388 fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
389 request_headers_, false, this));
390 fetch_pending_ = true;
391 fetcher_->Start();
392 }
393
394 // static
395 GoogleServiceAuthError GaiaOAuthFetcher::GenerateAuthError(
396 const std::string& data,
397 const net::URLRequestStatus& status,
398 int response_code) {
399 if (!status.is_success()) {
400 if (status.status() == net::URLRequestStatus::CANCELED) {
401 return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
402 } else {
403 LOG(WARNING) << "Could not reach Google Accounts servers: errno "
404 << status.error();
405 return GoogleServiceAuthError::FromConnectionError(status.error());
406 }
407 } else {
408 LOG(WARNING) << "Unrecognized response from Google Accounts servers "
409 << "code " << response_code << " data " << data;
410 return GoogleServiceAuthError(
411 GoogleServiceAuthError::SERVICE_UNAVAILABLE);
412 }
413
414 NOTREACHED();
415 return GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
416 }
417
418 void GaiaOAuthFetcher::OnGetOAuthTokenUrlFetched(
419 const net::ResponseCookies& cookies,
420 const net::URLRequestStatus& status,
421 int response_code) {
422 if (status.is_success() && response_code == net::HTTP_OK) {
423 for (net::ResponseCookies::const_iterator iter = cookies.begin();
424 iter != cookies.end(); ++iter) {
425 net::ParsedCookie cookie(*iter);
426 if (cookie.Name() == kOAuthTokenCookie) {
427 std::string token = cookie.Value();
428 consumer_->OnGetOAuthTokenSuccess(token);
429 if (ShouldAutoFetch(OAUTH1_ALL_ACCESS_TOKEN))
430 StartOAuthGetAccessToken(token);
431 return;
432 }
433 }
434 }
435 consumer_->OnGetOAuthTokenFailure(
436 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
437 }
438
439 void GaiaOAuthFetcher::OnOAuthLoginFetched(
440 const std::string& data,
441 const net::URLRequestStatus& status,
442 int response_code) {
443 if (status.is_success() && response_code == net::HTTP_OK) {
444 std::string sid;
445 std::string lsid;
446 std::string auth;
447 ParseOAuthLoginResponse(data, &sid, &lsid, &auth);
448 if (!sid.empty() && !lsid.empty() && !auth.empty()) {
449 consumer_->OnOAuthLoginSuccess(sid, lsid, auth);
450 return;
451 }
452 }
453 // OAuthLogin returns error messages that are identical to ClientLogin,
454 // so we use GaiaAuthFetcher::GenerateAuthError to parse the response
455 // instead.
456 consumer_->OnOAuthLoginFailure(
457 GaiaAuthFetcher::GenerateOAuthLoginError(data, status));
458 }
459
460 void GaiaOAuthFetcher::OnOAuthGetAccessTokenFetched(
461 const std::string& data,
462 const net::URLRequestStatus& status,
463 int response_code) {
464 if (status.is_success() && response_code == net::HTTP_OK) {
465 VLOG(1) << "OAuth1 access token fetched.";
466 std::string secret;
467 std::string token;
468 ParseOAuthGetAccessTokenResponse(data, &token, &secret);
469 if (!token.empty() && !secret.empty()) {
470 consumer_->OnOAuthGetAccessTokenSuccess(token, secret);
471 if (ShouldAutoFetch(OAUTH2_SERVICE_ACCESS_TOKEN))
472 StartOAuthWrapBridge(
473 token, secret, GaiaConstants::kGaiaOAuthDuration, service_scope_);
474 return;
475 }
476 }
477 consumer_->OnOAuthGetAccessTokenFailure(GenerateAuthError(data, status,
478 response_code));
479 }
480
481 void GaiaOAuthFetcher::OnOAuthWrapBridgeFetched(
482 const std::string& data,
483 const net::URLRequestStatus& status,
484 int response_code) {
485 if (status.is_success() && response_code == net::HTTP_OK) {
486 VLOG(1) << "OAuth2 access token fetched.";
487 std::string token;
488 std::string expires_in;
489 ParseOAuthWrapBridgeResponse(data, &token, &expires_in);
490 if (!token.empty() && !expires_in.empty()) {
491 consumer_->OnOAuthWrapBridgeSuccess(service_scope_, token, expires_in);
492 if (ShouldAutoFetch(USER_INFO))
493 StartUserInfo(token);
494 return;
495 }
496 }
497 consumer_->OnOAuthWrapBridgeFailure(service_scope_,
498 GenerateAuthError(data, status,
499 response_code));
500 }
501
502 void GaiaOAuthFetcher::OnOAuthRevokeTokenFetched(
503 const std::string& data,
504 const net::URLRequestStatus& status,
505 int response_code) {
506 if (status.is_success() && response_code == net::HTTP_OK) {
507 consumer_->OnOAuthRevokeTokenSuccess();
508 } else {
509 LOG(ERROR) << "Token revocation failure " << response_code << ": " << data;
510 consumer_->OnOAuthRevokeTokenFailure(GenerateAuthError(data, status,
511 response_code));
512 }
513 }
514
515 void GaiaOAuthFetcher::OnUserInfoFetched(
516 const std::string& data,
517 const net::URLRequestStatus& status,
518 int response_code) {
519 if (status.is_success() && response_code == net::HTTP_OK) {
520 std::string email;
521 ParseUserInfoResponse(data, &email);
522 if (!email.empty()) {
523 VLOG(1) << "GAIA user info fetched for " << email << ".";
524 consumer_->OnUserInfoSuccess(email);
525 return;
526 }
527 }
528 consumer_->OnUserInfoFailure(GenerateAuthError(data, status,
529 response_code));
530 }
531
532 void GaiaOAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
533 // Keep |fetcher_| around to avoid invalidating its |status| (accessed below).
534 scoped_ptr<net::URLFetcher> current_fetcher(fetcher_.release());
535 fetch_pending_ = false;
536 std::string data;
537 source->GetResponseAsString(&data);
538 net::URLRequestStatus status = source->GetStatus();
539 int response_code = source->GetResponseCode();
540
541 switch (request_type_) {
542 case OAUTH1_LOGIN:
543 OnOAuthLoginFetched(data, status, response_code);
544 break;
545 case OAUTH1_REQUEST_TOKEN:
546 OnGetOAuthTokenUrlFetched(source->GetCookies(), status, response_code);
547 break;
548 case OAUTH1_ALL_ACCESS_TOKEN:
549 OnOAuthGetAccessTokenFetched(data, status, response_code);
550 break;
551 case OAUTH2_SERVICE_ACCESS_TOKEN:
552 OnOAuthWrapBridgeFetched(data, status, response_code);
553 break;
554 case USER_INFO:
555 OnUserInfoFetched(data, status, response_code);
556 break;
557 case OAUTH2_REVOKE_TOKEN:
558 OnOAuthRevokeTokenFetched(data, status, response_code);
559 break;
560 }
561 }
562
563 bool GaiaOAuthFetcher::ShouldAutoFetch(RequestType fetch_step) {
564 return fetch_step <= auto_fetch_limit_;
565 }
OLDNEW
« no previous file with comments | « chrome/browser/net/gaia/gaia_oauth_fetcher.h ('k') | chrome/browser/net/gaia/gaia_oauth_fetcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698