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/login_performer.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/user_metrics.h"
12 #include "base/metrics/user_metrics_action.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/thread_restrictions.h"
16 #include "chromeos/dbus/dbus_thread_manager.h"
17 #include "chromeos/dbus/session_manager_client.h"
18 #include "chromeos/login/user_names.h"
19 #include "chromeos/login_event_recorder.h"
20 #include "chromeos/settings/cros_settings_names.h"
21 #include "google_apis/gaia/gaia_auth_util.h"
22 #include "net/cookies/cookie_monster.h"
23 #include "net/cookies/cookie_store.h"
24 #include "net/url_request/url_request_context.h"
25 #include "net/url_request/url_request_context_getter.h"
27 using base::UserMetricsAction
;
31 LoginPerformer::LoginPerformer(scoped_refptr
<base::TaskRunner
> task_runner
,
33 : delegate_(delegate
),
34 task_runner_(task_runner
),
35 online_attempt_host_(this),
36 last_login_failure_(AuthFailure::AuthFailureNone()),
37 password_changed_(false),
38 password_changed_callback_count_(0),
39 auth_mode_(AUTH_MODE_INTERNAL
),
43 LoginPerformer::~LoginPerformer() {
44 DVLOG(1) << "Deleting LoginPerformer";
45 if (authenticator_
.get())
46 authenticator_
->SetConsumer(NULL
);
47 if (extended_authenticator_
.get())
48 extended_authenticator_
->SetConsumer(NULL
);
51 ////////////////////////////////////////////////////////////////////////////////
52 // LoginPerformer, AuthStatusConsumer implementation:
54 void LoginPerformer::OnAuthFailure(const AuthFailure
& failure
) {
55 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
56 base::RecordAction(UserMetricsAction("Login_Failure"));
58 UMA_HISTOGRAM_ENUMERATION("Login.FailureReason",
60 AuthFailure::NUM_FAILURE_REASONS
);
62 DVLOG(1) << "failure.reason " << failure
.reason();
63 DVLOG(1) << "failure.error.state " << failure
.error().state();
65 last_login_failure_
= failure
;
67 delegate_
->OnAuthFailure(failure
);
70 // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS:
71 // happens during offline auth only.
76 void LoginPerformer::OnAuthSuccess(const UserContext
& user_context
) {
77 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
78 base::RecordAction(UserMetricsAction("Login_Success"));
79 VLOG(1) << "LoginSuccess hash: " << user_context
.GetUserIDHash();
81 // After delegate_->OnAuthSuccess(...) is called, delegate_ releases
82 // LoginPerformer ownership. LP now manages it's lifetime on its own.
83 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
84 delegate_
->OnAuthSuccess(user_context
);
87 void LoginPerformer::OnOffTheRecordAuthSuccess() {
88 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
89 base::RecordAction(UserMetricsAction("Login_GuestLoginSuccess"));
92 delegate_
->OnOffTheRecordAuthSuccess();
97 void LoginPerformer::OnPasswordChangeDetected() {
98 password_changed_
= true;
99 password_changed_callback_count_
++;
101 delegate_
->OnPasswordChangeDetected();
107 void LoginPerformer::OnChecked(const std::string
& user_id
, bool success
) {
109 // Delegate is reset in case of successful offline login.
110 // See ExistingUserConstoller::OnAuthSuccess().
111 // Case when user has changed password and enters old password
112 // does not block user from sign in yet.
115 delegate_
->OnOnlineChecked(user_id
, success
);
118 ////////////////////////////////////////////////////////////////////////////////
119 // LoginPerformer, public:
121 void LoginPerformer::NotifyWhitelistCheckFailure() {
123 delegate_
->WhiteListCheckFailed(user_context_
.GetUserID());
128 void LoginPerformer::PerformLogin(const UserContext
& user_context
,
129 AuthorizationMode auth_mode
) {
130 auth_mode_
= auth_mode
;
131 user_context_
= user_context
;
133 if (RunTrustedCheck(base::Bind(&LoginPerformer::DoPerformLogin
,
134 weak_factory_
.GetWeakPtr(),
139 DoPerformLogin(user_context_
, auth_mode
);
142 void LoginPerformer::DoPerformLogin(const UserContext
& user_context
,
143 AuthorizationMode auth_mode
) {
144 std::string email
= gaia::CanonicalizeEmail(user_context
.GetUserID());
145 bool wildcard_match
= false;
146 if (!IsUserWhitelisted(email
, &wildcard_match
)) {
147 NotifyWhitelistCheckFailure();
151 if (user_context
.GetAuthFlow() == UserContext::AUTH_FLOW_EASY_UNLOCK
)
152 SetupEasyUnlockUserFlow(user_context
.GetUserID());
154 switch (auth_mode_
) {
155 case AUTH_MODE_EXTENSION
: {
156 RunOnlineWhitelistCheck(
159 base::Bind(&LoginPerformer::StartLoginCompletion
,
160 weak_factory_
.GetWeakPtr()),
161 base::Bind(&LoginPerformer::NotifyWhitelistCheckFailure
,
162 weak_factory_
.GetWeakPtr()));
165 case AUTH_MODE_INTERNAL
:
166 StartAuthentication();
171 void LoginPerformer::LoginAsSupervisedUser(const UserContext
& user_context
) {
172 DCHECK_EQ(chromeos::login::kSupervisedUserDomain
,
173 gaia::ExtractDomainName(user_context
.GetUserID()));
175 user_context_
= user_context
;
177 if (RunTrustedCheck(base::Bind(&LoginPerformer::TrustedLoginAsSupervisedUser
,
178 weak_factory_
.GetWeakPtr(),
182 TrustedLoginAsSupervisedUser(user_context_
);
185 void LoginPerformer::TrustedLoginAsSupervisedUser(
186 const UserContext
& user_context
) {
187 if (!AreSupervisedUsersAllowed()) {
188 LOG(ERROR
) << "Login attempt of supervised user detected.";
189 delegate_
->WhiteListCheckFailed(user_context
.GetUserID());
193 SetupSupervisedUserFlow(user_context
.GetUserID());
194 UserContext user_context_copy
= TransformSupervisedKey(user_context
);
196 if (UseExtendedAuthenticatorForSupervisedUser(user_context
)) {
197 EnsureExtendedAuthenticator();
198 // TODO(antrim) : Replace empty callback with explicit method.
199 // http://crbug.com/351268
200 task_runner_
->PostTask(
202 base::Bind(&ExtendedAuthenticator::AuthenticateToMount
,
203 extended_authenticator_
.get(),
205 ExtendedAuthenticator::ResultCallback()));
208 EnsureAuthenticator();
209 task_runner_
->PostTask(FROM_HERE
,
210 base::Bind(&Authenticator::LoginAsSupervisedUser
,
211 authenticator_
.get(),
216 void LoginPerformer::LoginAsPublicSession(const UserContext
& user_context
) {
217 if (!CheckPolicyForUser(user_context
.GetUserID())) {
220 delegate_
->PolicyLoadFailed();
224 EnsureAuthenticator();
225 task_runner_
->PostTask(FROM_HERE
,
226 base::Bind(&Authenticator::LoginAsPublicSession
,
227 authenticator_
.get(),
231 void LoginPerformer::LoginOffTheRecord() {
232 EnsureAuthenticator();
233 task_runner_
->PostTask(
235 base::Bind(&Authenticator::LoginOffTheRecord
, authenticator_
.get()));
238 void LoginPerformer::LoginAsKioskAccount(const std::string
& app_user_id
,
239 bool use_guest_mount
) {
240 EnsureAuthenticator();
241 task_runner_
->PostTask(FROM_HERE
,
242 base::Bind(&Authenticator::LoginAsKioskAccount
,
243 authenticator_
.get(),
248 void LoginPerformer::RecoverEncryptedData(const std::string
& old_password
) {
249 task_runner_
->PostTask(FROM_HERE
,
250 base::Bind(&Authenticator::RecoverEncryptedData
,
251 authenticator_
.get(),
255 void LoginPerformer::ResyncEncryptedData() {
256 task_runner_
->PostTask(
258 base::Bind(&Authenticator::ResyncEncryptedData
, authenticator_
.get()));
261 ////////////////////////////////////////////////////////////////////////////////
262 // LoginPerformer, private:
264 void LoginPerformer::EnsureExtendedAuthenticator() {
265 if (extended_authenticator_
.get())
266 extended_authenticator_
->SetConsumer(NULL
);
267 extended_authenticator_
= ExtendedAuthenticator::Create(this);
270 void LoginPerformer::StartLoginCompletion() {
271 DVLOG(1) << "Login completion started";
272 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("AuthStarted", false);
273 content::BrowserContext
* browser_context
= GetSigninContext();
274 EnsureAuthenticator();
275 task_runner_
->PostTask(FROM_HERE
,
276 base::Bind(&chromeos::Authenticator::CompleteLogin
,
277 authenticator_
.get(),
280 user_context_
.ClearSecrets();
283 void LoginPerformer::StartAuthentication() {
284 DVLOG(1) << "Auth started";
285 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("AuthStarted", false);
287 EnsureAuthenticator();
288 content::BrowserContext
* browser_context
= GetSigninContext();
289 task_runner_
->PostTask(FROM_HERE
,
290 base::Bind(&Authenticator::AuthenticateToLogin
,
291 authenticator_
.get(),
292 base::Unretained(browser_context
),
294 // Make unobtrusive online check. It helps to determine password change
295 // state in the case when offline login fails.
296 online_attempt_host_
.Check(GetSigninRequestContext(), user_context_
);
300 user_context_
.ClearSecrets();
303 void LoginPerformer::EnsureAuthenticator() {
304 authenticator_
= CreateAuthenticator();
306 } // namespace chromeos