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 "chromeos/login/auth/online_attempt.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop_proxy.h"
15 #include "chromeos/login/auth/auth_attempt_state.h"
16 #include "chromeos/login/auth/auth_attempt_state_resolver.h"
17 #include "chromeos/login/auth/key.h"
18 #include "chromeos/login/auth/user_context.h"
19 #include "components/user_manager/user_type.h"
20 #include "google_apis/gaia/gaia_auth_consumer.h"
21 #include "google_apis/gaia/gaia_auth_fetcher.h"
22 #include "google_apis/gaia/gaia_constants.h"
23 #include "net/base/load_flags.h"
24 #include "net/base/net_errors.h"
25 #include "net/url_request/url_request_status.h"
30 const int OnlineAttempt::kClientLoginTimeoutMs
= 10000;
32 OnlineAttempt::OnlineAttempt(AuthAttemptState
* current_attempt
,
33 AuthAttemptStateResolver
* callback
)
34 : message_loop_(base::MessageLoopProxy::current()),
35 attempt_(current_attempt
),
39 DCHECK(attempt_
->user_type
== user_manager::USER_TYPE_REGULAR
);
42 OnlineAttempt::~OnlineAttempt() {
44 if (client_fetcher_
.get())
45 client_fetcher_
->CancelRequest();
48 void OnlineAttempt::Initiate(net::URLRequestContextGetter
* request_context
) {
49 client_fetcher_
.reset(new GaiaAuthFetcher(
50 this, GaiaConstants::kChromeOSSource
, request_context
));
51 message_loop_
->PostTask(
53 base::Bind(&OnlineAttempt::TryClientLogin
, weak_factory_
.GetWeakPtr()));
56 void OnlineAttempt::OnClientLoginSuccess(
57 const GaiaAuthConsumer::ClientLoginResult
& unused
) {
58 VLOG(1) << "Online login successful!";
60 weak_factory_
.InvalidateWeakPtrs();
62 if (attempt_
->hosted_policy() == GaiaAuthFetcher::HostedAccountsAllowed
&&
63 attempt_
->is_first_time_user()) {
64 // First time user, and we don't know if the account is HOSTED or not.
65 // Since we don't allow HOSTED accounts to log in, we need to try
66 // again, without allowing HOSTED accounts.
68 // NOTE: we used to do this in the opposite order, so that we'd only
69 // try the HOSTED pathway if GOOGLE-only failed. This breaks CAPTCHA
71 attempt_
->DisableHosted();
75 TriggerResolve(AuthFailure::AuthFailureNone());
78 void OnlineAttempt::OnClientLoginFailure(const GoogleServiceAuthError
& error
) {
79 weak_factory_
.InvalidateWeakPtrs();
81 if (error
.state() == GoogleServiceAuthError::REQUEST_CANCELED
) {
84 // TODO(cmasone): add UMA tracking for this to see if we can remove it.
85 LOG(ERROR
) << "Login attempt canceled!?!? Trying again.";
89 LOG(ERROR
) << "Login attempt canceled again? Already retried...";
92 if (error
.state() == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
&&
93 attempt_
->is_first_time_user() &&
94 attempt_
->hosted_policy() != GaiaAuthFetcher::HostedAccountsAllowed
) {
95 // This was a first-time login, we already tried allowing HOSTED accounts
96 // and succeeded. That we've failed with INVALID_GAIA_CREDENTIALS now
97 // indicates that the account is HOSTED.
98 LOG(WARNING
) << "Rejecting valid HOSTED account.";
99 TriggerResolve(AuthFailure::FromNetworkAuthFailure(
100 GoogleServiceAuthError(GoogleServiceAuthError::HOSTED_NOT_ALLOWED
)));
104 if (error
.state() == GoogleServiceAuthError::TWO_FACTOR
) {
105 LOG(WARNING
) << "Two factor authenticated. Sync will not work.";
106 TriggerResolve(AuthFailure::AuthFailureNone());
110 VLOG(2) << "ClientLogin attempt failed with " << error
.state();
111 TriggerResolve(AuthFailure::FromNetworkAuthFailure(error
));
114 void OnlineAttempt::TryClientLogin() {
115 message_loop_
->PostDelayedTask(
117 base::Bind(&OnlineAttempt::CancelClientLogin
, weak_factory_
.GetWeakPtr()),
118 base::TimeDelta::FromMilliseconds(kClientLoginTimeoutMs
));
120 client_fetcher_
->StartClientLogin(
121 attempt_
->user_context
.GetUserID(),
122 attempt_
->user_context
.GetKey()->GetSecret(),
123 GaiaConstants::kSyncService
,
124 attempt_
->login_token
,
125 attempt_
->login_captcha
,
126 attempt_
->hosted_policy());
129 bool OnlineAttempt::HasPendingFetch() {
130 return client_fetcher_
->HasPendingFetch();
133 void OnlineAttempt::CancelRequest() {
134 weak_factory_
.InvalidateWeakPtrs();
137 void OnlineAttempt::CancelClientLogin() {
138 if (HasPendingFetch()) {
139 LOG(WARNING
) << "Canceling ClientLogin attempt.";
142 TriggerResolve(AuthFailure(AuthFailure::LOGIN_TIMED_OUT
));
146 void OnlineAttempt::TriggerResolve(const AuthFailure
& outcome
) {
147 attempt_
->RecordOnlineLoginStatus(outcome
);
148 client_fetcher_
.reset(NULL
);
149 resolver_
->Resolve();
152 } // namespace chromeos