Chromium Code Reviews| Index: chrome/browser/chromeos/login/oauth2_login_verifier.cc |
| diff --git a/chrome/browser/chromeos/login/oauth2_login_verifier.cc b/chrome/browser/chromeos/login/oauth2_login_verifier.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a75f7dfa6ca81944e3f94470930435f9340d638b |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/login/oauth2_login_verifier.cc |
| @@ -0,0 +1,192 @@ |
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/chromeos/login/oauth2_login_verifier.h" |
| + |
| +#include "base/logging.h" |
| +#include "base/metrics/histogram.h" |
| +#include "base/stringprintf.h" |
| +#include "chrome/browser/chromeos/cros/cros_library.h" |
| +#include "chrome/browser/chromeos/cros/network_library.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "google_apis/gaia/gaia_constants.h" |
| +#include "google_apis/gaia/gaia_urls.h" |
| +#include "google_apis/gaia/oauth2_access_token_fetcher.h" |
|
Joao da Silva
2013/01/11 16:45:07
Already in .h
zel
2013/01/11 19:51:16
Done.
|
| + |
| +using content::BrowserThread; |
| + |
| +namespace { |
| + |
| +// OAuth token request max retry count. |
| +const int kMaxRequestAttemptCount = 5; |
| +// OAuth token request retry delay in milliseconds. |
| +const int kRequestRestartDelay = 3000; |
| + |
| +// The service scope of the OAuth v2 token that ChromeOS login will be |
| +// requesting. |
| +const char kServiceScopeChromeOS[] = |
|
Joao da Silva
2013/01/11 16:45:07
Not used, did you mean to include in |scopes| belo
zel
2013/01/11 19:51:16
Done.
|
| + "https://www.googleapis.com/auth/chromesync"; |
| + |
| +const char kOAuthLoginServiceScope[] = |
|
Joao da Silva
2013/01/11 16:45:07
GaiaUrls::oauth1_login_scope()?
zel
2013/01/11 19:51:16
Done.
|
| + "https://www.google.com/accounts/OAuthLogin"; |
| + |
| +} // namespace |
| + |
| +namespace chromeos { |
| + |
| +OAuth2LoginVerifier::OAuth2LoginVerifier( |
| + OAuth2LoginVerifier::Delegate* delegate, |
| + net::URLRequestContextGetter* system_request_context, |
| + net::URLRequestContextGetter* user_request_context) |
| + : delegate_(delegate), |
| + token_fetcher_(this, system_request_context), |
|
Joao da Silva
2013/01/11 16:45:07
ALLOW_THIS_IN_INITIALIZER_LIST (also below)
zel
2013/01/11 19:51:16
Done.
|
| + gaia_fetcher_(this, std::string(GaiaConstants::kChromeOSSource), |
| + user_request_context), |
| + retry_count_(0) { |
| + DCHECK(delegate); |
| +} |
| + |
| +OAuth2LoginVerifier::~OAuth2LoginVerifier() { |
| +} |
| + |
| +void OAuth2LoginVerifier::VerifyRefreshToken(const std::string& refresh_token) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + if (CrosLibrary::Get()->libcros_loaded()) { |
| + // Delay the verification if the network is not connected or on a captive |
| + // portal. |
| + const Network* network = |
| + CrosLibrary::Get()->GetNetworkLibrary()->active_network(); |
| + if (!network || !network->connected() || network->restricted_pool()) { |
| + // If network is offline, defer the token fetching until online. |
| + VLOG(1) << "Network is offline. Deferring OAuth2 access token fetch."; |
| + BrowserThread::PostDelayedTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&OAuth2LoginVerifier::VerifyRefreshToken, |
| + AsWeakPtr(), |
| + refresh_token), |
| + base::TimeDelta::FromMilliseconds(kRequestRestartDelay)); |
|
Joao da Silva
2013/01/11 16:45:07
#include "base/time.h"
zel
2013/01/11 19:51:16
Done.
|
| + return; |
| + } |
| + } |
| + |
| + access_token_.clear(); |
| + refresh_token_ = refresh_token; |
| + std::vector<std::string> scopes; |
|
Joao da Silva
2013/01/11 16:45:07
#include <vector>
zel
2013/01/11 19:51:16
Done.
|
| + scopes.push_back(kOAuthLoginServiceScope); |
| + token_fetcher_.Start(GaiaUrls::GetInstance()->oauth2_chrome_client_id(), |
| + GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), |
| + refresh_token, |
| + scopes); |
| +} |
| + |
| +void OAuth2LoginVerifier::OnGetTokenSuccess( |
| + const std::string& access_token, const base::Time& expiration_time) { |
| + VLOG(1) << "Got OAuth2 access token!"; |
| + retry_count_ = 0; |
| + access_token_ = access_token; |
| + StartOAuthLogin(); |
| +} |
| + |
| +void OAuth2LoginVerifier::StartOAuthLogin() { |
| + gaia_fetcher_.StartOAuthLogin(access_token_, |
| + GaiaConstants::kSyncService); |
| +} |
| + |
| +void OAuth2LoginVerifier::OnGetTokenFailure( |
| + const GoogleServiceAuthError& error) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + LOG(WARNING) << "Failed to hget OAuth2 access token, " |
|
Joao da Silva
2013/01/11 16:45:07
*get
zel
2013/01/11 19:51:16
Done.
|
| + << " error: " << error.state(); |
| + RetryOnError("GetToken", error, |
| + base::Bind(&OAuth2LoginVerifier::VerifyRefreshToken, |
| + AsWeakPtr(), |
| + refresh_token_)); |
| +} |
| + |
| +void OAuth2LoginVerifier::OnClientLoginSuccess( |
| + const ClientLoginResult& result) { |
| + LOG(WARNING) << "OAuthLogin successful!"; |
|
Joao da Silva
2013/01/11 16:45:07
warning or vlog(1)?
zel
2013/01/11 19:51:16
Nope, I really want this in user feedback logs as
|
| + sid_ = result.sid; |
| + lsid_ = result.lsid; |
| + token_ = result.token; |
| + retry_count_ = 0; |
| + StartCookiesRetrieval(); |
| +} |
| + |
| +void OAuth2LoginVerifier::OnClientLoginFailure( |
| + const GoogleServiceAuthError& error) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + LOG(WARNING) << "Failed to log in with OAuth1 access tokens," |
|
Joao da Silva
2013/01/11 16:45:07
OAuth2
zel
2013/01/11 19:51:16
Done.
|
| + << " error: " << error.state(); |
| + RetryOnError("OAuthLogin", error, |
| + base::Bind(&OAuth2LoginVerifier::StartOAuthLogin, |
| + AsWeakPtr())); |
| +} |
| + |
| +void OAuth2LoginVerifier::StartCookiesRetrieval() { |
| + DCHECK(!sid_.empty()); |
| + DCHECK(!lsid_.empty()); |
| + gaia_fetcher_.StartIssueAuthToken(sid_, lsid_, GaiaConstants::kGaiaService); |
| +} |
| + |
| +void OAuth2LoginVerifier::OnIssueAuthTokenSuccess( |
| + const std::string& service, |
| + const std::string& token_token) { |
| + LOG(WARNING) << "Got auth token!"; |
|
Joao da Silva
2013/01/11 16:45:07
warning or vlog(1)?
zel
2013/01/11 19:51:16
Same as above.
|
| + retry_count_ = 0; |
| + gaia_fetcher_.StartMergeSession(token_token); |
| +} |
| + |
| +void OAuth2LoginVerifier::OnIssueAuthTokenFailure( |
| + const std::string& service, |
| + const GoogleServiceAuthError& error) { |
| + LOG(WARNING) << "Failed IssueAuthToken request," |
| + << " error:" << error.state(); |
| + RetryOnError("IssueAuthToken", error, |
| + base::Bind(&OAuth2LoginVerifier::StartCookiesRetrieval, |
| + AsWeakPtr())); |
| +} |
| + |
| +void OAuth2LoginVerifier::OnMergeSessionSuccess(const std::string& data) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + LOG(WARNING) << "MergeSession successful."; |
|
Joao da Silva
2013/01/11 16:45:07
warning or vlog?
zel
2013/01/11 19:51:16
Same as above.
|
| + delegate_->OnOAuth2LoginVerifierSuccess(sid_, lsid_, token_); |
| +} |
| + |
| +void OAuth2LoginVerifier::OnMergeSessionFailure( |
| + const GoogleServiceAuthError& error) { |
| + LOG(WARNING) << "Failed MergeSession request," |
| + << " error: " << error.state(); |
| + RetryOnError("MergeSession", error, |
| + base::Bind(&OAuth2LoginVerifier::StartCookiesRetrieval, |
|
Joao da Silva
2013/01/11 16:45:07
Is the retry callback StartCookiesRetrieval, or sh
zel
2013/01/11 19:51:16
Well, the token that we fetched with /IssueAuthTok
|
| + AsWeakPtr())); |
| +} |
| + |
| +void OAuth2LoginVerifier::RetryOnError(const char* operation_id, |
| + const GoogleServiceAuthError& error, |
| + const base::Closure& task) { |
| + if ((error.state() == GoogleServiceAuthError::CONNECTION_FAILED || |
| + error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE || |
| + error.state() == GoogleServiceAuthError::REQUEST_CANCELED) && |
| + retry_count_ < kMaxRequestAttemptCount) { |
| + retry_count_++; |
| + UMA_HISTOGRAM_ENUMERATION( |
| + base::StringPrintf("OAuth2LoginVerifier.%sWithRetry", operation_id), |
| + error.state(), |
| + GoogleServiceAuthError::NUM_STATES); |
| + BrowserThread::PostDelayedTask( |
| + BrowserThread::UI, FROM_HERE, task, |
| + base::TimeDelta::FromMilliseconds(kRequestRestartDelay)); |
| + } else { |
| + LOG(WARNING) << "Unrecoverable error or retry count max reached for " |
| + << operation_id; |
| + UMA_HISTOGRAM_ENUMERATION( |
| + base::StringPrintf("OAuth2LoginVerifier.%sWithNoRetry", operation_id), |
| + error.state(), |
| + GoogleServiceAuthError::NUM_STATES); |
| + delegate_->OnOAuth2LoginVerifierFaulure(); |
|
Joao da Silva
2013/01/11 16:45:07
*Failure
zel
2013/01/11 19:51:16
Done.
|
| + } |
| +} |
| + |
| +} // namespace chromeos |