Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / google_apis / gaia / ubertoken_fetcher.cc
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.
4
5 #include "google_apis/gaia/ubertoken_fetcher.h"
6
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "base/rand_util.h"
11 #include "base/time/time.h"
12 #include "google_apis/gaia/gaia_auth_fetcher.h"
13 #include "google_apis/gaia/gaia_constants.h"
14 #include "google_apis/gaia/google_service_auth_error.h"
15 #include "google_apis/gaia/oauth2_token_service.h"
16
17 const int UbertokenFetcher::kMaxRetries = 3;
18
19 UbertokenFetcher::UbertokenFetcher(
20     OAuth2TokenService* token_service,
21     UbertokenConsumer* consumer,
22     net::URLRequestContextGetter* request_context)
23     : OAuth2TokenService::Consumer("uber_token_fetcher"),
24       token_service_(token_service),
25       consumer_(consumer),
26       request_context_(request_context),
27       retry_number_(0),
28       second_access_token_request_(false) {
29   DCHECK(token_service);
30   DCHECK(consumer);
31   DCHECK(request_context);
32 }
33
34 UbertokenFetcher::~UbertokenFetcher() {
35 }
36
37 void UbertokenFetcher::StartFetchingToken(const std::string& account_id) {
38   DCHECK(!account_id.empty());
39   account_id_ = account_id;
40   second_access_token_request_ = false;
41   RequestAccessToken();
42 }
43
44 void UbertokenFetcher::OnUberAuthTokenSuccess(const std::string& token) {
45   consumer_->OnUbertokenSuccess(token);
46 }
47
48 void UbertokenFetcher::OnUberAuthTokenFailure(
49     const GoogleServiceAuthError& error) {
50   // Retry only transient errors.
51   bool should_retry =
52       error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
53       error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE;
54   if (should_retry) {
55     if (retry_number_ < kMaxRetries) {
56       // Calculate an exponential backoff with randomness of less than 1 sec.
57       double backoff = base::RandDouble() + (1 << retry_number_);
58       ++retry_number_;
59       retry_timer_.Stop();
60       retry_timer_.Start(FROM_HERE,
61                          base::TimeDelta::FromSecondsD(backoff),
62                          this,
63                          &UbertokenFetcher::ExchangeTokens);
64       return;
65     }
66   } else {
67     // The access token is invalid.  Tell the token service.
68     OAuth2TokenService::ScopeSet scopes;
69     scopes.insert(GaiaConstants::kOAuth1LoginScope);
70     token_service_->InvalidateToken(account_id_, scopes, access_token_);
71
72     // In case the access was just stale, try one more time.
73     if (!second_access_token_request_) {
74       second_access_token_request_ = true;
75       RequestAccessToken();
76       return;
77     }
78   }
79
80   consumer_->OnUbertokenFailure(error);
81 }
82
83 void UbertokenFetcher::OnGetTokenSuccess(
84     const OAuth2TokenService::Request* request,
85     const std::string& access_token,
86     const base::Time& expiration_time) {
87   DCHECK(!access_token.empty());
88   access_token_ = access_token;
89   access_token_request_.reset();
90   ExchangeTokens();
91 }
92
93 void UbertokenFetcher::OnGetTokenFailure(
94     const OAuth2TokenService::Request* request,
95     const GoogleServiceAuthError& error) {
96   access_token_request_.reset();
97   consumer_->OnUbertokenFailure(error);
98 }
99
100 void UbertokenFetcher::RequestAccessToken() {
101   retry_number_ = 0;
102   gaia_auth_fetcher_.reset();
103   retry_timer_.Stop();
104
105   OAuth2TokenService::ScopeSet scopes;
106   scopes.insert(GaiaConstants::kOAuth1LoginScope);
107   access_token_request_ =
108       token_service_->StartRequest(account_id_, scopes, this);
109 }
110
111 void UbertokenFetcher::ExchangeTokens() {
112   gaia_auth_fetcher_.reset(new GaiaAuthFetcher(this,
113                                                GaiaConstants::kChromeSource,
114                                                request_context_));
115   gaia_auth_fetcher_->StartTokenFetchForUberAuthExchange(access_token_);
116 }