ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / chromeos / login / existing_user_controller.cc
blob3378e9979d479d658dd8bf65be5201b7e9fa8fef
1 // Copyright (c) 2012 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 "chrome/browser/chromeos/login/existing_user_controller.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/command_line.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/histogram.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/values.h"
21 #include "base/version.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/browser_process_platform_part.h"
24 #include "chrome/browser/chrome_notification_types.h"
25 #include "chrome/browser/chromeos/boot_times_recorder.h"
26 #include "chrome/browser/chromeos/customization/customization_document.h"
27 #include "chrome/browser/chromeos/login/auth/chrome_login_performer.h"
28 #include "chrome/browser/chromeos/login/helper.h"
29 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
30 #include "chrome/browser/chromeos/login/signin_specifics.h"
31 #include "chrome/browser/chromeos/login/startup_utils.h"
32 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
33 #include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
34 #include "chrome/browser/chromeos/login/user_flow.h"
35 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
36 #include "chrome/browser/chromeos/login/wizard_controller.h"
37 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
38 #include "chrome/browser/chromeos/policy/device_local_account.h"
39 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
40 #include "chrome/browser/chromeos/profiles/profile_helper.h"
41 #include "chrome/browser/chromeos/settings/cros_settings.h"
42 #include "chrome/browser/chromeos/system/device_disabling_manager.h"
43 #include "chrome/browser/signin/easy_unlock_service.h"
44 #include "chrome/browser/ui/ash/accessibility/automation_manager_ash.h"
45 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
46 #include "chrome/common/chrome_switches.h"
47 #include "chrome/common/chrome_version_info.h"
48 #include "chrome/common/url_constants.h"
49 #include "chrome/grit/generated_resources.h"
50 #include "chromeos/chromeos_switches.h"
51 #include "chromeos/dbus/dbus_thread_manager.h"
52 #include "chromeos/dbus/power_manager_client.h"
53 #include "chromeos/dbus/session_manager_client.h"
54 #include "chromeos/login/user_names.h"
55 #include "chromeos/settings/cros_settings_names.h"
56 #include "components/google/core/browser/google_util.h"
57 #include "components/policy/core/common/cloud/cloud_policy_core.h"
58 #include "components/policy/core/common/cloud/cloud_policy_store.h"
59 #include "components/policy/core/common/policy_map.h"
60 #include "components/policy/core/common/policy_service.h"
61 #include "components/policy/core/common/policy_types.h"
62 #include "components/user_manager/user_manager.h"
63 #include "components/user_manager/user_type.h"
64 #include "content/public/browser/browser_thread.h"
65 #include "content/public/browser/notification_service.h"
66 #include "content/public/browser/notification_types.h"
67 #include "content/public/browser/user_metrics.h"
68 #include "google_apis/gaia/gaia_auth_util.h"
69 #include "google_apis/gaia/google_service_auth_error.h"
70 #include "net/http/http_auth_cache.h"
71 #include "net/http/http_network_session.h"
72 #include "net/http/http_transaction_factory.h"
73 #include "net/url_request/url_request_context.h"
74 #include "net/url_request/url_request_context_getter.h"
75 #include "policy/policy_constants.h"
76 #include "ui/accessibility/ax_enums.h"
77 #include "ui/base/l10n/l10n_util.h"
78 #include "ui/views/widget/widget.h"
80 namespace chromeos {
82 namespace {
84 // URL for account creation.
85 const char kCreateAccountURL[] =
86 "https://accounts.google.com/NewAccount?service=mail";
88 // Delay for transferring the auth cache to the system profile.
89 const long int kAuthCacheTransferDelayMs = 2000;
91 // Delay for restarting the ui if safe-mode login has failed.
92 const long int kSafeModeRestartUiDelayMs = 30000;
94 // Makes a call to the policy subsystem to reload the policy when we detect
95 // authentication change.
96 void RefreshPoliciesOnUIThread() {
97 if (g_browser_process->policy_service())
98 g_browser_process->policy_service()->RefreshPolicies(base::Closure());
101 // Copies any authentication details that were entered in the login profile in
102 // the mail profile to make sure all subsystems of Chrome can access the network
103 // with the provided authentication which are possibly for a proxy server.
104 void TransferContextAuthenticationsOnIOThread(
105 net::URLRequestContextGetter* default_profile_context_getter,
106 net::URLRequestContextGetter* browser_process_context_getter) {
107 net::HttpAuthCache* new_cache =
108 browser_process_context_getter->GetURLRequestContext()->
109 http_transaction_factory()->GetSession()->http_auth_cache();
110 net::HttpAuthCache* old_cache =
111 default_profile_context_getter->GetURLRequestContext()->
112 http_transaction_factory()->GetSession()->http_auth_cache();
113 new_cache->UpdateAllFrom(*old_cache);
114 VLOG(1) << "Main request context populated with authentication data.";
115 // Last but not least tell the policy subsystem to refresh now as it might
116 // have been stuck until now too.
117 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
118 base::Bind(&RefreshPoliciesOnUIThread));
121 // Record UMA for password login of regular user when Easy sign-in is enabled.
122 void RecordPasswordLoginEvent(const UserContext& user_context) {
123 EasyUnlockService* easy_unlock_service =
124 EasyUnlockService::Get(ProfileHelper::GetSigninProfile());
125 if (user_context.GetUserType() == user_manager::USER_TYPE_REGULAR &&
126 user_context.GetAuthFlow() == UserContext::AUTH_FLOW_OFFLINE &&
127 easy_unlock_service) {
128 easy_unlock_service->RecordPasswordLoginEvent(user_context.GetUserID());
132 bool CanShowDebuggingFeatures() {
133 // We need to be on the login screen and in dev mode to show this menu item.
134 return base::CommandLine::ForCurrentProcess()->HasSwitch(
135 chromeos::switches::kSystemDevMode) &&
136 base::CommandLine::ForCurrentProcess()->HasSwitch(
137 chromeos::switches::kLoginManager) &&
138 !user_manager::UserManager::Get()->IsSessionStarted();
141 } // namespace
143 // static
144 ExistingUserController* ExistingUserController::current_controller_ = NULL;
146 ////////////////////////////////////////////////////////////////////////////////
147 // ExistingUserController, public:
149 ExistingUserController::ExistingUserController(LoginDisplayHost* host)
150 : auth_status_consumer_(NULL),
151 host_(host),
152 login_display_(host_->CreateLoginDisplay(this)),
153 num_login_attempts_(0),
154 cros_settings_(CrosSettings::Get()),
155 offline_failed_(false),
156 is_login_in_progress_(false),
157 password_changed_(false),
158 auth_mode_(LoginPerformer::AUTH_MODE_EXTENSION),
159 signin_screen_ready_(false),
160 network_state_helper_(new login::NetworkStateHelper),
161 weak_factory_(this) {
162 DCHECK(current_controller_ == NULL);
163 current_controller_ = this;
165 registrar_.Add(this,
166 chrome::NOTIFICATION_USER_LIST_CHANGED,
167 content::NotificationService::AllSources());
168 registrar_.Add(this,
169 chrome::NOTIFICATION_AUTH_SUPPLIED,
170 content::NotificationService::AllSources());
171 registrar_.Add(this,
172 chrome::NOTIFICATION_SESSION_STARTED,
173 content::NotificationService::AllSources());
174 show_user_names_subscription_ = cros_settings_->AddSettingsObserver(
175 kAccountsPrefShowUserNamesOnSignIn,
176 base::Bind(&ExistingUserController::DeviceSettingsChanged,
177 base::Unretained(this)));
178 allow_new_user_subscription_ = cros_settings_->AddSettingsObserver(
179 kAccountsPrefAllowNewUser,
180 base::Bind(&ExistingUserController::DeviceSettingsChanged,
181 base::Unretained(this)));
182 allow_guest_subscription_ = cros_settings_->AddSettingsObserver(
183 kAccountsPrefAllowGuest,
184 base::Bind(&ExistingUserController::DeviceSettingsChanged,
185 base::Unretained(this)));
186 allow_supervised_user_subscription_ = cros_settings_->AddSettingsObserver(
187 kAccountsPrefSupervisedUsersEnabled,
188 base::Bind(&ExistingUserController::DeviceSettingsChanged,
189 base::Unretained(this)));
190 users_subscription_ = cros_settings_->AddSettingsObserver(
191 kAccountsPrefUsers,
192 base::Bind(&ExistingUserController::DeviceSettingsChanged,
193 base::Unretained(this)));
194 local_account_auto_login_id_subscription_ =
195 cros_settings_->AddSettingsObserver(
196 kAccountsPrefDeviceLocalAccountAutoLoginId,
197 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
198 base::Unretained(this)));
199 local_account_auto_login_delay_subscription_ =
200 cros_settings_->AddSettingsObserver(
201 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
202 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
203 base::Unretained(this)));
206 void ExistingUserController::Init(const user_manager::UserList& users) {
207 time_init_ = base::Time::Now();
208 UpdateLoginDisplay(users);
209 ConfigurePublicSessionAutoLogin();
212 void ExistingUserController::UpdateLoginDisplay(
213 const user_manager::UserList& users) {
214 bool show_users_on_signin;
215 user_manager::UserList filtered_users;
217 cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn,
218 &show_users_on_signin);
219 for (user_manager::UserList::const_iterator it = users.begin();
220 it != users.end();
221 ++it) {
222 // TODO(xiyuan): Clean user profile whose email is not in whitelist.
223 bool meets_supervised_requirements =
224 (*it)->GetType() != user_manager::USER_TYPE_SUPERVISED ||
225 user_manager::UserManager::Get()->AreSupervisedUsersAllowed();
226 bool meets_whitelist_requirements =
227 CrosSettings::IsWhitelisted((*it)->email(), NULL) ||
228 !(*it)->HasGaiaAccount();
230 // Public session accounts are always shown on login screen.
231 bool meets_show_users_requirements =
232 show_users_on_signin ||
233 (*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
234 if (meets_supervised_requirements &&
235 meets_whitelist_requirements &&
236 meets_show_users_requirements) {
237 filtered_users.push_back(*it);
241 // If no user pods are visible, fallback to single new user pod which will
242 // have guest session link.
243 bool show_guest;
244 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &show_guest);
245 show_users_on_signin |= !filtered_users.empty();
246 show_guest &= !filtered_users.empty();
247 bool show_new_user = true;
248 login_display_->set_parent_window(GetNativeWindow());
249 login_display_->Init(
250 filtered_users, show_guest, show_users_on_signin, show_new_user);
251 host_->OnPreferencesChanged();
254 ////////////////////////////////////////////////////////////////////////////////
255 // ExistingUserController, content::NotificationObserver implementation:
258 void ExistingUserController::Observe(
259 int type,
260 const content::NotificationSource& source,
261 const content::NotificationDetails& details) {
262 if (type == chrome::NOTIFICATION_SESSION_STARTED) {
263 // Stop listening to any notification once session has started.
264 // Sign in screen objects are marked for deletion with DeleteSoon so
265 // make sure no object would be used after session has started.
266 // http://crbug.com/125276
267 registrar_.RemoveAll();
268 return;
270 if (type == chrome::NOTIFICATION_USER_LIST_CHANGED) {
271 DeviceSettingsChanged();
272 return;
274 if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
275 // Possibly the user has authenticated against a proxy server and we might
276 // need the credentials for enrollment and other system requests from the
277 // main |g_browser_process| request context (see bug
278 // http://crosbug.com/24861). So we transfer any credentials to the global
279 // request context here.
280 // The issue we have here is that the NOTIFICATION_AUTH_SUPPLIED is sent
281 // just after the UI is closed but before the new credentials were stored
282 // in the profile. Therefore we have to give it some time to make sure it
283 // has been updated before we copy it.
284 VLOG(1) << "Authentication was entered manually, possibly for proxyauth.";
285 scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter =
286 g_browser_process->system_request_context();
287 Profile* signin_profile = ProfileHelper::GetSigninProfile();
288 scoped_refptr<net::URLRequestContextGetter> signin_profile_context_getter =
289 signin_profile->GetRequestContext();
290 DCHECK(browser_process_context_getter.get());
291 DCHECK(signin_profile_context_getter.get());
292 content::BrowserThread::PostDelayedTask(
293 content::BrowserThread::IO, FROM_HERE,
294 base::Bind(&TransferContextAuthenticationsOnIOThread,
295 signin_profile_context_getter,
296 browser_process_context_getter),
297 base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs));
301 ////////////////////////////////////////////////////////////////////////////////
302 // ExistingUserController, private:
304 ExistingUserController::~ExistingUserController() {
305 UserSessionManager::GetInstance()->DelegateDeleted(this);
307 if (current_controller_ == this) {
308 current_controller_ = NULL;
309 } else {
310 NOTREACHED() << "More than one controller are alive.";
312 DCHECK(login_display_.get());
315 ////////////////////////////////////////////////////////////////////////////////
316 // ExistingUserController, LoginDisplay::Delegate implementation:
319 void ExistingUserController::CancelPasswordChangedFlow() {
320 login_performer_.reset(NULL);
321 PerformLoginFinishedActions(true /* start public session timer */);
324 void ExistingUserController::CreateAccount() {
325 content::RecordAction(base::UserMetricsAction("Login.CreateAccount"));
326 guest_mode_url_ = google_util::AppendGoogleLocaleParam(
327 GURL(kCreateAccountURL), g_browser_process->GetApplicationLocale());
328 Login(UserContext(user_manager::USER_TYPE_GUEST, std::string()),
329 SigninSpecifics());
332 void ExistingUserController::CompleteLogin(const UserContext& user_context) {
333 login_display_->set_signin_completed(true);
334 if (!host_) {
335 // Complete login event was generated already from UI. Ignore notification.
336 return;
339 ContinueLoginIfDeviceNotDisabled(base::Bind(
340 &ExistingUserController::DoCompleteLogin,
341 weak_factory_.GetWeakPtr(),
342 user_context));
345 base::string16 ExistingUserController::GetConnectedNetworkName() {
346 return network_state_helper_->GetCurrentNetworkName();
349 bool ExistingUserController::IsSigninInProgress() const {
350 return is_login_in_progress_;
353 void ExistingUserController::Login(const UserContext& user_context,
354 const SigninSpecifics& specifics) {
355 ContinueLoginIfDeviceNotDisabled(base::Bind(
356 &ExistingUserController::DoLogin,
357 weak_factory_.GetWeakPtr(),
358 user_context,
359 specifics));
362 void ExistingUserController::PerformLogin(
363 const UserContext& user_context,
364 LoginPerformer::AuthorizationMode auth_mode) {
365 // TODO(antrim): remove this output once crash reason is found.
366 LOG(ERROR) << "Setting flow from PerformLogin";
367 ChromeUserManager::Get()
368 ->GetUserFlow(user_context.GetUserID())
369 ->SetHost(host_);
371 BootTimesRecorder::Get()->RecordLoginAttempted();
373 // Use the same LoginPerformer for subsequent login as it has state
374 // such as Authenticator instance.
375 if (!login_performer_.get() || num_login_attempts_ <= 1) {
376 // Only one instance of LoginPerformer should exist at a time.
377 login_performer_.reset(NULL);
378 login_performer_.reset(new ChromeLoginPerformer(this));
381 if (gaia::ExtractDomainName(user_context.GetUserID()) ==
382 chromeos::login::kSupervisedUserDomain) {
383 login_performer_->LoginAsSupervisedUser(user_context);
384 } else {
385 login_performer_->PerformLogin(user_context, auth_mode);
386 RecordPasswordLoginEvent(user_context);
388 SendAccessibilityAlert(
389 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN));
392 void ExistingUserController::MigrateUserData(const std::string& old_password) {
393 // LoginPerformer instance has state of the user so it should exist.
394 if (login_performer_.get())
395 login_performer_->RecoverEncryptedData(old_password);
399 void ExistingUserController::OnSigninScreenReady() {
400 signin_screen_ready_ = true;
401 StartPublicSessionAutoLoginTimer();
404 void ExistingUserController::OnStartEnterpriseEnrollment() {
405 if (KioskAppManager::Get()->IsConsumerKioskDeviceWithAutoLaunch()) {
406 LOG(WARNING) << "Enterprise enrollment is not available after kiosk auto "
407 "launch is set.";
408 return;
411 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
412 base::Bind(&ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
413 weak_factory_.GetWeakPtr()));
416 void ExistingUserController::OnStartEnableDebuggingScreen() {
417 if (CanShowDebuggingFeatures())
418 ShowEnableDebuggingScreen();
421 void ExistingUserController::OnStartKioskEnableScreen() {
422 KioskAppManager::Get()->GetConsumerKioskAutoLaunchStatus(
423 base::Bind(
424 &ExistingUserController::OnConsumerKioskAutoLaunchCheckCompleted,
425 weak_factory_.GetWeakPtr()));
428 void ExistingUserController::OnStartKioskAutolaunchScreen() {
429 ShowKioskAutolaunchScreen();
432 void ExistingUserController::ResyncUserData() {
433 // LoginPerformer instance has state of the user so it should exist.
434 if (login_performer_.get())
435 login_performer_->ResyncEncryptedData();
438 void ExistingUserController::SetDisplayEmail(const std::string& email) {
439 display_email_ = email;
442 void ExistingUserController::ShowWrongHWIDScreen() {
443 host_->StartWizard(WizardController::kWrongHWIDScreenName);
446 void ExistingUserController::Signout() {
447 NOTREACHED();
450 void ExistingUserController::OnConsumerKioskAutoLaunchCheckCompleted(
451 KioskAppManager::ConsumerKioskAutoLaunchStatus status) {
452 if (status == KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE)
453 ShowKioskEnableScreen();
456 void ExistingUserController::OnEnrollmentOwnershipCheckCompleted(
457 DeviceSettingsService::OwnershipStatus status) {
458 if (status == DeviceSettingsService::OWNERSHIP_NONE) {
459 ShowEnrollmentScreen();
460 } else if (status == DeviceSettingsService::OWNERSHIP_TAKEN) {
461 // On a device that is already owned we might want to allow users to
462 // re-enroll if the policy information is invalid.
463 CrosSettingsProvider::TrustedStatus trusted_status =
464 CrosSettings::Get()->PrepareTrustedValues(
465 base::Bind(
466 &ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
467 weak_factory_.GetWeakPtr(), status));
468 if (trusted_status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
469 ShowEnrollmentScreen();
471 } else {
472 // OwnershipService::GetStatusAsync is supposed to return either
473 // OWNERSHIP_NONE or OWNERSHIP_TAKEN.
474 NOTREACHED();
478 void ExistingUserController::ShowEnrollmentScreen() {
479 host_->StartWizard(WizardController::kEnrollmentScreenName);
482 void ExistingUserController::ShowResetScreen() {
483 host_->StartWizard(WizardController::kResetScreenName);
486 void ExistingUserController::ShowEnableDebuggingScreen() {
487 host_->StartWizard(WizardController::kEnableDebuggingScreenName);
490 void ExistingUserController::ShowKioskEnableScreen() {
491 host_->StartWizard(WizardController::kKioskEnableScreenName);
494 void ExistingUserController::ShowKioskAutolaunchScreen() {
495 host_->StartWizard(WizardController::kKioskAutolaunchScreenName);
498 void ExistingUserController::ShowTPMError() {
499 login_display_->SetUIEnabled(false);
500 login_display_->ShowErrorScreen(LoginDisplay::TPM_ERROR);
503 ////////////////////////////////////////////////////////////////////////////////
504 // ExistingUserController, LoginPerformer::Delegate implementation:
507 void ExistingUserController::OnAuthFailure(const AuthFailure& failure) {
508 offline_failed_ = true;
509 guest_mode_url_ = GURL::EmptyGURL();
510 std::string error = failure.GetErrorString();
512 PerformLoginFinishedActions(false /* don't start public session timer */);
514 if (ChromeUserManager::Get()
515 ->GetUserFlow(last_login_attempt_username_)
516 ->HandleLoginFailure(failure)) {
517 return;
520 if (failure.reason() == AuthFailure::OWNER_REQUIRED) {
521 ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error);
522 content::BrowserThread::PostDelayedTask(
523 content::BrowserThread::UI, FROM_HERE,
524 base::Bind(&SessionManagerClient::StopSession,
525 base::Unretained(DBusThreadManager::Get()->
526 GetSessionManagerClient())),
527 base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs));
528 } else if (failure.reason() == AuthFailure::TPM_ERROR) {
529 ShowTPMError();
530 } else if (!online_succeeded_for_.empty()) {
531 ShowGaiaPasswordChanged(online_succeeded_for_);
532 } else if (last_login_attempt_username_ == chromeos::login::kGuestUserName) {
533 // Show no errors, just re-enable input.
534 login_display_->ClearAndEnablePassword();
535 StartPublicSessionAutoLoginTimer();
536 } else {
537 // Check networking after trying to login in case user is
538 // cached locally or the local admin account.
539 bool is_known_user = user_manager::UserManager::Get()->IsKnownUser(
540 last_login_attempt_username_);
541 if (!network_state_helper_->IsConnected()) {
542 if (is_known_user)
543 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
544 else
545 ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
546 } else {
547 // TODO(nkostylev): Cleanup rest of ClientLogin related code.
548 if (failure.reason() == AuthFailure::NETWORK_AUTH_FAILED &&
549 failure.error().state() ==
550 GoogleServiceAuthError::HOSTED_NOT_ALLOWED) {
551 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED, error);
552 } else {
553 if (!is_known_user)
554 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
555 else
556 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
559 login_display_->ClearAndEnablePassword();
560 StartPublicSessionAutoLoginTimer();
563 // Reset user flow to default, so that special flow will not affect next
564 // attempt.
565 ChromeUserManager::Get()->ResetUserFlow(last_login_attempt_username_);
567 if (auth_status_consumer_)
568 auth_status_consumer_->OnAuthFailure(failure);
570 // Clear the recorded displayed email so it won't affect any future attempts.
571 display_email_.clear();
574 void ExistingUserController::OnAuthSuccess(const UserContext& user_context) {
575 is_login_in_progress_ = false;
576 offline_failed_ = false;
577 login_display_->set_signin_completed(true);
579 // Login performer will be gone so cache this value to use
580 // once profile is loaded.
581 password_changed_ = login_performer_->password_changed();
582 auth_mode_ = login_performer_->auth_mode();
584 ChromeUserManager::Get()
585 ->GetUserFlow(user_context.GetUserID())
586 ->HandleLoginSuccess(user_context);
588 StopPublicSessionAutoLoginTimer();
590 const bool has_auth_cookies =
591 login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION &&
592 user_context.GetAuthCode().empty();
594 // LoginPerformer instance will delete itself in case of successful auth.
595 login_performer_->set_delegate(NULL);
596 ignore_result(login_performer_.release());
598 UserSessionManager::StartSessionType start_session_type =
599 UserAddingScreen::Get()->IsRunning()
600 ? UserSessionManager::SECONDARY_USER_SESSION
601 : UserSessionManager::PRIMARY_USER_SESSION;
602 UserSessionManager::GetInstance()->StartSession(
603 user_context, start_session_type, has_auth_cookies,
604 false, // Start session for user.
605 this);
607 // Update user's displayed email.
608 if (!display_email_.empty()) {
609 user_manager::UserManager::Get()->SaveUserDisplayEmail(
610 user_context.GetUserID(), display_email_);
611 display_email_.clear();
615 void ExistingUserController::OnProfilePrepared(Profile* profile,
616 bool browser_launched) {
617 // Reenable clicking on other windows and status area.
618 login_display_->SetUIEnabled(true);
620 if (browser_launched)
621 host_ = NULL;
623 // Inform |auth_status_consumer_| about successful login.
624 // TODO(nkostylev): Pass UserContext back crbug.com/424550
625 if (auth_status_consumer_) {
626 auth_status_consumer_->
627 OnAuthSuccess(UserContext(last_login_attempt_username_));
631 void ExistingUserController::OnOffTheRecordAuthSuccess() {
632 is_login_in_progress_ = false;
633 offline_failed_ = false;
635 // Mark the device as registered., i.e. the second part of OOBE as completed.
636 if (!StartupUtils::IsDeviceRegistered())
637 StartupUtils::MarkDeviceRegistered(base::Closure());
639 UserSessionManager::GetInstance()->CompleteGuestSessionLogin(guest_mode_url_);
641 if (auth_status_consumer_)
642 auth_status_consumer_->OnOffTheRecordAuthSuccess();
645 void ExistingUserController::OnPasswordChangeDetected() {
646 is_login_in_progress_ = false;
647 offline_failed_ = false;
649 // Must not proceed without signature verification.
650 if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
651 base::Bind(&ExistingUserController::OnPasswordChangeDetected,
652 weak_factory_.GetWeakPtr()))) {
653 // Value of owner email is still not verified.
654 // Another attempt will be invoked after verification completion.
655 return;
658 if (ChromeUserManager::Get()
659 ->GetUserFlow(last_login_attempt_username_)
660 ->HandlePasswordChangeDetected()) {
661 return;
664 // True if user has already made an attempt to enter old password and failed.
665 bool show_invalid_old_password_error =
666 login_performer_->password_changed_callback_count() > 1;
668 // Note: We allow owner using "full sync" mode which will recreate
669 // cryptohome and deal with owner private key being lost. This also allows
670 // us to recover from a lost owner password/homedir.
671 // TODO(gspencer): We shouldn't have to erase stateful data when
672 // doing this. See http://crosbug.com/9115 http://crosbug.com/7792
673 login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error);
675 if (auth_status_consumer_)
676 auth_status_consumer_->OnPasswordChangeDetected();
678 display_email_.clear();
681 void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
682 PerformLoginFinishedActions(true /* start public session timer */);
683 offline_failed_ = false;
685 if (g_browser_process->platform_part()
686 ->browser_policy_connector_chromeos()
687 ->IsEnterpriseManaged()) {
688 ShowError(IDS_ENTERPRISE_LOGIN_ERROR_WHITELIST, email);
689 } else {
690 ShowError(IDS_LOGIN_ERROR_WHITELIST, email);
693 login_display_->ShowSigninUI(email);
695 if (auth_status_consumer_) {
696 auth_status_consumer_->OnAuthFailure(
697 AuthFailure(AuthFailure::WHITELIST_CHECK_FAILED));
700 display_email_.clear();
703 void ExistingUserController::PolicyLoadFailed() {
704 ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, "");
706 PerformLoginFinishedActions(false /* don't start public session timer */);
707 offline_failed_ = false;
708 display_email_.clear();
711 void ExistingUserController::OnOnlineChecked(const std::string& username,
712 bool success) {
713 if (success && last_login_attempt_username_ == username) {
714 online_succeeded_for_ = username;
715 // Wait for login attempt to end, if it hasn't yet.
716 if (offline_failed_ && !is_login_in_progress_)
717 ShowGaiaPasswordChanged(username);
721 ////////////////////////////////////////////////////////////////////////////////
722 // ExistingUserController, private:
724 void ExistingUserController::DeviceSettingsChanged() {
725 // If login was already completed, we should avoid any signin screen
726 // transitions, see http://crbug.com/461604 for example.
727 if (host_ != NULL && !login_display_->is_signin_completed()) {
728 // Signed settings or user list changed. Notify views and update them.
729 UpdateLoginDisplay(user_manager::UserManager::Get()->GetUsers());
730 ConfigurePublicSessionAutoLogin();
734 LoginPerformer::AuthorizationMode ExistingUserController::auth_mode() const {
735 if (login_performer_)
736 return login_performer_->auth_mode();
738 return auth_mode_;
741 bool ExistingUserController::password_changed() const {
742 if (login_performer_)
743 return login_performer_->password_changed();
745 return password_changed_;
748 void ExistingUserController::LoginAsGuest() {
749 PerformPreLoginActions(UserContext(user_manager::USER_TYPE_GUEST,
750 chromeos::login::kGuestUserName));
752 bool allow_guest;
753 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
754 if (!allow_guest) {
755 // Disallowed. The UI should normally not show the guest pod but if for some
756 // reason this has been made available to the user here is the time to tell
757 // this nicely.
758 if (g_browser_process->platform_part()
759 ->browser_policy_connector_chromeos()
760 ->IsEnterpriseManaged()) {
761 login_display_->ShowError(IDS_ENTERPRISE_LOGIN_ERROR_WHITELIST, 1,
762 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
763 } else {
764 login_display_->ShowError(IDS_LOGIN_ERROR_WHITELIST, 1,
765 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
767 PerformLoginFinishedActions(true /* start public session timer */);
768 display_email_.clear();
769 return;
772 // Only one instance of LoginPerformer should exist at a time.
773 login_performer_.reset(NULL);
774 login_performer_.reset(new ChromeLoginPerformer(this));
775 login_performer_->LoginOffTheRecord();
776 SendAccessibilityAlert(
777 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_OFFRECORD));
780 void ExistingUserController::LoginAsPublicSession(
781 const UserContext& user_context) {
782 PerformPreLoginActions(user_context);
784 // If there is no public account with the given user ID, logging in is not
785 // possible.
786 const user_manager::User* user =
787 user_manager::UserManager::Get()->FindUser(user_context.GetUserID());
788 if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
789 PerformLoginFinishedActions(true /* start public session timer */);
790 return;
793 UserContext new_user_context = user_context;
794 std::string locale = user_context.GetPublicSessionLocale();
795 if (locale.empty()) {
796 // When performing auto-login, no locale is chosen by the user. Check
797 // whether a list of recommended locales was set by policy. If so, use its
798 // first entry. Otherwise, |locale| will remain blank, indicating that the
799 // public session should use the current UI locale.
800 const policy::PolicyMap::Entry* entry = g_browser_process->platform_part()->
801 browser_policy_connector_chromeos()->
802 GetDeviceLocalAccountPolicyService()->
803 GetBrokerForUser(user_context.GetUserID())->core()->store()->
804 policy_map().Get(policy::key::kSessionLocales);
805 base::ListValue const* list = NULL;
806 if (entry &&
807 entry->level == policy::POLICY_LEVEL_RECOMMENDED &&
808 entry->value &&
809 entry->value->GetAsList(&list)) {
810 if (list->GetString(0, &locale))
811 new_user_context.SetPublicSessionLocale(locale);
815 if (!locale.empty() &&
816 new_user_context.GetPublicSessionInputMethod().empty()) {
817 // When |locale| is set, a suitable keyboard layout should be chosen. In
818 // most cases, this will already be the case because the UI shows a list of
819 // keyboard layouts suitable for the |locale| and ensures that one of them
820 // us selected. However, it is still possible that |locale| is set but no
821 // keyboard layout was chosen:
822 // * The list of keyboard layouts is updated asynchronously. If the user
823 // enters the public session before the list of keyboard layouts for the
824 // |locale| has been retrieved, the UI will indicate that no keyboard
825 // layout was chosen.
826 // * During auto-login, the |locale| is set in this method and a suitable
827 // keyboard layout must be chosen next.
829 // The list of suitable keyboard layouts is constructed asynchronously. Once
830 // it has been retrieved, |SetPublicSessionKeyboardLayoutAndLogin| will
831 // select the first layout from the list and continue login.
832 GetKeyboardLayoutsForLocale(
833 base::Bind(
834 &ExistingUserController::SetPublicSessionKeyboardLayoutAndLogin,
835 weak_factory_.GetWeakPtr(),
836 new_user_context),
837 locale);
838 return;
841 // The user chose a locale and a suitable keyboard layout or left both unset.
842 // Login can continue immediately.
843 LoginAsPublicSessionInternal(new_user_context);
846 void ExistingUserController::LoginAsKioskApp(const std::string& app_id,
847 bool diagnostic_mode) {
848 const bool auto_start = false;
849 host_->StartAppLaunch(app_id, diagnostic_mode, auto_start);
852 void ExistingUserController::ConfigurePublicSessionAutoLogin() {
853 std::string auto_login_account_id;
854 cros_settings_->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
855 &auto_login_account_id);
856 const std::vector<policy::DeviceLocalAccount> device_local_accounts =
857 policy::GetDeviceLocalAccounts(cros_settings_);
859 public_session_auto_login_username_.clear();
860 for (std::vector<policy::DeviceLocalAccount>::const_iterator
861 it = device_local_accounts.begin();
862 it != device_local_accounts.end(); ++it) {
863 if (it->account_id == auto_login_account_id) {
864 public_session_auto_login_username_ = it->user_id;
865 break;
869 const user_manager::User* user = user_manager::UserManager::Get()->FindUser(
870 public_session_auto_login_username_);
871 if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT)
872 public_session_auto_login_username_.clear();
874 if (!cros_settings_->GetInteger(
875 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
876 &public_session_auto_login_delay_)) {
877 public_session_auto_login_delay_ = 0;
880 if (!public_session_auto_login_username_.empty())
881 StartPublicSessionAutoLoginTimer();
882 else
883 StopPublicSessionAutoLoginTimer();
886 void ExistingUserController::ResetPublicSessionAutoLoginTimer() {
887 // Only restart the auto-login timer if it's already running.
888 if (auto_login_timer_ && auto_login_timer_->IsRunning()) {
889 StopPublicSessionAutoLoginTimer();
890 StartPublicSessionAutoLoginTimer();
894 void ExistingUserController::OnPublicSessionAutoLoginTimerFire() {
895 CHECK(signin_screen_ready_ && !public_session_auto_login_username_.empty());
896 Login(UserContext(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
897 public_session_auto_login_username_),
898 SigninSpecifics());
901 void ExistingUserController::StopPublicSessionAutoLoginTimer() {
902 if (auto_login_timer_)
903 auto_login_timer_->Stop();
906 void ExistingUserController::StartPublicSessionAutoLoginTimer() {
907 if (!signin_screen_ready_ ||
908 is_login_in_progress_ ||
909 public_session_auto_login_username_.empty()) {
910 return;
913 // Start the auto-login timer.
914 if (!auto_login_timer_)
915 auto_login_timer_.reset(new base::OneShotTimer<ExistingUserController>);
917 auto_login_timer_->Start(
918 FROM_HERE,
919 base::TimeDelta::FromMilliseconds(
920 public_session_auto_login_delay_),
921 base::Bind(
922 &ExistingUserController::OnPublicSessionAutoLoginTimerFire,
923 weak_factory_.GetWeakPtr()));
926 gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
927 return host_->GetNativeWindow();
930 void ExistingUserController::ShowError(int error_id,
931 const std::string& details) {
932 // TODO(dpolukhin): show detailed error info. |details| string contains
933 // low level error info that is not localized and even is not user friendly.
934 // For now just ignore it because error_text contains all required information
935 // for end users, developers can see details string in Chrome logs.
936 VLOG(1) << details;
937 HelpAppLauncher::HelpTopic help_topic_id;
938 bool is_offline = !network_state_helper_->IsConnected();
939 switch (login_performer_->error().state()) {
940 case GoogleServiceAuthError::CONNECTION_FAILED:
941 help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE;
942 break;
943 case GoogleServiceAuthError::ACCOUNT_DISABLED:
944 help_topic_id = HelpAppLauncher::HELP_ACCOUNT_DISABLED;
945 break;
946 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
947 help_topic_id = HelpAppLauncher::HELP_HOSTED_ACCOUNT;
948 break;
949 default:
950 help_topic_id = is_offline ?
951 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE :
952 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT;
953 break;
956 if (error_id == IDS_LOGIN_ERROR_AUTHENTICATING) {
957 if (num_login_attempts_ > 1) {
958 const user_manager::User* user =
959 user_manager::UserManager::Get()->FindUser(
960 last_login_attempt_username_);
961 if (user && (user->GetType() == user_manager::USER_TYPE_SUPERVISED))
962 error_id = IDS_LOGIN_ERROR_AUTHENTICATING_2ND_TIME_SUPERVISED;
966 login_display_->ShowError(error_id, num_login_attempts_, help_topic_id);
969 void ExistingUserController::ShowGaiaPasswordChanged(
970 const std::string& username) {
971 // Invalidate OAuth token, since it can't be correct after password is
972 // changed.
973 user_manager::UserManager::Get()->SaveUserOAuthStatus(
974 username, user_manager::User::OAUTH2_TOKEN_STATUS_INVALID);
976 login_display_->SetUIEnabled(true);
977 login_display_->ShowGaiaPasswordChanged(username);
980 void ExistingUserController::SendAccessibilityAlert(
981 const std::string& alert_text) {
982 AutomationManagerAsh::GetInstance()->HandleAlert(
983 ProfileHelper::GetSigninProfile(), alert_text);
986 void ExistingUserController::SetPublicSessionKeyboardLayoutAndLogin(
987 const UserContext& user_context,
988 scoped_ptr<base::ListValue> keyboard_layouts) {
989 UserContext new_user_context = user_context;
990 std::string keyboard_layout;
991 for (size_t i = 0; i < keyboard_layouts->GetSize(); ++i) {
992 base::DictionaryValue* entry = NULL;
993 keyboard_layouts->GetDictionary(i, &entry);
994 bool selected = false;
995 entry->GetBoolean("selected", &selected);
996 if (selected) {
997 entry->GetString("value", &keyboard_layout);
998 break;
1001 DCHECK(!keyboard_layout.empty());
1002 new_user_context.SetPublicSessionInputMethod(keyboard_layout);
1004 LoginAsPublicSessionInternal(new_user_context);
1007 void ExistingUserController::LoginAsPublicSessionInternal(
1008 const UserContext& user_context) {
1009 // Only one instance of LoginPerformer should exist at a time.
1010 login_performer_.reset(NULL);
1011 login_performer_.reset(new ChromeLoginPerformer(this));
1012 login_performer_->LoginAsPublicSession(user_context);
1013 SendAccessibilityAlert(
1014 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_PUBLIC_ACCOUNT));
1017 void ExistingUserController::PerformPreLoginActions(
1018 const UserContext& user_context) {
1019 // Disable clicking on other windows and status tray.
1020 login_display_->SetUIEnabled(false);
1022 if (last_login_attempt_username_ != user_context.GetUserID()) {
1023 last_login_attempt_username_ = user_context.GetUserID();
1024 num_login_attempts_ = 0;
1026 // Also reset state variables, which are used to determine password change.
1027 offline_failed_ = false;
1028 online_succeeded_for_.clear();
1031 // Guard in cases when we're called twice but login process is still active.
1032 // This might happen when login process is paused till signed settings status
1033 // is verified which results in Login* method called again as a callback.
1034 if (!is_login_in_progress_)
1035 num_login_attempts_++;
1037 is_login_in_progress_ = true;
1039 // Stop the auto-login timer when attempting login.
1040 StopPublicSessionAutoLoginTimer();
1043 void ExistingUserController::PerformLoginFinishedActions(
1044 bool start_public_session_timer) {
1045 is_login_in_progress_ = false;
1047 // Reenable clicking on other windows and status area.
1048 login_display_->SetUIEnabled(true);
1050 if (start_public_session_timer)
1051 StartPublicSessionAutoLoginTimer();
1054 void ExistingUserController::ContinueLoginIfDeviceNotDisabled(
1055 const base::Closure& continuation) {
1056 // Disable clicking on other windows and status tray.
1057 login_display_->SetUIEnabled(false);
1059 // Stop the auto-login timer.
1060 StopPublicSessionAutoLoginTimer();
1062 // Wait for the |cros_settings_| to become either trusted or permanently
1063 // untrusted.
1064 const CrosSettingsProvider::TrustedStatus status =
1065 cros_settings_->PrepareTrustedValues(base::Bind(
1066 &ExistingUserController::ContinueLoginIfDeviceNotDisabled,
1067 weak_factory_.GetWeakPtr(),
1068 continuation));
1069 if (status == CrosSettingsProvider::TEMPORARILY_UNTRUSTED)
1070 return;
1072 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
1073 // If the |cros_settings_| are permanently untrusted, show an error message
1074 // and refuse to log in.
1075 login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST,
1077 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
1079 // Re-enable clicking on other windows and the status area. Do not start the
1080 // auto-login timer though. Without trusted |cros_settings_|, no auto-login
1081 // can succeed.
1082 login_display_->SetUIEnabled(true);
1083 return;
1086 bool device_disabled = false;
1087 cros_settings_->GetBoolean(kDeviceDisabled, &device_disabled);
1088 if (device_disabled && system::DeviceDisablingManager::
1089 HonorDeviceDisablingDuringNormalOperation()) {
1090 // If the device is disabled, bail out. A device disabled screen will be
1091 // shown by the DeviceDisablingManager.
1093 // Re-enable clicking on other windows and the status area. Do not start the
1094 // auto-login timer though. On a disabled device, no auto-login can succeed.
1095 login_display_->SetUIEnabled(true);
1096 return;
1099 continuation.Run();
1102 void ExistingUserController::DoCompleteLogin(const UserContext& user_context) {
1103 PerformPreLoginActions(user_context);
1105 if (!time_init_.is_null()) {
1106 base::TimeDelta delta = base::Time::Now() - time_init_;
1107 UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToCompleteLoginTime", delta);
1108 time_init_ = base::Time(); // Reset to null.
1111 host_->OnCompleteLogin();
1112 PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION);
1115 void ExistingUserController::DoLogin(const UserContext& user_context,
1116 const SigninSpecifics& specifics) {
1117 if (is_login_in_progress_) {
1118 // If there is another login in progress, bail out. Do not re-enable
1119 // clicking on other windows and the status area. Do not start the
1120 // auto-login timer.
1121 return;
1124 if (user_context.GetUserType() != user_manager::USER_TYPE_REGULAR &&
1125 user_manager::UserManager::Get()->IsUserLoggedIn()) {
1126 // Multi-login is only allowed for regular users. If we are attempting to
1127 // do multi-login as another type of user somehow, bail out. Do not
1128 // re-enable clicking on other windows and the status area. Do not start the
1129 // auto-login timer.
1130 return;
1133 if (user_context.GetUserType() == user_manager::USER_TYPE_GUEST) {
1134 if (!specifics.guest_mode_url.empty()) {
1135 guest_mode_url_ = GURL(specifics.guest_mode_url);
1136 if (specifics.guest_mode_url_append_locale)
1137 guest_mode_url_ = google_util::AppendGoogleLocaleParam(
1138 guest_mode_url_, g_browser_process->GetApplicationLocale());
1140 LoginAsGuest();
1141 return;
1144 if (user_context.GetUserType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
1145 LoginAsPublicSession(user_context);
1146 return;
1149 if (user_context.GetUserType() == user_manager::USER_TYPE_KIOSK_APP) {
1150 LoginAsKioskApp(user_context.GetUserID(), specifics.kiosk_diagnostic_mode);
1151 return;
1154 // Regular user or supervised user login.
1156 if (!user_context.HasCredentials()) {
1157 // If credentials are missing, refuse to log in.
1159 // Reenable clicking on other windows and status area.
1160 login_display_->SetUIEnabled(true);
1161 // Restart the auto-login timer.
1162 StartPublicSessionAutoLoginTimer();
1165 PerformPreLoginActions(user_context);
1166 PerformLogin(user_context, LoginPerformer::AUTH_MODE_INTERNAL);
1169 } // namespace chromeos