gaia_oauth_client.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_oauth_client.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_status_code.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAccessTokenValue[] = "access_token";
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRefreshTokenValue[] = "refresh_token";
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kExpiresInValue[] = "expires_in";
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gaia {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GaiaOAuthClient::Core
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<GaiaOAuthClient::Core>,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public net::URLFetcherDelegate {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core(const std::string& gaia_url,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       net::URLRequestContextGetter* request_context_getter)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           : gaia_url_(gaia_url),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             num_retries_(0),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             request_context_getter_(request_context_getter),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             delegate_(NULL),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             request_type_(NO_PENDING_REQUEST) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetTokensFromAuthCode(const OAuthClientInfo& oauth_client_info,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const std::string& auth_code,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int max_retries,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             GaiaOAuthClient::Delegate* delegate);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RefreshToken(const OAuthClientInfo& oauth_client_info,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& refresh_token,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int max_retries,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    GaiaOAuthClient::Delegate* delegate);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetUserInfo(const std::string& oauth_access_token,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int max_retries,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    Delegate* delegate);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // net::URLFetcherDelegate implementation.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<Core>;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum RequestType {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NO_PENDING_REQUEST,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TOKENS_FROM_AUTH_CODE,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    REFRESH_TOKEN,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    USER_INFO,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Core() {}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void MakeGaiaRequest(const std::string& post_body,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int max_retries,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       GaiaOAuthClient::Delegate* delegate);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleResponse(const net::URLFetcher* source,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool* should_retry_request);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL gaia_url_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_retries_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GaiaOAuthClient::Delegate* delegate_;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<net::URLFetcher> request_;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestType request_type_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::GetTokensFromAuthCode(
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OAuthClientInfo& oauth_client_info,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& auth_code,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int max_retries,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GaiaOAuthClient::Delegate* delegate) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_type_, NO_PENDING_REQUEST);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_type_ = TOKENS_FROM_AUTH_CODE;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string post_body =
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "code=" + net::EscapeUrlEncodedData(auth_code, true) +
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "&client_id=" + net::EscapeUrlEncodedData(oauth_client_info.client_id,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                true) +
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "&client_secret=" +
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::EscapeUrlEncodedData(oauth_client_info.client_secret, true) +
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "&redirect_uri=" +
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::EscapeUrlEncodedData(oauth_client_info.redirect_uri, true) +
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "&grant_type=authorization_code";
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MakeGaiaRequest(post_body, max_retries, delegate);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::RefreshToken(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OAuthClientInfo& oauth_client_info,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& refresh_token,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int max_retries,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GaiaOAuthClient::Delegate* delegate) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_type_, NO_PENDING_REQUEST);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_type_ = REFRESH_TOKEN;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string post_body =
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "refresh_token=" + net::EscapeUrlEncodedData(refresh_token, true) +
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "&client_id=" + net::EscapeUrlEncodedData(oauth_client_info.client_id,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                true) +
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "&client_secret=" +
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::EscapeUrlEncodedData(oauth_client_info.client_secret, true) +
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "&grant_type=refresh_token";
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MakeGaiaRequest(post_body, max_retries, delegate);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::GetUserInfo(const std::string& oauth_access_token,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int max_retries,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        Delegate* delegate) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_type_, NO_PENDING_REQUEST);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!request_.get());
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_type_ = USER_INFO;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_ = delegate;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_retries_ = 0;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_.reset(net::URLFetcher::Create(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, GURL(GaiaUrls::GetInstance()->oauth_user_info_url()),
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::URLFetcher::GET, this));
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  request_->SetRequestContext(request_context_getter_.get());
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  request_->AddExtraRequestHeader("Authorization: OAuth " + oauth_access_token);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_->SetMaxRetriesOn5xx(max_retries);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fetchers are sometimes cancelled because a network change was detected,
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // especially at startup and after sign-in on ChromeOS. Retrying once should
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // be enough in those cases; let the fetcher retry up to 3 times just in case.
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // http://crbug.com/163710
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_->SetAutomaticallyRetryOnNetworkChanges(3);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->Start();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::MakeGaiaRequest(
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& post_body,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int max_retries,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GaiaOAuthClient::Delegate* delegate) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!request_.get()) << "Tried to fetch two things at once!";
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_ = delegate;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_retries_ = 0;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_.reset(net::URLFetcher::Create(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, gaia_url_, net::URLFetcher::POST, this));
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  request_->SetRequestContext(request_context_getter_.get());
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->SetUploadData("application/x-www-form-urlencoded", post_body);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_->SetMaxRetriesOn5xx(max_retries);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // See comment on SetAutomaticallyRetryOnNetworkChanges() above.
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_->SetAutomaticallyRetryOnNetworkChanges(3);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->Start();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// URLFetcher::Delegate implementation.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::OnURLFetchComplete(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool should_retry = false;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandleResponse(source, &should_retry);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_retry) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Explicitly call ReceivedContentWasMalformed() to ensure the current
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // request gets counted as a failure for calculation of the back-off
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // period.  If it was already a failure by status code, this call will
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // be ignored.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->ReceivedContentWasMalformed();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_retries_++;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We must set our request_context_getter_ again because
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // URLFetcher::Core::RetryOrCompleteUrlFetch resets it to NULL...
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    request_->SetRequestContext(request_context_getter_.get());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->Start();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::Core::HandleResponse(
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* should_retry_request) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep the URLFetcher object in case we need to reuse it.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<net::URLFetcher> old_request = request_.Pass();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(source, old_request.get());
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RC_BAD_REQUEST means the arguments are invalid. No point retrying. We are
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // done here.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source->GetResponseCode() == net::HTTP_BAD_REQUEST) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnOAuthError();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DictionaryValue> response_dict;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source->GetResponseCode() == net::HTTP_OK) {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string data;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source->GetResponseAsString(&data);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<Value> message_value(base::JSONReader::Read(data));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (message_value.get() &&
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_value->IsType(Value::TYPE_DICTIONARY)) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_dict.reset(
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<DictionaryValue*>(message_value.release()));
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_dict.get()) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we don't have an access token yet and the the error was not
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // RC_BAD_REQUEST, we may need to retry.
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((source->GetMaxRetriesOn5xx() != -1) &&
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        (num_retries_ >= source->GetMaxRetriesOn5xx())) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Retry limit reached. Give up.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->OnNetworkError(source->GetResponseCode());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_ = old_request.Pass();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *should_retry_request = true;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestType type = request_type_;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_type_ = NO_PENDING_REQUEST;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case USER_INFO: {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string email;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_dict->GetString("email", &email);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->OnGetUserInfoResponse(email);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TOKENS_FROM_AUTH_CODE:
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case REFRESH_TOKEN: {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string access_token;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string refresh_token;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int expires_in_seconds = 0;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_dict->GetString(kAccessTokenValue, &access_token);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_dict->GetString(kRefreshTokenValue, &refresh_token);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_dict->GetInteger(kExpiresInValue, &expires_in_seconds);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (access_token.empty()) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnOAuthError();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (type == REFRESH_TOKEN) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnRefreshTokenResponse(access_token, expires_in_seconds);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnGetTokensResponse(refresh_token,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       access_token,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       expires_in_seconds);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GaiaOAuthClient::GaiaOAuthClient(const std::string& gaia_url,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 net::URLRequestContextGetter* context_getter) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_ = new Core(gaia_url, context_getter);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GaiaOAuthClient::~GaiaOAuthClient() {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::GetTokensFromAuthCode(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OAuthClientInfo& oauth_client_info,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& auth_code,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int max_retries,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Delegate* delegate) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return core_->GetTokensFromAuthCode(oauth_client_info,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      auth_code,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      max_retries,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      delegate);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::RefreshToken(const OAuthClientInfo& oauth_client_info,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& refresh_token,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int max_retries,
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   Delegate* delegate) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return core_->RefreshToken(oauth_client_info,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             refresh_token,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             max_retries,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             delegate);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GaiaOAuthClient::GetUserInfo(const std::string& access_token,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int max_retries,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  Delegate* delegate) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return core_->GetUserInfo(access_token, max_retries, delegate);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gaia
291