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 last_login_failure_(AuthFailure::AuthFailureNone()),
36 password_changed_(false),
37 password_changed_callback_count_(0),
38 auth_mode_(AUTH_MODE_INTERNAL
),
39 weak_factory_(this) {}
41 LoginPerformer::~LoginPerformer() {
42 DVLOG(1) << "Deleting LoginPerformer";
43 if (authenticator_
.get())
44 authenticator_
->SetConsumer(NULL
);
45 if (extended_authenticator_
.get())
46 extended_authenticator_
->SetConsumer(NULL
);
49 ////////////////////////////////////////////////////////////////////////////////
50 // LoginPerformer, AuthStatusConsumer implementation:
52 void LoginPerformer::OnAuthFailure(const AuthFailure
& failure
) {
53 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
54 base::RecordAction(UserMetricsAction("Login_Failure"));
56 UMA_HISTOGRAM_ENUMERATION("Login.FailureReason",
58 AuthFailure::NUM_FAILURE_REASONS
);
60 DVLOG(1) << "failure.reason " << failure
.reason();
61 DVLOG(1) << "failure.error.state " << failure
.error().state();
63 last_login_failure_
= failure
;
65 delegate_
->OnAuthFailure(failure
);
68 // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS:
69 // happens during offline auth only.
74 void LoginPerformer::OnAuthSuccess(const UserContext
& user_context
) {
75 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
76 base::RecordAction(UserMetricsAction("Login_Success"));
77 VLOG(1) << "LoginSuccess hash: " << user_context
.GetUserIDHash();
79 // After delegate_->OnAuthSuccess(...) is called, delegate_ releases
80 // LoginPerformer ownership. LP now manages it's lifetime on its own.
81 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
82 delegate_
->OnAuthSuccess(user_context
);
85 void LoginPerformer::OnOffTheRecordAuthSuccess() {
86 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
87 base::RecordAction(UserMetricsAction("Login_GuestLoginSuccess"));
90 delegate_
->OnOffTheRecordAuthSuccess();
95 void LoginPerformer::OnPasswordChangeDetected() {
96 password_changed_
= true;
97 password_changed_callback_count_
++;
99 delegate_
->OnPasswordChangeDetected();
105 ////////////////////////////////////////////////////////////////////////////////
106 // LoginPerformer, public:
108 void LoginPerformer::NotifyWhitelistCheckFailure() {
110 delegate_
->WhiteListCheckFailed(user_context_
.GetUserID());
115 void LoginPerformer::PerformLogin(const UserContext
& user_context
,
116 AuthorizationMode auth_mode
) {
117 auth_mode_
= auth_mode
;
118 user_context_
= user_context
;
120 if (RunTrustedCheck(base::Bind(&LoginPerformer::DoPerformLogin
,
121 weak_factory_
.GetWeakPtr(),
126 DoPerformLogin(user_context_
, auth_mode
);
129 void LoginPerformer::DoPerformLogin(const UserContext
& user_context
,
130 AuthorizationMode auth_mode
) {
131 std::string email
= gaia::CanonicalizeEmail(user_context
.GetUserID());
132 bool wildcard_match
= false;
134 if (!IsUserWhitelisted(email
, &wildcard_match
)) {
135 NotifyWhitelistCheckFailure();
139 if (user_context
.GetAuthFlow() == UserContext::AUTH_FLOW_EASY_UNLOCK
)
140 SetupEasyUnlockUserFlow(user_context
.GetUserID());
142 switch (auth_mode_
) {
143 case AUTH_MODE_EXTENSION
: {
144 RunOnlineWhitelistCheck(
145 email
, wildcard_match
, user_context
.GetRefreshToken(),
146 base::Bind(&LoginPerformer::StartLoginCompletion
,
147 weak_factory_
.GetWeakPtr()),
148 base::Bind(&LoginPerformer::NotifyWhitelistCheckFailure
,
149 weak_factory_
.GetWeakPtr()));
152 case AUTH_MODE_INTERNAL
:
153 StartAuthentication();
158 void LoginPerformer::LoginAsSupervisedUser(const UserContext
& user_context
) {
159 DCHECK_EQ(chromeos::login::kSupervisedUserDomain
,
160 gaia::ExtractDomainName(user_context
.GetUserID()));
162 user_context_
= user_context
;
163 user_context_
.SetUserType(user_manager::USER_TYPE_SUPERVISED
);
165 if (RunTrustedCheck(base::Bind(&LoginPerformer::TrustedLoginAsSupervisedUser
,
166 weak_factory_
.GetWeakPtr(),
170 TrustedLoginAsSupervisedUser(user_context_
);
173 void LoginPerformer::TrustedLoginAsSupervisedUser(
174 const UserContext
& user_context
) {
175 if (!AreSupervisedUsersAllowed()) {
176 LOG(ERROR
) << "Login attempt of supervised user detected.";
177 delegate_
->WhiteListCheckFailed(user_context
.GetUserID());
181 SetupSupervisedUserFlow(user_context
.GetUserID());
182 UserContext user_context_copy
= TransformSupervisedKey(user_context
);
184 if (UseExtendedAuthenticatorForSupervisedUser(user_context
)) {
185 EnsureExtendedAuthenticator();
186 // TODO(antrim) : Replace empty callback with explicit method.
187 // http://crbug.com/351268
188 task_runner_
->PostTask(
190 base::Bind(&ExtendedAuthenticator::AuthenticateToMount
,
191 extended_authenticator_
.get(),
193 ExtendedAuthenticator::ResultCallback()));
196 EnsureAuthenticator();
197 task_runner_
->PostTask(FROM_HERE
,
198 base::Bind(&Authenticator::LoginAsSupervisedUser
,
199 authenticator_
.get(),
204 void LoginPerformer::LoginAsPublicSession(const UserContext
& user_context
) {
205 if (!CheckPolicyForUser(user_context
.GetUserID())) {
208 delegate_
->PolicyLoadFailed();
212 EnsureAuthenticator();
213 task_runner_
->PostTask(FROM_HERE
,
214 base::Bind(&Authenticator::LoginAsPublicSession
,
215 authenticator_
.get(),
219 void LoginPerformer::LoginOffTheRecord() {
220 EnsureAuthenticator();
221 task_runner_
->PostTask(
223 base::Bind(&Authenticator::LoginOffTheRecord
, authenticator_
.get()));
226 void LoginPerformer::LoginAsKioskAccount(const std::string
& app_user_id
,
227 bool use_guest_mount
) {
228 EnsureAuthenticator();
229 task_runner_
->PostTask(FROM_HERE
,
230 base::Bind(&Authenticator::LoginAsKioskAccount
,
231 authenticator_
.get(),
236 void LoginPerformer::RecoverEncryptedData(const std::string
& old_password
) {
237 task_runner_
->PostTask(FROM_HERE
,
238 base::Bind(&Authenticator::RecoverEncryptedData
,
239 authenticator_
.get(),
243 void LoginPerformer::ResyncEncryptedData() {
244 task_runner_
->PostTask(
246 base::Bind(&Authenticator::ResyncEncryptedData
, authenticator_
.get()));
249 ////////////////////////////////////////////////////////////////////////////////
250 // LoginPerformer, private:
252 void LoginPerformer::EnsureExtendedAuthenticator() {
253 if (extended_authenticator_
.get())
254 extended_authenticator_
->SetConsumer(NULL
);
255 extended_authenticator_
= ExtendedAuthenticator::Create(this);
258 void LoginPerformer::StartLoginCompletion() {
259 DVLOG(1) << "Login completion started";
260 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("AuthStarted", false);
261 content::BrowserContext
* browser_context
= GetSigninContext();
262 EnsureAuthenticator();
263 task_runner_
->PostTask(FROM_HERE
,
264 base::Bind(&chromeos::Authenticator::CompleteLogin
,
265 authenticator_
.get(),
268 user_context_
.ClearSecrets();
271 void LoginPerformer::StartAuthentication() {
272 DVLOG(1) << "Auth started";
273 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("AuthStarted", false);
275 EnsureAuthenticator();
276 content::BrowserContext
* browser_context
= GetSigninContext();
277 task_runner_
->PostTask(FROM_HERE
,
278 base::Bind(&Authenticator::AuthenticateToLogin
,
279 authenticator_
.get(),
280 base::Unretained(browser_context
),
285 user_context_
.ClearSecrets();
288 void LoginPerformer::EnsureAuthenticator() {
289 authenticator_
= CreateAuthenticator();
291 } // namespace chromeos