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/policy/policy_oauth2_token_fetcher.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "google_apis/gaia/gaia_auth_fetcher.h"
14 #include "google_apis/gaia/gaia_constants.h"
15 #include "google_apis/gaia/gaia_urls.h"
16 #include "google_apis/gaia/google_service_auth_error.h"
17 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
18 #include "net/url_request/url_request_context_getter.h"
19
20 using content::BrowserThread;
21
22 namespace policy {
23
24 namespace {
25
26 // Max retry count for token fetching requests.
27 const int kMaxRequestAttemptCount = 5;
28
29 // OAuth token request retry delay in milliseconds.
30 const int kRequestRestartDelay = 3000;
31
32 } // namespace
33
PolicyOAuth2TokenFetcher(net::URLRequestContextGetter * auth_context_getter,net::URLRequestContextGetter * system_context_getter,const TokenCallback & callback)34 PolicyOAuth2TokenFetcher::PolicyOAuth2TokenFetcher(
35 net::URLRequestContextGetter* auth_context_getter,
36 net::URLRequestContextGetter* system_context_getter,
37 const TokenCallback& callback)
38 : auth_context_getter_(auth_context_getter),
39 system_context_getter_(system_context_getter),
40 retry_count_(0),
41 failed_(false),
42 callback_(callback) {}
43
~PolicyOAuth2TokenFetcher()44 PolicyOAuth2TokenFetcher::~PolicyOAuth2TokenFetcher() {}
45
Start()46 void PolicyOAuth2TokenFetcher::Start() {
47 retry_count_ = 0;
48 StartFetchingRefreshToken();
49 }
50
StartFetchingRefreshToken()51 void PolicyOAuth2TokenFetcher::StartFetchingRefreshToken() {
52 refresh_token_fetcher_.reset(new GaiaAuthFetcher(
53 this, GaiaConstants::kChromeSource, auth_context_getter_.get()));
54 refresh_token_fetcher_->StartCookieForOAuthLoginTokenExchange(std::string());
55 }
56
StartFetchingAccessToken()57 void PolicyOAuth2TokenFetcher::StartFetchingAccessToken() {
58 std::vector<std::string> scopes;
59 scopes.push_back(GaiaConstants::kDeviceManagementServiceOAuth);
60 scopes.push_back(GaiaConstants::kOAuthWrapBridgeUserInfoScope);
61 access_token_fetcher_.reset(
62 new OAuth2AccessTokenFetcherImpl(this,
63 system_context_getter_.get(),
64 oauth2_refresh_token_));
65 access_token_fetcher_->Start(
66 GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
67 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
68 scopes);
69 }
70
OnClientOAuthSuccess(const GaiaAuthConsumer::ClientOAuthResult & oauth2_tokens)71 void PolicyOAuth2TokenFetcher::OnClientOAuthSuccess(
72 const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) {
73 VLOG(1) << "OAuth2 tokens for policy fetching succeeded.";
74 oauth2_refresh_token_ = oauth2_tokens.refresh_token;
75 retry_count_ = 0;
76 StartFetchingAccessToken();
77 }
78
OnClientOAuthFailure(const GoogleServiceAuthError & error)79 void PolicyOAuth2TokenFetcher::OnClientOAuthFailure(
80 const GoogleServiceAuthError& error) {
81 VLOG(1) << "OAuth2 tokens fetch for policy fetch failed!";
82 RetryOnError(error,
83 base::Bind(&PolicyOAuth2TokenFetcher::StartFetchingRefreshToken,
84 AsWeakPtr()));
85 }
86
OnGetTokenSuccess(const std::string & access_token,const base::Time & expiration_time)87 void PolicyOAuth2TokenFetcher::OnGetTokenSuccess(
88 const std::string& access_token,
89 const base::Time& expiration_time) {
90 VLOG(1) << "OAuth2 access token (device management) fetching succeeded.";
91 oauth2_access_token_ = access_token;
92 ForwardPolicyToken(access_token,
93 GoogleServiceAuthError(GoogleServiceAuthError::NONE));
94 }
95
OnGetTokenFailure(const GoogleServiceAuthError & error)96 void PolicyOAuth2TokenFetcher::OnGetTokenFailure(
97 const GoogleServiceAuthError& error) {
98 LOG(ERROR) << "OAuth2 access token (device management) fetching failed!";
99 RetryOnError(error,
100 base::Bind(&PolicyOAuth2TokenFetcher::StartFetchingAccessToken,
101 AsWeakPtr()));
102 }
103
RetryOnError(const GoogleServiceAuthError & error,const base::Closure & task)104 void PolicyOAuth2TokenFetcher::RetryOnError(const GoogleServiceAuthError& error,
105 const base::Closure& task) {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
107 if ((error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
108 error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE ||
109 error.state() == GoogleServiceAuthError::REQUEST_CANCELED) &&
110 retry_count_ < kMaxRequestAttemptCount) {
111 retry_count_++;
112 BrowserThread::PostDelayedTask(
113 BrowserThread::UI, FROM_HERE, task,
114 base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
115 return;
116 }
117 LOG(ERROR) << "Unrecoverable error or retry count max reached.";
118 failed_ = true;
119 // Invoking the |callback_| signals to the owner of this object that it has
120 // completed, and the owner may delete this object on the callback method.
121 // So don't rely on |this| still being valid after ForwardPolicyToken()
122 // returns i.e. don't write to |failed_| or other fields.
123 ForwardPolicyToken(std::string(), error);
124 }
125
ForwardPolicyToken(const std::string & token,const GoogleServiceAuthError & error)126 void PolicyOAuth2TokenFetcher::ForwardPolicyToken(
127 const std::string& token,
128 const GoogleServiceAuthError& error) {
129 if (!callback_.is_null())
130 callback_.Run(token, error);
131 }
132
133 } // namespace policy
134