ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / chromeos / login / signin / oauth2_login_verifier.cc
blob807e28399c3e2d97d0ff73cdd49669287de0db84
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 "chrome/browser/chromeos/login/signin/oauth2_login_verifier.h"
7 #include <vector>
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/time/time.h"
14 #include "chrome/browser/chromeos/net/delay_network_call.h"
15 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "components/signin/core/browser/profile_oauth2_token_service.h"
18 #include "components/signin/core/browser/signin_manager.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "google_apis/gaia/gaia_constants.h"
22 using content::BrowserThread;
24 namespace {
26 // OAuth token request max retry count.
27 const int kMaxRequestAttemptCount = 5;
29 // OAuth token request retry delay in milliseconds.
30 const int kRequestRestartDelay = 3000;
32 // Post merge session verification delay.
33 #ifndef NDEBUG
34 const int kPostResoreVerificationDelay = 1000;
35 #else
36 const int kPostResoreVerificationDelay = 1000*60*3;
37 #endif
39 bool IsConnectionOrServiceError(const GoogleServiceAuthError& error) {
40 return error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
41 error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE ||
42 error.state() == GoogleServiceAuthError::REQUEST_CANCELED;
45 } // namespace
47 namespace chromeos {
49 OAuth2LoginVerifier::OAuth2LoginVerifier(
50 OAuth2LoginVerifier::Delegate* delegate,
51 net::URLRequestContextGetter* system_request_context,
52 net::URLRequestContextGetter* user_request_context,
53 const std::string& oauthlogin_access_token)
54 : OAuth2TokenService::Consumer("cros_login_verifier"),
55 delegate_(delegate),
56 system_request_context_(system_request_context),
57 user_request_context_(user_request_context),
58 access_token_(oauthlogin_access_token),
59 retry_count_(0) {
60 DCHECK(delegate);
63 OAuth2LoginVerifier::~OAuth2LoginVerifier() {
66 void OAuth2LoginVerifier::VerifyUserCookies(Profile* profile) {
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
69 // Delay the verification if the network is not connected or on a captive
70 // portal.
71 DelayNetworkCall(
72 base::TimeDelta::FromMilliseconds(kRequestRestartDelay),
73 base::Bind(&OAuth2LoginVerifier::StartAuthCookiesVerification,
74 AsWeakPtr()));
77 void OAuth2LoginVerifier::VerifyProfileTokens(Profile* profile) {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
80 // Delay the verification if the network is not connected or on a captive
81 // portal.
82 DelayNetworkCall(base::TimeDelta::FromMilliseconds(kRequestRestartDelay),
83 base::Bind(&OAuth2LoginVerifier::VerifyProfileTokensImpl,
84 AsWeakPtr(), profile));
87 void OAuth2LoginVerifier::VerifyProfileTokensImpl(Profile* profile) {
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
90 gaia_token_.clear();
91 if (access_token_.empty()) {
92 // Fetch /OAuthLogin scoped access token.
93 StartFetchingOAuthLoginAccessToken(profile);
94 } else {
95 // If OAuthLogin-scoped access token already exists (if it's generated
96 // together with freshly minted refresh token), then fetch GAIA uber token.
97 StartOAuthLoginForUberToken();
101 void OAuth2LoginVerifier::StartFetchingOAuthLoginAccessToken(Profile* profile) {
102 OAuth2TokenService::ScopeSet scopes;
103 scopes.insert(GaiaConstants::kOAuth1LoginScope);
104 ProfileOAuth2TokenService* token_service =
105 ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
106 SigninManagerBase* signin_manager =
107 SigninManagerFactory::GetForProfile(profile);
108 login_token_request_ = token_service->StartRequestWithContext(
109 signin_manager->GetAuthenticatedAccountId(),
110 system_request_context_.get(),
111 scopes,
112 this);
115 void OAuth2LoginVerifier::StartOAuthLoginForUberToken() {
116 // No service will fetch us uber auth token.
117 gaia_fetcher_.reset(
118 new GaiaAuthFetcher(this,
119 std::string(GaiaConstants::kChromeOSSource),
120 user_request_context_.get()));
121 gaia_fetcher_->StartTokenFetchForUberAuthExchange(access_token_);
125 void OAuth2LoginVerifier::OnUberAuthTokenSuccess(
126 const std::string& uber_token) {
127 VLOG(1) << "OAuthLogin(uber_token) successful!";
128 retry_count_ = 0;
129 gaia_token_ = uber_token;
130 StartMergeSession();
133 void OAuth2LoginVerifier::OnUberAuthTokenFailure(
134 const GoogleServiceAuthError& error) {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
136 LOG(WARNING) << "OAuthLogin(uber_token) failed,"
137 << " error: " << error.state();
138 RetryOnError("OAuthLoginUberToken", error,
139 base::Bind(&OAuth2LoginVerifier::StartOAuthLoginForUberToken,
140 AsWeakPtr()),
141 base::Bind(&Delegate::OnSessionMergeFailure,
142 base::Unretained(delegate_)));
145 void OAuth2LoginVerifier::StartMergeSession() {
146 DCHECK(!gaia_token_.empty());
147 gaia_fetcher_.reset(
148 new GaiaAuthFetcher(this,
149 std::string(GaiaConstants::kChromeOSSource),
150 user_request_context_.get()));
151 gaia_fetcher_->StartMergeSession(gaia_token_, std::string());
154 void OAuth2LoginVerifier::OnMergeSessionSuccess(const std::string& data) {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
156 VLOG(1) << "MergeSession successful.";
157 delegate_->OnSessionMergeSuccess();
158 // Schedule post-merge verification to analyze how many LSID/SID overruns
159 // were created by the session restore.
160 SchedulePostMergeVerification();
163 void OAuth2LoginVerifier::SchedulePostMergeVerification() {
164 BrowserThread::PostDelayedTask(
165 BrowserThread::UI,
166 FROM_HERE,
167 base::Bind(
168 &OAuth2LoginVerifier::StartAuthCookiesVerification, AsWeakPtr()),
169 base::TimeDelta::FromMilliseconds(kPostResoreVerificationDelay));
172 void OAuth2LoginVerifier::StartAuthCookiesVerification() {
173 gaia_fetcher_.reset(
174 new GaiaAuthFetcher(this,
175 std::string(GaiaConstants::kChromeOSSource),
176 user_request_context_.get()));
177 gaia_fetcher_->StartListAccounts();
180 void OAuth2LoginVerifier::OnMergeSessionFailure(
181 const GoogleServiceAuthError& error) {
182 LOG(WARNING) << "Failed MergeSession request," << " error: " << error.state();
183 // If MergeSession from GAIA service token fails, retry the session restore
184 // from OAuth2 refresh token. If that failed too, signal the delegate.
185 RetryOnError(
186 "MergeSession",
187 error,
188 base::Bind(&OAuth2LoginVerifier::StartMergeSession,
189 AsWeakPtr()),
190 base::Bind(&Delegate::OnSessionMergeFailure,
191 base::Unretained(delegate_)));
194 void OAuth2LoginVerifier::OnGetTokenSuccess(
195 const OAuth2TokenService::Request* request,
196 const std::string& access_token,
197 const base::Time& expiration_time) {
198 DCHECK_EQ(login_token_request_.get(), request);
199 login_token_request_.reset();
201 VLOG(1) << "Got OAuth2 access token!";
202 retry_count_ = 0;
203 access_token_ = access_token;
204 StartOAuthLoginForUberToken();
207 void OAuth2LoginVerifier::OnGetTokenFailure(
208 const OAuth2TokenService::Request* request,
209 const GoogleServiceAuthError& error) {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
211 DCHECK_EQ(login_token_request_.get(), request);
212 login_token_request_.reset();
214 LOG(WARNING) << "Failed to get OAuth2 access token, "
215 << " error: " << error.state();
216 UMA_HISTOGRAM_ENUMERATION(
217 base::StringPrintf("OAuth2Login.%sFailure", "GetOAuth2AccessToken"),
218 error.state(),
219 GoogleServiceAuthError::NUM_STATES);
220 delegate_->OnSessionMergeFailure(IsConnectionOrServiceError(error));
223 void OAuth2LoginVerifier::OnListAccountsSuccess(
224 const std::string& data) {
225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
226 VLOG(1) << "ListAccounts successful.";
227 delegate_->OnListAccountsSuccess(data);
230 void OAuth2LoginVerifier::OnListAccountsFailure(
231 const GoogleServiceAuthError& error) {
232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
233 LOG(WARNING) << "Failed to get list of session accounts, "
234 << " error: " << error.state();
235 RetryOnError(
236 "ListAccounts",
237 error,
238 base::Bind(&OAuth2LoginVerifier::StartAuthCookiesVerification,
239 AsWeakPtr()),
240 base::Bind(&Delegate::OnListAccountsFailure,
241 base::Unretained(delegate_)));
244 void OAuth2LoginVerifier::RetryOnError(const char* operation_id,
245 const GoogleServiceAuthError& error,
246 const base::Closure& task_to_retry,
247 const ErrorHandler& error_handler) {
248 if (IsConnectionOrServiceError(error) &&
249 retry_count_ < kMaxRequestAttemptCount) {
250 retry_count_++;
251 UMA_HISTOGRAM_ENUMERATION(
252 base::StringPrintf("OAuth2Login.%sRetry", operation_id),
253 error.state(),
254 GoogleServiceAuthError::NUM_STATES);
255 BrowserThread::PostDelayedTask(
256 BrowserThread::UI, FROM_HERE, task_to_retry,
257 base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
258 return;
261 LOG(WARNING) << "Unrecoverable error or retry count max reached for "
262 << operation_id;
263 UMA_HISTOGRAM_ENUMERATION(
264 base::StringPrintf("OAuth2Login.%sFailure", operation_id),
265 error.state(),
266 GoogleServiceAuthError::NUM_STATES);
268 error_handler.Run(IsConnectionOrServiceError(error));
271 } // namespace chromeos