oauth2_token_fetcher.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright (c) 2013 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/chromeos/login/oauth2_token_fetcher.h"
6
7#include "base/logging.h"
8#include "base/strings/string_util.h"
9#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
10#include "content/public/browser/browser_thread.h"
11#include "google_apis/gaia/gaia_constants.h"
12#include "google_apis/gaia/google_service_auth_error.h"
13
14using content::BrowserThread;
15
16namespace {
17
18// OAuth token request max retry count.
19const int kMaxRequestAttemptCount = 5;
20// OAuth token request retry delay in milliseconds.
21const int kRequestRestartDelay = 3000;
22
23}  // namespace
24
25namespace chromeos {
26
27OAuth2TokenFetcher::OAuth2TokenFetcher(
28    OAuth2TokenFetcher::Delegate* delegate,
29    net::URLRequestContextGetter* context_getter)
30    : delegate_(delegate),
31      auth_fetcher_(this, GaiaConstants::kChromeSource, context_getter),
32      retry_count_(0) {
33  DCHECK(delegate);
34}
35
36OAuth2TokenFetcher::~OAuth2TokenFetcher() {
37}
38
39void OAuth2TokenFetcher::StartExchangeFromCookies() {
40  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
41
42  // Delay the verification if the network is not connected or on a captive
43  // portal.
44  ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
45  if (!csh->DefaultNetworkOnline()) {
46    // If network is offline, defer the token fetching until online.
47    VLOG(1) << "Network is offline.  Deferring OAuth2 token fetch.";
48    BrowserThread::PostDelayedTask(
49        BrowserThread::UI, FROM_HERE,
50        base::Bind(&OAuth2TokenFetcher::StartExchangeFromCookies,
51                   AsWeakPtr()),
52        base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
53    return;
54  }
55  auth_fetcher_.StartCookieForOAuthLoginTokenExchange(EmptyString());
56}
57
58void OAuth2TokenFetcher::StartExchangeFromAuthCode(
59    const std::string& auth_code) {
60  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
61  auth_code_ = auth_code;
62  // Delay the verification if the network is not connected or on a captive
63  // portal.
64  ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
65  if (!csh->DefaultNetworkOnline()) {
66    // If network is offline, defer the token fetching until online.
67    VLOG(1) << "Network is offline.  Deferring OAuth2 token fetch.";
68    BrowserThread::PostDelayedTask(
69        BrowserThread::UI, FROM_HERE,
70        base::Bind(&OAuth2TokenFetcher::StartExchangeFromAuthCode,
71                   AsWeakPtr(),
72                   auth_code),
73        base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
74    return;
75  }
76  auth_fetcher_.StartAuthCodeForOAuth2TokenExchange(auth_code);
77}
78
79void OAuth2TokenFetcher::OnClientOAuthSuccess(
80    const GaiaAuthConsumer::ClientOAuthResult& oauth_tokens) {
81  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82  LOG(INFO) << "Got OAuth2 tokens!";
83  retry_count_ = 0;
84  oauth_tokens_ = oauth_tokens;
85  delegate_->OnOAuth2TokensAvailable(oauth_tokens_);
86}
87
88void OAuth2TokenFetcher::OnClientOAuthFailure(
89    const GoogleServiceAuthError& error) {
90  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
91  RetryOnError(
92      error,
93      auth_code_.empty() ?
94          base::Bind(&OAuth2TokenFetcher::StartExchangeFromCookies,
95                     AsWeakPtr()) :
96          base::Bind(&OAuth2TokenFetcher::StartExchangeFromAuthCode,
97                     AsWeakPtr(), auth_code_),
98      base::Bind(&Delegate::OnOAuth2TokensFetchFailed,
99                 base::Unretained(delegate_)));
100}
101
102void OAuth2TokenFetcher::RetryOnError(const GoogleServiceAuthError& error,
103                                      const base::Closure& task,
104                                      const base::Closure& error_handler) {
105  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
106  if ((error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
107       error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE ||
108       error.state() == GoogleServiceAuthError::REQUEST_CANCELED) &&
109      retry_count_ < kMaxRequestAttemptCount) {
110    retry_count_++;
111    BrowserThread::PostDelayedTask(
112        BrowserThread::UI, FROM_HERE, task,
113        base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
114    return;
115  }
116  LOG(ERROR) << "Unrecoverable error or retry count max reached. State: "
117             << error.state() << ", network error: " << error.network_error()
118             << ", message: " << error.error_message();
119  error_handler.Run();
120}
121
122}  // namespace chromeos
123