Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / google_apis / gaia / ubertoken_fetcher.cc
blob0e65e917d58fa56f2f129821a6101a06af7f15dd
1 // Copyright 2014 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.
5 #include "google_apis/gaia/ubertoken_fetcher.h"
7 #include <vector>
9 #include "base/logging.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "base/rand_util.h"
12 #include "base/time/time.h"
13 #include "google_apis/gaia/gaia_auth_fetcher.h"
14 #include "google_apis/gaia/gaia_constants.h"
15 #include "google_apis/gaia/google_service_auth_error.h"
16 #include "google_apis/gaia/oauth2_token_service.h"
18 namespace {
19 GaiaAuthFetcher* CreateGaiaAuthFetcher(
20 GaiaAuthConsumer* consumer,
21 const std::string& source,
22 net::URLRequestContextGetter* request_context) {
23 return new GaiaAuthFetcher(consumer, source, request_context);
27 const int UbertokenFetcher::kMaxRetries = 3;
29 UbertokenFetcher::UbertokenFetcher(
30 OAuth2TokenService* token_service,
31 UbertokenConsumer* consumer,
32 const std::string& source,
33 net::URLRequestContextGetter* request_context)
34 : UbertokenFetcher(token_service,
35 consumer,
36 source,
37 request_context,
38 base::Bind(CreateGaiaAuthFetcher)) {
41 UbertokenFetcher::UbertokenFetcher(
42 OAuth2TokenService* token_service,
43 UbertokenConsumer* consumer,
44 const std::string& source,
45 net::URLRequestContextGetter* request_context,
46 GaiaAuthFetcherFactory factory)
47 : OAuth2TokenService::Consumer("uber_token_fetcher"),
48 token_service_(token_service),
49 consumer_(consumer),
50 source_(source),
51 request_context_(request_context),
52 gaia_auth_fetcher_factory_(factory),
53 retry_number_(0),
54 second_access_token_request_(false) {
55 DCHECK(token_service);
56 DCHECK(consumer);
57 DCHECK(request_context);
60 UbertokenFetcher::~UbertokenFetcher() {
63 void UbertokenFetcher::StartFetchingToken(const std::string& account_id) {
64 DCHECK(!account_id.empty());
65 account_id_ = account_id;
66 second_access_token_request_ = false;
67 RequestAccessToken();
70 void UbertokenFetcher::StartFetchingTokenWithAccessToken(
71 const std::string& account_id, const std::string& access_token) {
72 DCHECK(!account_id.empty());
73 DCHECK(!access_token.empty());
75 account_id_ = account_id;
76 access_token_ = access_token;
77 ExchangeTokens();
80 void UbertokenFetcher::OnUberAuthTokenSuccess(const std::string& token) {
81 consumer_->OnUbertokenSuccess(token);
84 void UbertokenFetcher::OnUberAuthTokenFailure(
85 const GoogleServiceAuthError& error) {
86 // Retry only transient errors.
87 bool should_retry =
88 error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
89 error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE;
90 if (should_retry) {
91 if (retry_number_ < kMaxRetries) {
92 // Calculate an exponential backoff with randomness of less than 1 sec.
93 double backoff = base::RandDouble() + (1 << retry_number_);
94 ++retry_number_;
95 UMA_HISTOGRAM_ENUMERATION("Signin.UberTokenRetry",
96 error.state(), GoogleServiceAuthError::NUM_STATES);
97 retry_timer_.Stop();
98 retry_timer_.Start(FROM_HERE,
99 base::TimeDelta::FromSecondsD(backoff),
100 this,
101 &UbertokenFetcher::ExchangeTokens);
102 return;
104 } else {
105 // The access token is invalid. Tell the token service.
106 OAuth2TokenService::ScopeSet scopes;
107 scopes.insert(GaiaConstants::kOAuth1LoginScope);
108 token_service_->InvalidateAccessToken(account_id_, scopes, access_token_);
110 // In case the access was just stale, try one more time.
111 if (!second_access_token_request_) {
112 second_access_token_request_ = true;
113 RequestAccessToken();
114 return;
118 UMA_HISTOGRAM_ENUMERATION("Signin.UberTokenFailure",
119 error.state(), GoogleServiceAuthError::NUM_STATES);
120 consumer_->OnUbertokenFailure(error);
123 void UbertokenFetcher::OnGetTokenSuccess(
124 const OAuth2TokenService::Request* request,
125 const std::string& access_token,
126 const base::Time& expiration_time) {
127 DCHECK(!access_token.empty());
128 access_token_ = access_token;
129 access_token_request_.reset();
130 ExchangeTokens();
133 void UbertokenFetcher::OnGetTokenFailure(
134 const OAuth2TokenService::Request* request,
135 const GoogleServiceAuthError& error) {
136 access_token_request_.reset();
137 consumer_->OnUbertokenFailure(error);
140 void UbertokenFetcher::RequestAccessToken() {
141 retry_number_ = 0;
142 gaia_auth_fetcher_.reset();
143 retry_timer_.Stop();
145 OAuth2TokenService::ScopeSet scopes;
146 scopes.insert(GaiaConstants::kOAuth1LoginScope);
147 access_token_request_ =
148 token_service_->StartRequest(account_id_, scopes, this);
151 void UbertokenFetcher::ExchangeTokens() {
152 gaia_auth_fetcher_.reset(
153 gaia_auth_fetcher_factory_.Run(this, source_, request_context_));
154 gaia_auth_fetcher_->StartTokenFetchForUberAuthExchange(access_token_);