1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/signin/oauth2_login_verifier.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/chromeos/net/delay_network_call.h"
15558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/profile_oauth2_token_service.h"
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// OAuth token request max retry count.
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaxRequestAttemptCount = 5;
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// OAuth token request retry delay in milliseconds.
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kRequestRestartDelay = 3000;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Post merge session verification delay.
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#ifndef NDEBUG
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const int kPostResoreVerificationDelay = 1000;
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#else
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const int kPostResoreVerificationDelay = 1000*60*3;
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool IsConnectionOrServiceError(const GoogleServiceAuthError& error) {
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE ||
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         error.state() == GoogleServiceAuthError::REQUEST_CANCELED;
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2LoginVerifier::OAuth2LoginVerifier(
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OAuth2LoginVerifier::Delegate* delegate,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::URLRequestContextGetter* system_request_context,
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    net::URLRequestContextGetter* user_request_context,
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& oauthlogin_access_token)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : OAuth2TokenService::Consumer("cros_login_verifier"),
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delegate_(delegate),
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      system_request_context_(system_request_context),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      user_request_context_(user_request_context),
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      access_token_(oauthlogin_access_token),
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      retry_count_(0) {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(delegate);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OAuth2LoginVerifier::~OAuth2LoginVerifier() {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OAuth2LoginVerifier::VerifyUserCookies(Profile* profile) {
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Delay the verification if the network is not connected or on a captive
70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // portal.
71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DelayNetworkCall(
72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&OAuth2LoginVerifier::StartAuthCookiesVerification,
73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 AsWeakPtr()),
74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
77558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid OAuth2LoginVerifier::VerifyProfileTokens(Profile* profile) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Delay the verification if the network is not connected or on a captive
81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // portal.
82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DelayNetworkCall(
83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(
84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          &OAuth2LoginVerifier::VerifyProfileTokensImpl, AsWeakPtr(), profile),
85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid OAuth2LoginVerifier::VerifyProfileTokensImpl(Profile* profile) {
89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gaia_token_.clear();
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (access_token_.empty()) {
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Fetch /OAuthLogin scoped access token.
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StartFetchingOAuthLoginAccessToken(profile);
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If OAuthLogin-scoped access token already exists (if it's generated
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // together with freshly minted refresh token), then fetch GAIA uber token.
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StartOAuthLoginForUberToken();
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid OAuth2LoginVerifier::StartFetchingOAuthLoginAccessToken(Profile* profile) {
103558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  OAuth2TokenService::ScopeSet scopes;
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scopes.insert(GaiaConstants::kOAuth1LoginScope);
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ProfileOAuth2TokenService* token_service =
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SigninManagerBase* signin_manager =
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SigninManagerFactory::GetForProfile(profile);
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  login_token_request_ = token_service->StartRequestWithContext(
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      signin_manager->GetAuthenticatedAccountId(),
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      system_request_context_.get(),
11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      scopes,
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      this);
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2LoginVerifier::StartOAuthLoginForUberToken() {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // No service will fetch us uber auth token.
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gaia_fetcher_.reset(
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      new GaiaAuthFetcher(this,
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                          std::string(GaiaConstants::kChromeOSSource),
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          user_request_context_.get()));
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gaia_fetcher_->StartTokenFetchForUberAuthExchange(access_token_);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2LoginVerifier::OnUberAuthTokenSuccess(
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& uber_token) {
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(1) << "OAuthLogin(uber_token) successful!";
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  retry_count_ = 0;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gaia_token_ = uber_token;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StartMergeSession();
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2LoginVerifier::OnUberAuthTokenFailure(
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GoogleServiceAuthError& error) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LOG(WARNING) << "OAuthLogin(uber_token) failed,"
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               << " error: " << error.state();
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RetryOnError("OAuthLoginUberToken", error,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               base::Bind(&OAuth2LoginVerifier::StartOAuthLoginForUberToken,
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          AsWeakPtr()),
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               base::Bind(&Delegate::OnSessionMergeFailure,
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          base::Unretained(delegate_)));
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void OAuth2LoginVerifier::StartMergeSession() {
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(!gaia_token_.empty());
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gaia_fetcher_.reset(
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      new GaiaAuthFetcher(this,
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                          std::string(GaiaConstants::kChromeOSSource),
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          user_request_context_.get()));
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  gaia_fetcher_->StartMergeSession(gaia_token_, std::string());
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void OAuth2LoginVerifier::OnMergeSessionSuccess(const std::string& data) {
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << "MergeSession successful.";
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  delegate_->OnSessionMergeSuccess();
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Schedule post-merge verification to analyze how many LSID/SID overruns
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // were created by the session restore.
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SchedulePostMergeVerification();
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void OAuth2LoginVerifier::SchedulePostMergeVerification() {
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserThread::PostDelayedTask(
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserThread::UI,
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      FROM_HERE,
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &OAuth2LoginVerifier::StartAuthCookiesVerification, AsWeakPtr()),
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(kPostResoreVerificationDelay));
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void OAuth2LoginVerifier::StartAuthCookiesVerification() {
1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  gaia_fetcher_.reset(
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      new GaiaAuthFetcher(this,
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                          std::string(GaiaConstants::kChromeOSSource),
1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                          user_request_context_.get()));
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gaia_fetcher_->StartListAccounts();
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2LoginVerifier::OnMergeSessionFailure(
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GoogleServiceAuthError& error) {
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  LOG(WARNING) << "Failed MergeSession request," << " error: " << error.state();
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If MergeSession from GAIA service token fails, retry the session restore
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // from OAuth2 refresh token. If that failed too, signal the delegate.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RetryOnError(
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "MergeSession",
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&OAuth2LoginVerifier::StartMergeSession,
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 AsWeakPtr()),
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Delegate::OnSessionMergeFailure,
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Unretained(delegate_)));
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
195558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid OAuth2LoginVerifier::OnGetTokenSuccess(
196558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    const OAuth2TokenService::Request* request,
197558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    const std::string& access_token,
198558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    const base::Time& expiration_time) {
199558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK_EQ(login_token_request_.get(), request);
200558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  login_token_request_.reset();
201558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(1) << "Got OAuth2 access token!";
203558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  retry_count_ = 0;
204558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  access_token_ = access_token;
205558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  StartOAuthLoginForUberToken();
206558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
207558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
208558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid OAuth2LoginVerifier::OnGetTokenFailure(
209558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    const OAuth2TokenService::Request* request,
210558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    const GoogleServiceAuthError& error) {
211558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
212558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK_EQ(login_token_request_.get(), request);
213558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  login_token_request_.reset();
214558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LOG(WARNING) << "Failed to get OAuth2 access token, "
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               << " error: " << error.state();
217558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  UMA_HISTOGRAM_ENUMERATION(
218558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      base::StringPrintf("OAuth2Login.%sFailure", "GetOAuth2AccessToken"),
219558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      error.state(),
220558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      GoogleServiceAuthError::NUM_STATES);
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  delegate_->OnSessionMergeFailure(IsConnectionOrServiceError(error));
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void OAuth2LoginVerifier::OnListAccountsSuccess(
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& data) {
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << "ListAccounts successful.";
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  delegate_->OnListAccountsSuccess(data);
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void OAuth2LoginVerifier::OnListAccountsFailure(
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GoogleServiceAuthError& error) {
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(WARNING) << "Failed to get list of session accounts, "
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << " error: " << error.state();
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RetryOnError(
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "ListAccounts",
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      error,
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&OAuth2LoginVerifier::StartAuthCookiesVerification,
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 AsWeakPtr()),
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&Delegate::OnListAccountsFailure,
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Unretained(delegate_)));
243558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
244558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OAuth2LoginVerifier::RetryOnError(const char* operation_id,
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const GoogleServiceAuthError& error,
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const base::Closure& task_to_retry,
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       const ErrorHandler& error_handler) {
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (IsConnectionOrServiceError(error) &&
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      retry_count_ < kMaxRequestAttemptCount) {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    retry_count_++;
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::StringPrintf("OAuth2Login.%sRetry", operation_id),
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        error.state(),
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GoogleServiceAuthError::NUM_STATES);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostDelayedTask(
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserThread::UI, FROM_HERE, task_to_retry,
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LOG(WARNING) << "Unrecoverable error or retry count max reached for "
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               << operation_id;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("OAuth2Login.%sFailure", operation_id),
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error.state(),
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GoogleServiceAuthError::NUM_STATES);
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error_handler.Run(IsConnectionOrServiceError(error));
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
273