summaryrefslogtreecommitdiffstats
path: root/chromeos/login
diff options
context:
space:
mode:
authorantrim@chromium.org <antrim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-19 15:50:01 +0000
committerantrim@chromium.org <antrim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-19 15:52:14 +0000
commit4cf25a21cd9cd7c74ea0c1e178685c45341d8802 (patch)
tree4e3189fba349875c183284c39414a41223176263 /chromeos/login
parent3074d78deed204dcf69c31c60c8dbfef2dc0ee46 (diff)
downloadchromium_src-4cf25a21cd9cd7c74ea0c1e178685c45341d8802.zip
chromium_src-4cf25a21cd9cd7c74ea0c1e178685c45341d8802.tar.gz
chromium_src-4cf25a21cd9cd7c74ea0c1e178685c45341d8802.tar.bz2
Refactoring : Move OnlineAttempt to chromeos/login
Also moved tpm_password_fetcher to chromeos/ and got rid of obsolette login/auth/mount_manager BUG=387613 R=nkostylev@chromium.org TBR=stevenjb@chromium.org Review URL: https://codereview.chromium.org/402403004 Cr-Commit-Position: refs/heads/master@{#290562} git-svn-id: svn://svn.chromium.org/chrome/trunk/src@290562 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/login')
-rw-r--r--chromeos/login/auth/mock_url_fetchers.cc176
-rw-r--r--chromeos/login/auth/mock_url_fetchers.h129
-rw-r--r--chromeos/login/auth/online_attempt.cc152
-rw-r--r--chromeos/login/auth/online_attempt.h83
-rw-r--r--chromeos/login/auth/online_attempt_host.cc63
-rw-r--r--chromeos/login/auth/online_attempt_host.h71
6 files changed, 674 insertions, 0 deletions
diff --git a/chromeos/login/auth/mock_url_fetchers.cc b/chromeos/login/auth/mock_url_fetchers.cc
new file mode 100644
index 0000000..a794426
--- /dev/null
+++ b/chromeos/login/auth/mock_url_fetchers.cc
@@ -0,0 +1,176 @@
+// Copyright 2014 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 "chromeos/login/auth/mock_url_fetchers.h"
+
+#include <errno.h>
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/stringprintf.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_status.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace chromeos {
+
+ExpectCanceledFetcher::ExpectCanceledFetcher(
+ bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d)
+ : net::TestURLFetcher(0, url, d), weak_factory_(this) {
+}
+
+ExpectCanceledFetcher::~ExpectCanceledFetcher() {
+}
+
+void ExpectCanceledFetcher::Start() {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ExpectCanceledFetcher::CompleteFetch,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(100));
+}
+
+void ExpectCanceledFetcher::CompleteFetch() {
+ ADD_FAILURE() << "Fetch completed in ExpectCanceledFetcher!";
+ base::MessageLoop::current()->Quit(); // Allow exiting even if we mess up.
+}
+
+GotCanceledFetcher::GotCanceledFetcher(
+ bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d)
+ : net::TestURLFetcher(0, url, d) {
+ set_url(url);
+ set_status(net::URLRequestStatus(net::URLRequestStatus::CANCELED, 0));
+ set_response_code(net::HTTP_FORBIDDEN);
+}
+
+GotCanceledFetcher::~GotCanceledFetcher() {
+}
+
+void GotCanceledFetcher::Start() {
+ delegate()->OnURLFetchComplete(this);
+}
+
+SuccessFetcher::SuccessFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d)
+ : net::TestURLFetcher(0, url, d) {
+ set_url(url);
+ set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0));
+ set_response_code(net::HTTP_OK);
+}
+
+SuccessFetcher::~SuccessFetcher() {
+}
+
+void SuccessFetcher::Start() {
+ delegate()->OnURLFetchComplete(this);
+}
+
+FailFetcher::FailFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d)
+ : net::TestURLFetcher(0, url, d) {
+ set_url(url);
+ set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, ECONNRESET));
+ set_response_code(net::HTTP_OK);
+}
+
+FailFetcher::~FailFetcher() {
+}
+
+void FailFetcher::Start() {
+ delegate()->OnURLFetchComplete(this);
+}
+
+// static
+const char CaptchaFetcher::kCaptchaToken[] = "token";
+// static
+const char CaptchaFetcher::kCaptchaUrlBase[] = "http://accounts.google.com/";
+// static
+const char CaptchaFetcher::kCaptchaUrlFragment[] = "fragment";
+// static
+const char CaptchaFetcher::kUnlockUrl[] = "http://what.ever";
+
+CaptchaFetcher::CaptchaFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d)
+ : net::TestURLFetcher(0, url, d) {
+ set_url(url);
+ set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0));
+ set_response_code(net::HTTP_FORBIDDEN);
+ SetResponseString(base::StringPrintf(
+ "Error=%s\n"
+ "Url=%s\n"
+ "CaptchaUrl=%s\n"
+ "CaptchaToken=%s\n",
+ "CaptchaRequired",
+ kUnlockUrl,
+ kCaptchaUrlFragment,
+ kCaptchaToken));
+}
+
+CaptchaFetcher::~CaptchaFetcher() {
+}
+
+// static
+std::string CaptchaFetcher::GetCaptchaToken() {
+ return kCaptchaToken;
+}
+
+// static
+std::string CaptchaFetcher::GetCaptchaUrl() {
+ return std::string(kCaptchaUrlBase).append(kCaptchaUrlFragment);
+}
+
+// static
+std::string CaptchaFetcher::GetUnlockUrl() {
+ return kUnlockUrl;
+}
+
+void CaptchaFetcher::Start() {
+ delegate()->OnURLFetchComplete(this);
+}
+
+HostedFetcher::HostedFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d)
+ : net::TestURLFetcher(0, url, d) {
+ set_url(url);
+ set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0));
+ set_response_code(net::HTTP_OK);
+}
+
+HostedFetcher::~HostedFetcher() {
+}
+
+void HostedFetcher::Start() {
+ VLOG(1) << upload_data();
+ if (upload_data().find("HOSTED") == std::string::npos) {
+ VLOG(1) << "HostedFetcher failing request";
+ set_response_code(net::HTTP_FORBIDDEN);
+ SetResponseString("Error=BadAuthentication");
+ }
+ delegate()->OnURLFetchComplete(this);
+}
+
+} // namespace chromeos
diff --git a/chromeos/login/auth/mock_url_fetchers.h b/chromeos/login/auth/mock_url_fetchers.h
new file mode 100644
index 0000000..703c466
--- /dev/null
+++ b/chromeos/login/auth/mock_url_fetchers.h
@@ -0,0 +1,129 @@
+// Copyright 2014 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.
+
+#ifndef CHROMEOS_LOGIN_AUTH_MOCK_URL_FETCHERS_H_
+#define CHROMEOS_LOGIN_AUTH_MOCK_URL_FETCHERS_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "chromeos/chromeos_export.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
+
+namespace net {
+class URLFetcherDelegate;
+}
+
+namespace chromeos {
+
+// Simulates a URL fetch by posting a delayed task. This fetch expects to be
+// canceled, and fails the test if it is not
+class ExpectCanceledFetcher : public net::TestURLFetcher {
+ public:
+ ExpectCanceledFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d);
+ virtual ~ExpectCanceledFetcher();
+
+ virtual void Start() OVERRIDE;
+
+ void CompleteFetch();
+
+ private:
+ base::WeakPtrFactory<ExpectCanceledFetcher> weak_factory_;
+ DISALLOW_COPY_AND_ASSIGN(ExpectCanceledFetcher);
+};
+
+class GotCanceledFetcher : public net::TestURLFetcher {
+ public:
+ GotCanceledFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d);
+ virtual ~GotCanceledFetcher();
+
+ virtual void Start() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GotCanceledFetcher);
+};
+
+class SuccessFetcher : public net::TestURLFetcher {
+ public:
+ SuccessFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d);
+ virtual ~SuccessFetcher();
+
+ virtual void Start() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SuccessFetcher);
+};
+
+class FailFetcher : public net::TestURLFetcher {
+ public:
+ FailFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d);
+ virtual ~FailFetcher();
+
+ virtual void Start() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FailFetcher);
+};
+
+class CaptchaFetcher : public net::TestURLFetcher {
+ public:
+ CaptchaFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d);
+ virtual ~CaptchaFetcher();
+
+ static std::string GetCaptchaToken();
+ static std::string GetCaptchaUrl();
+ static std::string GetUnlockUrl();
+
+ virtual void Start() OVERRIDE;
+
+ private:
+ static const char kCaptchaToken[];
+ static const char kCaptchaUrlBase[];
+ static const char kCaptchaUrlFragment[];
+ static const char kUnlockUrl[];
+ DISALLOW_COPY_AND_ASSIGN(CaptchaFetcher);
+};
+
+class HostedFetcher : public net::TestURLFetcher {
+ public:
+ HostedFetcher(bool success,
+ const GURL& url,
+ const std::string& results,
+ net::URLFetcher::RequestType request_type,
+ net::URLFetcherDelegate* d);
+ virtual ~HostedFetcher();
+
+ virtual void Start() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HostedFetcher);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_LOGIN_AUTH_MOCK_URL_FETCHERS_H_
diff --git a/chromeos/login/auth/online_attempt.cc b/chromeos/login/auth/online_attempt.cc
new file mode 100644
index 0000000..fc728f6
--- /dev/null
+++ b/chromeos/login/auth/online_attempt.cc
@@ -0,0 +1,152 @@
+// Copyright 2014 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 "chromeos/login/auth/online_attempt.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chromeos/login/auth/auth_attempt_state.h"
+#include "chromeos/login/auth/auth_attempt_state_resolver.h"
+#include "chromeos/login/auth/key.h"
+#include "chromeos/login/auth/user_context.h"
+#include "components/user_manager/user_type.h"
+#include "google_apis/gaia/gaia_auth_consumer.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "net/base/load_flags.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request_status.h"
+
+namespace chromeos {
+
+// static
+const int OnlineAttempt::kClientLoginTimeoutMs = 10000;
+
+OnlineAttempt::OnlineAttempt(AuthAttemptState* current_attempt,
+ AuthAttemptStateResolver* callback)
+ : message_loop_(base::MessageLoopProxy::current()),
+ attempt_(current_attempt),
+ resolver_(callback),
+ weak_factory_(this),
+ try_again_(true) {
+ DCHECK(attempt_->user_type == user_manager::USER_TYPE_REGULAR);
+}
+
+OnlineAttempt::~OnlineAttempt() {
+ // Just to be sure.
+ if (client_fetcher_.get())
+ client_fetcher_->CancelRequest();
+}
+
+void OnlineAttempt::Initiate(net::URLRequestContextGetter* request_context) {
+ client_fetcher_.reset(new GaiaAuthFetcher(
+ this, GaiaConstants::kChromeOSSource, request_context));
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&OnlineAttempt::TryClientLogin, weak_factory_.GetWeakPtr()));
+}
+
+void OnlineAttempt::OnClientLoginSuccess(
+ const GaiaAuthConsumer::ClientLoginResult& unused) {
+ VLOG(1) << "Online login successful!";
+
+ weak_factory_.InvalidateWeakPtrs();
+
+ if (attempt_->hosted_policy() == GaiaAuthFetcher::HostedAccountsAllowed &&
+ attempt_->is_first_time_user()) {
+ // First time user, and we don't know if the account is HOSTED or not.
+ // Since we don't allow HOSTED accounts to log in, we need to try
+ // again, without allowing HOSTED accounts.
+ //
+ // NOTE: we used to do this in the opposite order, so that we'd only
+ // try the HOSTED pathway if GOOGLE-only failed. This breaks CAPTCHA
+ // handling, though.
+ attempt_->DisableHosted();
+ TryClientLogin();
+ return;
+ }
+ TriggerResolve(AuthFailure::AuthFailureNone());
+}
+
+void OnlineAttempt::OnClientLoginFailure(const GoogleServiceAuthError& error) {
+ weak_factory_.InvalidateWeakPtrs();
+
+ if (error.state() == GoogleServiceAuthError::REQUEST_CANCELED) {
+ if (try_again_) {
+ try_again_ = false;
+ // TODO(cmasone): add UMA tracking for this to see if we can remove it.
+ LOG(ERROR) << "Login attempt canceled!?!? Trying again.";
+ TryClientLogin();
+ return;
+ }
+ LOG(ERROR) << "Login attempt canceled again? Already retried...";
+ }
+
+ if (error.state() == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS &&
+ attempt_->is_first_time_user() &&
+ attempt_->hosted_policy() != GaiaAuthFetcher::HostedAccountsAllowed) {
+ // This was a first-time login, we already tried allowing HOSTED accounts
+ // and succeeded. That we've failed with INVALID_GAIA_CREDENTIALS now
+ // indicates that the account is HOSTED.
+ LOG(WARNING) << "Rejecting valid HOSTED account.";
+ TriggerResolve(AuthFailure::FromNetworkAuthFailure(
+ GoogleServiceAuthError(GoogleServiceAuthError::HOSTED_NOT_ALLOWED)));
+ return;
+ }
+
+ if (error.state() == GoogleServiceAuthError::TWO_FACTOR) {
+ LOG(WARNING) << "Two factor authenticated. Sync will not work.";
+ TriggerResolve(AuthFailure::AuthFailureNone());
+
+ return;
+ }
+ VLOG(2) << "ClientLogin attempt failed with " << error.state();
+ TriggerResolve(AuthFailure::FromNetworkAuthFailure(error));
+}
+
+void OnlineAttempt::TryClientLogin() {
+ message_loop_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&OnlineAttempt::CancelClientLogin, weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kClientLoginTimeoutMs));
+
+ client_fetcher_->StartClientLogin(
+ attempt_->user_context.GetUserID(),
+ attempt_->user_context.GetKey()->GetSecret(),
+ GaiaConstants::kSyncService,
+ attempt_->login_token,
+ attempt_->login_captcha,
+ attempt_->hosted_policy());
+}
+
+bool OnlineAttempt::HasPendingFetch() {
+ return client_fetcher_->HasPendingFetch();
+}
+
+void OnlineAttempt::CancelRequest() {
+ weak_factory_.InvalidateWeakPtrs();
+}
+
+void OnlineAttempt::CancelClientLogin() {
+ if (HasPendingFetch()) {
+ LOG(WARNING) << "Canceling ClientLogin attempt.";
+ CancelRequest();
+
+ TriggerResolve(AuthFailure(AuthFailure::LOGIN_TIMED_OUT));
+ }
+}
+
+void OnlineAttempt::TriggerResolve(const AuthFailure& outcome) {
+ attempt_->RecordOnlineLoginStatus(outcome);
+ client_fetcher_.reset(NULL);
+ resolver_->Resolve();
+}
+
+} // namespace chromeos
diff --git a/chromeos/login/auth/online_attempt.h b/chromeos/login/auth/online_attempt.h
new file mode 100644
index 0000000..c91d064
--- /dev/null
+++ b/chromeos/login/auth/online_attempt.h
@@ -0,0 +1,83 @@
+// Copyright 2014 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.
+
+#ifndef CHROMEOS_LOGIN_AUTH_ONLINE_ATTEMPT_H_
+#define CHROMEOS_LOGIN_AUTH_ONLINE_ATTEMPT_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/login/auth/auth_status_consumer.h"
+#include "google_apis/gaia/gaia_auth_consumer.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+class GaiaAuthFetcher;
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace chromeos {
+class AuthAttemptState;
+class AuthAttemptStateResolver;
+
+class CHROMEOS_EXPORT OnlineAttempt : public GaiaAuthConsumer {
+ public:
+ OnlineAttempt(AuthAttemptState* current_attempt,
+ AuthAttemptStateResolver* callback);
+ virtual ~OnlineAttempt();
+
+ // Initiate the online login attempt either through client or auth login.
+ // Status will be recorded in |current_attempt|, and resolver_->Resolve() will
+ // be called on the IO thread when useful state is available.
+ // Must be called on the UI thread.
+ void Initiate(net::URLRequestContextGetter* request_context);
+
+ // GaiaAuthConsumer overrides. Callbacks from GaiaAuthFetcher
+ virtual void OnClientLoginFailure(
+ const GoogleServiceAuthError& error) OVERRIDE;
+ virtual void OnClientLoginSuccess(
+ const GaiaAuthConsumer::ClientLoginResult& credentials) OVERRIDE;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(OnlineAttemptTest, LoginSuccess);
+ FRIEND_TEST_ALL_PREFIXES(OnlineAttemptTest, TwoFactorSuccess);
+
+ // Milliseconds until we timeout our attempt to hit ClientLogin.
+ static const int kClientLoginTimeoutMs;
+
+ void TryClientLogin();
+ void CancelClientLogin();
+
+ void TriggerResolve(const AuthFailure& outcome);
+
+ bool HasPendingFetch();
+ void CancelRequest();
+
+ scoped_refptr<base::MessageLoopProxy> message_loop_;
+
+ AuthAttemptState* const attempt_;
+ AuthAttemptStateResolver* const resolver_;
+
+ // Handles ClientLogin communications with Gaia.
+ scoped_ptr<GaiaAuthFetcher> client_fetcher_;
+
+ // Used to cancel the CancelClientLogin closure.
+ base::WeakPtrFactory<OnlineAttempt> weak_factory_;
+
+ // Whether we're willing to re-try the ClientLogin attempt.
+ bool try_again_;
+
+ friend class OnlineAttemptTest;
+ DISALLOW_COPY_AND_ASSIGN(OnlineAttempt);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_LOGIN_AUTH_ONLINE_ATTEMPT_H_
diff --git a/chromeos/login/auth/online_attempt_host.cc b/chromeos/login/auth/online_attempt_host.cc
new file mode 100644
index 0000000..6b742f8
--- /dev/null
+++ b/chromeos/login/auth/online_attempt_host.cc
@@ -0,0 +1,63 @@
+// Copyright 2014 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 "chromeos/login/auth/online_attempt_host.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chromeos/login/auth/auth_attempt_state.h"
+#include "chromeos/login/auth/online_attempt.h"
+#include "chromeos/login/auth/user_context.h"
+#include "components/user_manager/user_type.h"
+
+namespace chromeos {
+
+OnlineAttemptHost::OnlineAttemptHost(Delegate* delegate)
+ : message_loop_(base::MessageLoopProxy::current()),
+ delegate_(delegate),
+ weak_ptr_factory_(this) {
+}
+
+OnlineAttemptHost::~OnlineAttemptHost() {
+ Reset();
+}
+
+void OnlineAttemptHost::Check(net::URLRequestContextGetter* request_context,
+ const UserContext& user_context) {
+ if (user_context != current_attempt_user_context_) {
+ Reset();
+ current_attempt_user_context_ = user_context;
+
+ state_.reset(new AuthAttemptState(user_context,
+ user_manager::USER_TYPE_REGULAR,
+ false, // unlock
+ false, // online_complete
+ false)); // user_is_new
+ online_attempt_.reset(new OnlineAttempt(state_.get(), this));
+ online_attempt_->Initiate(request_context);
+ }
+}
+
+void OnlineAttemptHost::Reset() {
+ online_attempt_.reset(NULL);
+ current_attempt_user_context_ = UserContext();
+}
+
+void OnlineAttemptHost::Resolve() {
+ if (state_->online_complete()) {
+ bool success = state_->online_outcome().reason() == AuthFailure::NONE;
+ message_loop_->PostTask(FROM_HERE,
+ base::Bind(&OnlineAttemptHost::ResolveOnUIThread,
+ weak_ptr_factory_.GetWeakPtr(),
+ success));
+ }
+}
+
+void OnlineAttemptHost::ResolveOnUIThread(bool success) {
+ delegate_->OnChecked(current_attempt_user_context_.GetUserID(), success);
+ Reset();
+}
+
+} // namespace chromeos
diff --git a/chromeos/login/auth/online_attempt_host.h b/chromeos/login/auth/online_attempt_host.h
new file mode 100644
index 0000000..8d49a7b
--- /dev/null
+++ b/chromeos/login/auth/online_attempt_host.h
@@ -0,0 +1,71 @@
+// Copyright 2014 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.
+
+#ifndef CHROMEOS_LOGIN_AUTH_ONLINE_ATTEMPT_HOST_H_
+#define CHROMEOS_LOGIN_AUTH_ONLINE_ATTEMPT_HOST_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/login/auth/auth_attempt_state_resolver.h"
+#include "chromeos/login/auth/user_context.h"
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace chromeos {
+
+class AuthAttemptState;
+class OnlineAttempt;
+class UserContext;
+
+// Helper class which hosts OnlineAttempt for online credentials checking.
+class CHROMEOS_EXPORT OnlineAttemptHost : public AuthAttemptStateResolver {
+ public:
+ class Delegate {
+ public:
+ // Called after user_context were checked online.
+ virtual void OnChecked(const std::string& username, bool success) = 0;
+ };
+
+ explicit OnlineAttemptHost(Delegate* delegate);
+ virtual ~OnlineAttemptHost();
+
+ // Performs an online check of the credentials in |request_context| and
+ // invokes
+ // the delegate's OnChecked() with the result. Note that only one check can be
+ // in progress at any given time. If this method is invoked with a different
+ // |user_context| than a check currently in progress, the current check will
+ // be silently aborted.
+ void Check(net::URLRequestContextGetter* request_context,
+ const UserContext& user_context);
+
+ // Resets the checking process.
+ void Reset();
+
+ // AuthAttemptStateResolver overrides.
+ // Executed on IO thread.
+ virtual void Resolve() OVERRIDE;
+
+ // Does an actual resolve on UI thread.
+ void ResolveOnUIThread(bool success);
+
+ private:
+ scoped_refptr<base::MessageLoopProxy> message_loop_;
+ Delegate* delegate_;
+ UserContext current_attempt_user_context_;
+ scoped_ptr<OnlineAttempt> online_attempt_;
+ scoped_ptr<AuthAttemptState> state_;
+ base::WeakPtrFactory<OnlineAttemptHost> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(OnlineAttemptHost);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_LOGIN_AUTH_ONLINE_ATTEMPT_HOST_H_