• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GaiaOAuthFetcher(GaiaOAuthConsumer * consumer,net::URLRequestContextGetter * getter,const std::string & service_scope)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 
~GaiaOAuthFetcher()40 GaiaOAuthFetcher::~GaiaOAuthFetcher() {}
41 
HasPendingFetch() const42 bool GaiaOAuthFetcher::HasPendingFetch() const {
43   return fetch_pending_;
44 }
45 
CancelRequest()46 void GaiaOAuthFetcher::CancelRequest() {
47   fetcher_.reset();
48   fetch_pending_ = false;
49 }
50 
51 // static
CreateGaiaFetcher(net::URLRequestContextGetter * getter,const GURL & gaia_gurl,const std::string & body,const std::string & headers,bool send_cookies,net::URLFetcherDelegate * delegate)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
MakeGetOAuthTokenUrl(const std::string & oauth1_login_scope,const std::string & product_name)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
MakeOAuthLoginBody(const char * source,const char * service,const std::string & oauth1_access_token,const std::string & oauth1_access_token_secret)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
MakeOAuthGetAccessTokenBody(const std::string & oauth1_request_token)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
MakeOAuthWrapBridgeBody(const std::string & oauth1_access_token,const std::string & oauth1_access_token_secret,const std::string & wrap_token_duration,const std::string & oauth2_scope)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
ParseOAuthLoginResponse(const std::string & data,std::string * sid,std::string * lsid,std::string * auth)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
ParseOAuthGetAccessTokenResponse(const std::string & data,std::string * token,std::string * secret)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
ParseOAuthWrapBridgeResponse(const std::string & data,std::string * token,std::string * expires_in)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
ParseUserInfoResponse(const std::string & data,std::string * email_result)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     Value* email_value;
246     DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
247     if (dict->Get("email", &email_value)) {
248       if (email_value->GetType() == base::Value::TYPE_STRING) {
249         email_value->GetAsString(email_result);
250       }
251     }
252   }
253 }
254 
StartOAuthLogin(const char * source,const char * service,const std::string & oauth1_access_token,const std::string & oauth1_access_token_secret)255 void GaiaOAuthFetcher::StartOAuthLogin(
256     const char* source,
257     const char* service,
258     const std::string& oauth1_access_token,
259     const std::string& oauth1_access_token_secret) {
260   DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
261 
262   request_type_ = OAUTH1_LOGIN;
263   // Must outlive fetcher_.
264   request_body_ = MakeOAuthLoginBody(source, service, oauth1_access_token,
265                                      oauth1_access_token_secret);
266   request_headers_ = "";
267   GURL url(GaiaUrls::GetInstance()->oauth1_login_url());
268   fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
269                                    request_headers_, false, this));
270   fetch_pending_ = true;
271   fetcher_->Start();
272 }
273 
StartGetOAuthTokenRequest()274 void GaiaOAuthFetcher::StartGetOAuthTokenRequest() {
275   DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
276 
277   request_type_ = OAUTH1_REQUEST_TOKEN;
278   // Must outlive fetcher_.
279   request_body_ = "";
280   request_headers_ = "";
281   fetcher_.reset(CreateGaiaFetcher(getter_,
282       MakeGetOAuthTokenUrl(GaiaUrls::GetInstance()->oauth1_login_scope(),
283                            l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)),
284       std::string(),
285       std::string(),
286       true,           // send_cookies
287       this));
288   fetch_pending_ = true;
289   fetcher_->Start();
290 }
291 
StartOAuthGetAccessToken(const std::string & oauth1_request_token)292 void GaiaOAuthFetcher::StartOAuthGetAccessToken(
293     const std::string& oauth1_request_token) {
294   DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
295 
296   request_type_ = OAUTH1_ALL_ACCESS_TOKEN;
297   // Must outlive fetcher_.
298   request_body_ = MakeOAuthGetAccessTokenBody(oauth1_request_token);
299   request_headers_ = "";
300   GURL url(GaiaUrls::GetInstance()->oauth_get_access_token_url());
301   fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
302                                    request_headers_, false, this));
303   fetch_pending_ = true;
304   fetcher_->Start();
305 }
306 
StartOAuthWrapBridge(const std::string & oauth1_access_token,const std::string & oauth1_access_token_secret,const std::string & wrap_token_duration,const std::string & service_scope)307 void GaiaOAuthFetcher::StartOAuthWrapBridge(
308     const std::string& oauth1_access_token,
309     const std::string& oauth1_access_token_secret,
310     const std::string& wrap_token_duration,
311     const std::string& service_scope) {
312   DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
313 
314   request_type_ = OAUTH2_SERVICE_ACCESS_TOKEN;
315   VLOG(1) << "Starting OAuthWrapBridge for: " << service_scope;
316   std::string combined_scope = service_scope + " " +
317       GaiaUrls::GetInstance()->oauth_wrap_bridge_user_info_scope();
318   service_scope_ = service_scope;
319 
320   // Must outlive fetcher_.
321   request_body_ = MakeOAuthWrapBridgeBody(
322       oauth1_access_token,
323       oauth1_access_token_secret,
324       wrap_token_duration,
325       combined_scope);
326 
327   request_headers_ = "";
328   GURL url(GaiaUrls::GetInstance()->oauth_wrap_bridge_url());
329   fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
330                                    request_headers_, false, this));
331   fetch_pending_ = true;
332   fetcher_->Start();
333 }
334 
StartUserInfo(const std::string & oauth2_access_token)335 void GaiaOAuthFetcher::StartUserInfo(const std::string& oauth2_access_token) {
336   DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
337 
338   request_type_ = USER_INFO;
339   // Must outlive fetcher_.
340   request_body_ = "";
341   request_headers_ = "Authorization: OAuth " + oauth2_access_token;
342   GURL url(GaiaUrls::GetInstance()->oauth_user_info_url());
343   fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
344                                    request_headers_, false, this));
345   fetch_pending_ = true;
346   fetcher_->Start();
347 }
348 
StartOAuthRevokeAccessToken(const std::string & token,const std::string & secret)349 void GaiaOAuthFetcher::StartOAuthRevokeAccessToken(const std::string& token,
350                                                    const std::string& secret) {
351   DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
352 
353   request_type_ = OAUTH2_REVOKE_TOKEN;
354   // Must outlive fetcher_.
355   request_body_ = "";
356 
357   OAuthRequestSigner::Parameters empty_parameters;
358   std::string auth_header;
359   bool is_signed = OAuthRequestSigner::SignAuthHeader(
360       GaiaUrls::GetInstance()->oauth_revoke_token_url(),
361       empty_parameters,
362       OAuthRequestSigner::HMAC_SHA1_SIGNATURE,
363       OAuthRequestSigner::GET_METHOD,
364       "anonymous",
365       "anonymous",
366       token,
367       secret,
368       &auth_header);
369   DCHECK(is_signed);
370   request_headers_ = "Authorization: " + auth_header;
371   GURL url(GaiaUrls::GetInstance()->oauth_revoke_token_url());
372   fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
373                                    request_headers_, false, this));
374   fetch_pending_ = true;
375   fetcher_->Start();
376 }
377 
StartOAuthRevokeWrapToken(const std::string & token)378 void GaiaOAuthFetcher::StartOAuthRevokeWrapToken(const std::string& token) {
379   DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
380 
381   request_type_ = OAUTH2_REVOKE_TOKEN;
382   // Must outlive fetcher_.
383   request_body_ = "";
384 
385   request_headers_ = "Authorization: Bearer " + token;
386   GURL url(GaiaUrls::GetInstance()->oauth_revoke_token_url());
387   fetcher_.reset(CreateGaiaFetcher(getter_, url, request_body_,
388                                    request_headers_, false, this));
389   fetch_pending_ = true;
390   fetcher_->Start();
391 }
392 
393 // static
GenerateAuthError(const std::string & data,const net::URLRequestStatus & status,int response_code)394 GoogleServiceAuthError GaiaOAuthFetcher::GenerateAuthError(
395     const std::string& data,
396     const net::URLRequestStatus& status,
397     int response_code) {
398   if (!status.is_success()) {
399     if (status.status() == net::URLRequestStatus::CANCELED) {
400       return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
401     } else {
402       LOG(WARNING) << "Could not reach Google Accounts servers: errno "
403                    << status.error();
404       return GoogleServiceAuthError::FromConnectionError(status.error());
405     }
406   } else {
407     LOG(WARNING) << "Unrecognized response from Google Accounts servers "
408                  << "code " << response_code << " data " << data;
409     return GoogleServiceAuthError(
410         GoogleServiceAuthError::SERVICE_UNAVAILABLE);
411   }
412 
413   NOTREACHED();
414   return GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE);
415 }
416 
OnGetOAuthTokenUrlFetched(const net::ResponseCookies & cookies,const net::URLRequestStatus & status,int response_code)417 void GaiaOAuthFetcher::OnGetOAuthTokenUrlFetched(
418     const net::ResponseCookies& cookies,
419     const net::URLRequestStatus& status,
420     int response_code) {
421   if (status.is_success() && response_code == net::HTTP_OK) {
422     for (net::ResponseCookies::const_iterator iter = cookies.begin();
423         iter != cookies.end(); ++iter) {
424       net::ParsedCookie cookie(*iter);
425       if (cookie.Name() == kOAuthTokenCookie) {
426         std::string token = cookie.Value();
427         consumer_->OnGetOAuthTokenSuccess(token);
428         if (ShouldAutoFetch(OAUTH1_ALL_ACCESS_TOKEN))
429           StartOAuthGetAccessToken(token);
430         return;
431       }
432     }
433   }
434   consumer_->OnGetOAuthTokenFailure(
435       GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
436 }
437 
OnOAuthLoginFetched(const std::string & data,const net::URLRequestStatus & status,int response_code)438 void GaiaOAuthFetcher::OnOAuthLoginFetched(
439     const std::string& data,
440     const net::URLRequestStatus& status,
441     int response_code) {
442   if (status.is_success() && response_code == net::HTTP_OK) {
443     std::string sid;
444     std::string lsid;
445     std::string auth;
446     ParseOAuthLoginResponse(data, &sid, &lsid, &auth);
447     if (!sid.empty() && !lsid.empty() && !auth.empty()) {
448       consumer_->OnOAuthLoginSuccess(sid, lsid, auth);
449       return;
450     }
451   }
452   // OAuthLogin returns error messages that are identical to ClientLogin,
453   // so we use GaiaAuthFetcher::GenerateAuthError to parse the response
454   // instead.
455   consumer_->OnOAuthLoginFailure(
456       GaiaAuthFetcher::GenerateOAuthLoginError(data, status));
457 }
458 
OnOAuthGetAccessTokenFetched(const std::string & data,const net::URLRequestStatus & status,int response_code)459 void GaiaOAuthFetcher::OnOAuthGetAccessTokenFetched(
460     const std::string& data,
461     const net::URLRequestStatus& status,
462     int response_code) {
463   if (status.is_success() && response_code == net::HTTP_OK) {
464     VLOG(1) << "OAuth1 access token fetched.";
465     std::string secret;
466     std::string token;
467     ParseOAuthGetAccessTokenResponse(data, &token, &secret);
468     if (!token.empty() && !secret.empty()) {
469       consumer_->OnOAuthGetAccessTokenSuccess(token, secret);
470       if (ShouldAutoFetch(OAUTH2_SERVICE_ACCESS_TOKEN))
471         StartOAuthWrapBridge(
472             token, secret, GaiaConstants::kGaiaOAuthDuration, service_scope_);
473       return;
474     }
475   }
476   consumer_->OnOAuthGetAccessTokenFailure(GenerateAuthError(data, status,
477                                                             response_code));
478 }
479 
OnOAuthWrapBridgeFetched(const std::string & data,const net::URLRequestStatus & status,int response_code)480 void GaiaOAuthFetcher::OnOAuthWrapBridgeFetched(
481     const std::string& data,
482     const net::URLRequestStatus& status,
483     int response_code) {
484   if (status.is_success() && response_code == net::HTTP_OK) {
485     VLOG(1) << "OAuth2 access token fetched.";
486     std::string token;
487     std::string expires_in;
488     ParseOAuthWrapBridgeResponse(data, &token, &expires_in);
489     if (!token.empty() && !expires_in.empty()) {
490       consumer_->OnOAuthWrapBridgeSuccess(service_scope_, token, expires_in);
491       if (ShouldAutoFetch(USER_INFO))
492         StartUserInfo(token);
493       return;
494     }
495   }
496   consumer_->OnOAuthWrapBridgeFailure(service_scope_,
497                                       GenerateAuthError(data, status,
498                                                         response_code));
499 }
500 
OnOAuthRevokeTokenFetched(const std::string & data,const net::URLRequestStatus & status,int response_code)501 void GaiaOAuthFetcher::OnOAuthRevokeTokenFetched(
502     const std::string& data,
503     const net::URLRequestStatus& status,
504     int response_code) {
505   if (status.is_success() && response_code == net::HTTP_OK) {
506     consumer_->OnOAuthRevokeTokenSuccess();
507   } else {
508     LOG(ERROR) << "Token revocation failure " << response_code << ": " << data;
509     consumer_->OnOAuthRevokeTokenFailure(GenerateAuthError(data, status,
510                                                            response_code));
511   }
512 }
513 
OnUserInfoFetched(const std::string & data,const net::URLRequestStatus & status,int response_code)514 void GaiaOAuthFetcher::OnUserInfoFetched(
515     const std::string& data,
516     const net::URLRequestStatus& status,
517     int response_code) {
518   if (status.is_success() && response_code == net::HTTP_OK) {
519     std::string email;
520     ParseUserInfoResponse(data, &email);
521     if (!email.empty()) {
522       VLOG(1) << "GAIA user info fetched for " << email << ".";
523       consumer_->OnUserInfoSuccess(email);
524       return;
525     }
526   }
527   consumer_->OnUserInfoFailure(GenerateAuthError(data, status,
528                                                  response_code));
529 }
530 
OnURLFetchComplete(const net::URLFetcher * source)531 void GaiaOAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
532   // Keep |fetcher_| around to avoid invalidating its |status| (accessed below).
533   scoped_ptr<net::URLFetcher> current_fetcher(fetcher_.release());
534   fetch_pending_ = false;
535   std::string data;
536   source->GetResponseAsString(&data);
537   net::URLRequestStatus status = source->GetStatus();
538   int response_code = source->GetResponseCode();
539 
540   switch (request_type_) {
541     case OAUTH1_LOGIN:
542       OnOAuthLoginFetched(data, status, response_code);
543       break;
544     case OAUTH1_REQUEST_TOKEN:
545       OnGetOAuthTokenUrlFetched(source->GetCookies(), status, response_code);
546       break;
547     case OAUTH1_ALL_ACCESS_TOKEN:
548       OnOAuthGetAccessTokenFetched(data, status, response_code);
549       break;
550     case OAUTH2_SERVICE_ACCESS_TOKEN:
551       OnOAuthWrapBridgeFetched(data, status, response_code);
552       break;
553     case USER_INFO:
554       OnUserInfoFetched(data, status, response_code);
555       break;
556     case OAUTH2_REVOKE_TOKEN:
557       OnOAuthRevokeTokenFetched(data, status, response_code);
558       break;
559   }
560 }
561 
ShouldAutoFetch(RequestType fetch_step)562 bool GaiaOAuthFetcher::ShouldAutoFetch(RequestType fetch_step) {
563   return fetch_step <= auto_fetch_limit_;
564 }
565