Various changes required to support ChromeVox Next to read Views and Windows.
[chromium-blink-merge.git] / chrome / browser / chromeos / login / existing_user_controller.cc
blob5ae19520d888996cac5c8bd2b8f60db33d157fe5
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/accessibility/accessibility_events.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/browser_process_platform_part.h"
25 #include "chrome/browser/chrome_notification_types.h"
26 #include "chrome/browser/chromeos/boot_times_loader.h"
27 #include "chrome/browser/chromeos/customization/customization_document.h"
28 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
29 #include "chrome/browser/chromeos/login/auth/chrome_login_performer.h"
30 #include "chrome/browser/chromeos/login/helper.h"
31 #include "chrome/browser/chromeos/login/login_utils.h"
32 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
33 #include "chrome/browser/chromeos/login/signin_specifics.h"
34 #include "chrome/browser/chromeos/login/startup_utils.h"
35 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
36 #include "chrome/browser/chromeos/login/user_flow.h"
37 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
38 #include "chrome/browser/chromeos/login/wizard_controller.h"
39 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
40 #include "chrome/browser/chromeos/policy/device_local_account.h"
41 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
42 #include "chrome/browser/chromeos/profiles/profile_helper.h"
43 #include "chrome/browser/chromeos/settings/cros_settings.h"
44 #include "chrome/browser/chromeos/system/device_disabling_manager.h"
45 #include "chrome/browser/signin/easy_unlock_service.h"
46 #include "chrome/browser/ui/ash/accessibility/automation_manager_ash.h"
47 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
48 #include "chrome/common/chrome_switches.h"
49 #include "chrome/common/chrome_version_info.h"
50 #include "chrome/common/url_constants.h"
51 #include "chrome/grit/generated_resources.h"
52 #include "chromeos/chromeos_switches.h"
53 #include "chromeos/dbus/dbus_thread_manager.h"
54 #include "chromeos/dbus/power_manager_client.h"
55 #include "chromeos/dbus/session_manager_client.h"
56 #include "chromeos/login/user_names.h"
57 #include "chromeos/settings/cros_settings_names.h"
58 #include "components/google/core/browser/google_util.h"
59 #include "components/policy/core/common/cloud/cloud_policy_core.h"
60 #include "components/policy/core/common/cloud/cloud_policy_store.h"
61 #include "components/policy/core/common/policy_map.h"
62 #include "components/policy/core/common/policy_service.h"
63 #include "components/policy/core/common/policy_types.h"
64 #include "components/user_manager/user_manager.h"
65 #include "components/user_manager/user_type.h"
66 #include "content/public/browser/browser_thread.h"
67 #include "content/public/browser/notification_service.h"
68 #include "content/public/browser/notification_types.h"
69 #include "content/public/browser/user_metrics.h"
70 #include "google_apis/gaia/gaia_auth_util.h"
71 #include "google_apis/gaia/google_service_auth_error.h"
72 #include "net/http/http_auth_cache.h"
73 #include "net/http/http_network_session.h"
74 #include "net/http/http_transaction_factory.h"
75 #include "net/url_request/url_request_context.h"
76 #include "net/url_request/url_request_context_getter.h"
77 #include "policy/policy_constants.h"
78 #include "ui/accessibility/ax_enums.h"
79 #include "ui/base/l10n/l10n_util.h"
80 #include "ui/views/widget/widget.h"
82 namespace chromeos {
84 namespace {
86 // URL for account creation.
87 const char kCreateAccountURL[] =
88 "https://accounts.google.com/NewAccount?service=mail";
90 // Delay for transferring the auth cache to the system profile.
91 const long int kAuthCacheTransferDelayMs = 2000;
93 // Delay for restarting the ui if safe-mode login has failed.
94 const long int kSafeModeRestartUiDelayMs = 30000;
96 // Makes a call to the policy subsystem to reload the policy when we detect
97 // authentication change.
98 void RefreshPoliciesOnUIThread() {
99 if (g_browser_process->policy_service())
100 g_browser_process->policy_service()->RefreshPolicies(base::Closure());
103 // Copies any authentication details that were entered in the login profile in
104 // the mail profile to make sure all subsystems of Chrome can access the network
105 // with the provided authentication which are possibly for a proxy server.
106 void TransferContextAuthenticationsOnIOThread(
107 net::URLRequestContextGetter* default_profile_context_getter,
108 net::URLRequestContextGetter* browser_process_context_getter) {
109 net::HttpAuthCache* new_cache =
110 browser_process_context_getter->GetURLRequestContext()->
111 http_transaction_factory()->GetSession()->http_auth_cache();
112 net::HttpAuthCache* old_cache =
113 default_profile_context_getter->GetURLRequestContext()->
114 http_transaction_factory()->GetSession()->http_auth_cache();
115 new_cache->UpdateAllFrom(*old_cache);
116 VLOG(1) << "Main request context populated with authentication data.";
117 // Last but not least tell the policy subsystem to refresh now as it might
118 // have been stuck until now too.
119 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
120 base::Bind(&RefreshPoliciesOnUIThread));
123 // Record UMA for Easy sign-in outcome.
124 void RecordEasySignInOutcome(const std::string& user_id, bool success) {
125 EasyUnlockService* easy_unlock_service =
126 EasyUnlockService::Get(ProfileHelper::GetSigninProfile());
127 if (!easy_unlock_service)
128 return;
129 easy_unlock_service->RecordEasySignInOutcome(user_id, success);
132 // Record UMA for password login of regular user when Easy sign-in is enabled.
133 void RecordPasswordLoginEvent(const UserContext& user_context) {
134 EasyUnlockService* easy_unlock_service =
135 EasyUnlockService::Get(ProfileHelper::GetSigninProfile());
136 if (user_context.GetUserType() == user_manager::USER_TYPE_REGULAR &&
137 user_context.GetAuthFlow() == UserContext::AUTH_FLOW_OFFLINE &&
138 easy_unlock_service) {
139 easy_unlock_service->RecordPasswordLoginEvent(user_context.GetUserID());
143 bool CanShowDebuggingFeatures() {
144 // We need to be on the login screen and in dev mode to show this menu item.
145 return CommandLine::ForCurrentProcess()->HasSwitch(
146 chromeos::switches::kSystemDevMode) &&
147 CommandLine::ForCurrentProcess()->HasSwitch(
148 chromeos::switches::kLoginManager) &&
149 !user_manager::UserManager::Get()->IsSessionStarted();
152 } // namespace
154 // static
155 ExistingUserController* ExistingUserController::current_controller_ = NULL;
157 ////////////////////////////////////////////////////////////////////////////////
158 // ExistingUserController, public:
160 ExistingUserController::ExistingUserController(LoginDisplayHost* host)
161 : auth_status_consumer_(NULL),
162 last_login_attempt_auth_flow_(UserContext::AUTH_FLOW_OFFLINE),
163 host_(host),
164 login_display_(host_->CreateLoginDisplay(this)),
165 num_login_attempts_(0),
166 cros_settings_(CrosSettings::Get()),
167 offline_failed_(false),
168 is_login_in_progress_(false),
169 password_changed_(false),
170 auth_mode_(LoginPerformer::AUTH_MODE_EXTENSION),
171 signin_screen_ready_(false),
172 network_state_helper_(new login::NetworkStateHelper),
173 weak_factory_(this) {
174 DCHECK(current_controller_ == NULL);
175 current_controller_ = this;
177 registrar_.Add(this,
178 chrome::NOTIFICATION_USER_LIST_CHANGED,
179 content::NotificationService::AllSources());
180 registrar_.Add(this,
181 chrome::NOTIFICATION_AUTH_SUPPLIED,
182 content::NotificationService::AllSources());
183 registrar_.Add(this,
184 chrome::NOTIFICATION_SESSION_STARTED,
185 content::NotificationService::AllSources());
186 show_user_names_subscription_ = cros_settings_->AddSettingsObserver(
187 kAccountsPrefShowUserNamesOnSignIn,
188 base::Bind(&ExistingUserController::DeviceSettingsChanged,
189 base::Unretained(this)));
190 allow_new_user_subscription_ = cros_settings_->AddSettingsObserver(
191 kAccountsPrefAllowNewUser,
192 base::Bind(&ExistingUserController::DeviceSettingsChanged,
193 base::Unretained(this)));
194 allow_guest_subscription_ = cros_settings_->AddSettingsObserver(
195 kAccountsPrefAllowGuest,
196 base::Bind(&ExistingUserController::DeviceSettingsChanged,
197 base::Unretained(this)));
198 allow_supervised_user_subscription_ = cros_settings_->AddSettingsObserver(
199 kAccountsPrefSupervisedUsersEnabled,
200 base::Bind(&ExistingUserController::DeviceSettingsChanged,
201 base::Unretained(this)));
202 users_subscription_ = cros_settings_->AddSettingsObserver(
203 kAccountsPrefUsers,
204 base::Bind(&ExistingUserController::DeviceSettingsChanged,
205 base::Unretained(this)));
206 local_account_auto_login_id_subscription_ =
207 cros_settings_->AddSettingsObserver(
208 kAccountsPrefDeviceLocalAccountAutoLoginId,
209 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
210 base::Unretained(this)));
211 local_account_auto_login_delay_subscription_ =
212 cros_settings_->AddSettingsObserver(
213 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
214 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
215 base::Unretained(this)));
218 void ExistingUserController::Init(const user_manager::UserList& users) {
219 time_init_ = base::Time::Now();
220 UpdateLoginDisplay(users);
221 ConfigurePublicSessionAutoLogin();
224 void ExistingUserController::UpdateLoginDisplay(
225 const user_manager::UserList& users) {
226 bool show_users_on_signin;
227 user_manager::UserList filtered_users;
229 cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn,
230 &show_users_on_signin);
231 for (user_manager::UserList::const_iterator it = users.begin();
232 it != users.end();
233 ++it) {
234 // TODO(xiyuan): Clean user profile whose email is not in whitelist.
235 bool meets_supervised_requirements =
236 (*it)->GetType() != user_manager::USER_TYPE_SUPERVISED ||
237 user_manager::UserManager::Get()->AreSupervisedUsersAllowed();
238 bool meets_whitelist_requirements =
239 LoginUtils::IsWhitelisted((*it)->email(), NULL) ||
240 !(*it)->HasGaiaAccount();
242 // Public session accounts are always shown on login screen.
243 bool meets_show_users_requirements =
244 show_users_on_signin ||
245 (*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
246 if (meets_supervised_requirements &&
247 meets_whitelist_requirements &&
248 meets_show_users_requirements) {
249 filtered_users.push_back(*it);
253 // If no user pods are visible, fallback to single new user pod which will
254 // have guest session link.
255 bool show_guest;
256 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &show_guest);
257 show_users_on_signin |= !filtered_users.empty();
258 show_guest &= !filtered_users.empty();
259 bool show_new_user = true;
260 login_display_->set_parent_window(GetNativeWindow());
261 login_display_->Init(
262 filtered_users, show_guest, show_users_on_signin, show_new_user);
263 host_->OnPreferencesChanged();
266 ////////////////////////////////////////////////////////////////////////////////
267 // ExistingUserController, content::NotificationObserver implementation:
270 void ExistingUserController::Observe(
271 int type,
272 const content::NotificationSource& source,
273 const content::NotificationDetails& details) {
274 if (type == chrome::NOTIFICATION_SESSION_STARTED) {
275 // Stop listening to any notification once session has started.
276 // Sign in screen objects are marked for deletion with DeleteSoon so
277 // make sure no object would be used after session has started.
278 // http://crbug.com/125276
279 registrar_.RemoveAll();
280 return;
282 if (type == chrome::NOTIFICATION_USER_LIST_CHANGED) {
283 DeviceSettingsChanged();
284 return;
286 if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
287 // Possibly the user has authenticated against a proxy server and we might
288 // need the credentials for enrollment and other system requests from the
289 // main |g_browser_process| request context (see bug
290 // http://crosbug.com/24861). So we transfer any credentials to the global
291 // request context here.
292 // The issue we have here is that the NOTIFICATION_AUTH_SUPPLIED is sent
293 // just after the UI is closed but before the new credentials were stored
294 // in the profile. Therefore we have to give it some time to make sure it
295 // has been updated before we copy it.
296 VLOG(1) << "Authentication was entered manually, possibly for proxyauth.";
297 scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter =
298 g_browser_process->system_request_context();
299 Profile* signin_profile = ProfileHelper::GetSigninProfile();
300 scoped_refptr<net::URLRequestContextGetter> signin_profile_context_getter =
301 signin_profile->GetRequestContext();
302 DCHECK(browser_process_context_getter.get());
303 DCHECK(signin_profile_context_getter.get());
304 content::BrowserThread::PostDelayedTask(
305 content::BrowserThread::IO, FROM_HERE,
306 base::Bind(&TransferContextAuthenticationsOnIOThread,
307 signin_profile_context_getter,
308 browser_process_context_getter),
309 base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs));
313 ////////////////////////////////////////////////////////////////////////////////
314 // ExistingUserController, private:
316 ExistingUserController::~ExistingUserController() {
317 LoginUtils::Get()->DelegateDeleted(this);
319 if (current_controller_ == this) {
320 current_controller_ = NULL;
321 } else {
322 NOTREACHED() << "More than one controller are alive.";
324 DCHECK(login_display_.get());
327 ////////////////////////////////////////////////////////////////////////////////
328 // ExistingUserController, LoginDisplay::Delegate implementation:
331 void ExistingUserController::CancelPasswordChangedFlow() {
332 login_performer_.reset(NULL);
333 PerformLoginFinishedActions(true /* start public session timer */);
336 void ExistingUserController::CreateAccount() {
337 content::RecordAction(base::UserMetricsAction("Login.CreateAccount"));
338 guest_mode_url_ = google_util::AppendGoogleLocaleParam(
339 GURL(kCreateAccountURL), g_browser_process->GetApplicationLocale());
340 Login(UserContext(user_manager::USER_TYPE_GUEST, std::string()),
341 SigninSpecifics());
344 void ExistingUserController::CompleteLogin(const UserContext& user_context) {
345 login_display_->set_signin_completed(true);
346 if (!host_) {
347 // Complete login event was generated already from UI. Ignore notification.
348 return;
351 PerformPreLoginActions(user_context);
353 if (!time_init_.is_null()) {
354 base::TimeDelta delta = base::Time::Now() - time_init_;
355 UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToCompleteLoginTime", delta);
356 time_init_ = base::Time(); // Reset to null.
359 host_->OnCompleteLogin();
360 PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION);
363 base::string16 ExistingUserController::GetConnectedNetworkName() {
364 return network_state_helper_->GetCurrentNetworkName();
367 bool ExistingUserController::IsSigninInProgress() const {
368 return is_login_in_progress_;
371 void ExistingUserController::Login(const UserContext& user_context,
372 const SigninSpecifics& specifics) {
373 // Disable clicking on other windows and status tray.
374 login_display_->SetUIEnabled(false);
376 // Stop the auto-login timer.
377 StopPublicSessionAutoLoginTimer();
379 // Wait for the |cros_settings_| to become either trusted or permanently
380 // untrusted.
381 const CrosSettingsProvider::TrustedStatus status =
382 cros_settings_->PrepareTrustedValues(base::Bind(
383 &ExistingUserController::Login,
384 weak_factory_.GetWeakPtr(),
385 user_context,
386 specifics));
387 if (status == CrosSettingsProvider::TEMPORARILY_UNTRUSTED)
388 return;
390 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
391 // If the |cros_settings_| are permanently untrusted, show an error message
392 // and refuse to log in.
393 login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST,
395 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
397 // Re-enable clicking on other windows and the status area. Do not start the
398 // auto-login timer though. Without trusted |cros_settings_|, no auto-login
399 // can succeed.
400 login_display_->SetUIEnabled(true);
401 return;
404 bool device_disabled = false;
405 cros_settings_->GetBoolean(kDeviceDisabled, &device_disabled);
406 if (device_disabled && system::DeviceDisablingManager::
407 HonorDeviceDisablingDuringNormalOperation()) {
408 // If the device is disabled, bail out. A device disabled screen will be
409 // shown by the DeviceDisablingManager.
411 // Re-enable clicking on other windows and the status area. Do not start the
412 // auto-login timer though. On a disabled device, no auto-login can succeed.
413 login_display_->SetUIEnabled(true);
414 return;
417 if (is_login_in_progress_) {
418 // If there is another login in progress, bail out. Do not re-enable
419 // clicking on other windows and the status area. Do not start the
420 // auto-login timer.
421 return;
424 if (user_context.GetUserType() != user_manager::USER_TYPE_REGULAR &&
425 user_manager::UserManager::Get()->IsUserLoggedIn()) {
426 // Multi-login is only allowed for regular users. If we are attempting to
427 // do multi-login as another type of user somehow, bail out. Do not
428 // re-enable clicking on other windows and the status area. Do not start the
429 // auto-login timer.
430 return;
433 if (user_context.GetUserType() == user_manager::USER_TYPE_GUEST) {
434 if (!specifics.guest_mode_url.empty()) {
435 guest_mode_url_ = GURL(specifics.guest_mode_url);
436 if (specifics.guest_mode_url_append_locale)
437 guest_mode_url_ = google_util::AppendGoogleLocaleParam(
438 guest_mode_url_, g_browser_process->GetApplicationLocale());
440 LoginAsGuest();
441 return;
444 if (user_context.GetUserType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
445 LoginAsPublicSession(user_context);
446 return;
449 if (user_context.GetUserType() == user_manager::USER_TYPE_RETAIL_MODE) {
450 LoginAsRetailModeUser();
451 return;
454 if (user_context.GetUserType() == user_manager::USER_TYPE_KIOSK_APP) {
455 LoginAsKioskApp(user_context.GetUserID(), specifics.kiosk_diagnostic_mode);
456 return;
459 // Regular user or supervised user login.
461 if (!user_context.HasCredentials()) {
462 // If credentials are missing, refuse to log in.
464 // Reenable clicking on other windows and status area.
465 login_display_->SetUIEnabled(true);
466 // Restart the auto-login timer.
467 StartPublicSessionAutoLoginTimer();
470 PerformPreLoginActions(user_context);
471 PerformLogin(user_context, LoginPerformer::AUTH_MODE_INTERNAL);
474 void ExistingUserController::PerformLogin(
475 const UserContext& user_context,
476 LoginPerformer::AuthorizationMode auth_mode) {
477 // TODO(antrim): remove this output once crash reason is found.
478 LOG(ERROR) << "Setting flow from PerformLogin";
479 ChromeUserManager::Get()
480 ->GetUserFlow(user_context.GetUserID())
481 ->SetHost(host_);
483 BootTimesLoader::Get()->RecordLoginAttempted();
485 last_login_attempt_auth_flow_ = user_context.GetAuthFlow();
487 // Use the same LoginPerformer for subsequent login as it has state
488 // such as Authenticator instance.
489 if (!login_performer_.get() || num_login_attempts_ <= 1) {
490 // Only one instance of LoginPerformer should exist at a time.
491 login_performer_.reset(NULL);
492 login_performer_.reset(new ChromeLoginPerformer(this));
495 if (gaia::ExtractDomainName(user_context.GetUserID()) ==
496 chromeos::login::kSupervisedUserDomain) {
497 login_performer_->LoginAsSupervisedUser(user_context);
498 } else {
499 login_performer_->PerformLogin(user_context, auth_mode);
500 RecordPasswordLoginEvent(user_context);
502 SendAccessibilityAlert(
503 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN));
506 void ExistingUserController::MigrateUserData(const std::string& old_password) {
507 // LoginPerformer instance has state of the user so it should exist.
508 if (login_performer_.get())
509 login_performer_->RecoverEncryptedData(old_password);
513 void ExistingUserController::OnSigninScreenReady() {
514 signin_screen_ready_ = true;
515 StartPublicSessionAutoLoginTimer();
518 void ExistingUserController::OnStartEnterpriseEnrollment() {
519 if (KioskAppManager::Get()->IsConsumerKioskDeviceWithAutoLaunch()) {
520 LOG(WARNING) << "Enterprise enrollment is not available after kiosk auto "
521 "launch is set.";
522 return;
525 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
526 base::Bind(&ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
527 weak_factory_.GetWeakPtr()));
530 void ExistingUserController::OnStartEnableDebuggingScreen() {
531 if (CanShowDebuggingFeatures())
532 ShowEnableDebuggingScreen();
535 void ExistingUserController::OnStartKioskEnableScreen() {
536 KioskAppManager::Get()->GetConsumerKioskAutoLaunchStatus(
537 base::Bind(
538 &ExistingUserController::OnConsumerKioskAutoLaunchCheckCompleted,
539 weak_factory_.GetWeakPtr()));
542 void ExistingUserController::OnStartKioskAutolaunchScreen() {
543 ShowKioskAutolaunchScreen();
546 void ExistingUserController::ResyncUserData() {
547 // LoginPerformer instance has state of the user so it should exist.
548 if (login_performer_.get())
549 login_performer_->ResyncEncryptedData();
552 void ExistingUserController::SetDisplayEmail(const std::string& email) {
553 display_email_ = email;
556 void ExistingUserController::ShowWrongHWIDScreen() {
557 host_->StartWizard(WizardController::kWrongHWIDScreenName);
560 void ExistingUserController::Signout() {
561 NOTREACHED();
564 void ExistingUserController::OnConsumerKioskAutoLaunchCheckCompleted(
565 KioskAppManager::ConsumerKioskAutoLaunchStatus status) {
566 if (status == KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE)
567 ShowKioskEnableScreen();
570 void ExistingUserController::OnEnrollmentOwnershipCheckCompleted(
571 DeviceSettingsService::OwnershipStatus status) {
572 if (status == DeviceSettingsService::OWNERSHIP_NONE) {
573 ShowEnrollmentScreen();
574 } else if (status == DeviceSettingsService::OWNERSHIP_TAKEN) {
575 // On a device that is already owned we might want to allow users to
576 // re-enroll if the policy information is invalid.
577 CrosSettingsProvider::TrustedStatus trusted_status =
578 CrosSettings::Get()->PrepareTrustedValues(
579 base::Bind(
580 &ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
581 weak_factory_.GetWeakPtr(), status));
582 if (trusted_status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
583 ShowEnrollmentScreen();
585 } else {
586 // OwnershipService::GetStatusAsync is supposed to return either
587 // OWNERSHIP_NONE or OWNERSHIP_TAKEN.
588 NOTREACHED();
592 void ExistingUserController::ShowEnrollmentScreen() {
593 host_->StartWizard(WizardController::kEnrollmentScreenName);
596 void ExistingUserController::ShowResetScreen() {
597 host_->StartWizard(WizardController::kResetScreenName);
600 void ExistingUserController::ShowEnableDebuggingScreen() {
601 host_->StartWizard(WizardController::kEnableDebuggingScreenName);
604 void ExistingUserController::ShowKioskEnableScreen() {
605 host_->StartWizard(WizardController::kKioskEnableScreenName);
608 void ExistingUserController::ShowKioskAutolaunchScreen() {
609 host_->StartWizard(WizardController::kKioskAutolaunchScreenName);
612 void ExistingUserController::ShowTPMError() {
613 login_display_->SetUIEnabled(false);
614 login_display_->ShowErrorScreen(LoginDisplay::TPM_ERROR);
617 ////////////////////////////////////////////////////////////////////////////////
618 // ExistingUserController, LoginPerformer::Delegate implementation:
621 void ExistingUserController::OnAuthFailure(const AuthFailure& failure) {
622 offline_failed_ = true;
623 guest_mode_url_ = GURL::EmptyGURL();
624 std::string error = failure.GetErrorString();
626 PerformLoginFinishedActions(false /* don't start public session timer */);
628 // TODO(xiyuan): Move into EasyUnlockUserLoginFlow.
629 if (last_login_attempt_auth_flow_ == UserContext::AUTH_FLOW_EASY_UNLOCK)
630 RecordEasySignInOutcome(last_login_attempt_username_, false);
632 if (ChromeUserManager::Get()
633 ->GetUserFlow(last_login_attempt_username_)
634 ->HandleLoginFailure(failure)) {
635 return;
638 if (failure.reason() == AuthFailure::OWNER_REQUIRED) {
639 ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error);
640 content::BrowserThread::PostDelayedTask(
641 content::BrowserThread::UI, FROM_HERE,
642 base::Bind(&SessionManagerClient::StopSession,
643 base::Unretained(DBusThreadManager::Get()->
644 GetSessionManagerClient())),
645 base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs));
646 } else if (failure.reason() == AuthFailure::TPM_ERROR) {
647 ShowTPMError();
648 } else if (!online_succeeded_for_.empty()) {
649 ShowGaiaPasswordChanged(online_succeeded_for_);
650 } else {
651 // Check networking after trying to login in case user is
652 // cached locally or the local admin account.
653 bool is_known_user = user_manager::UserManager::Get()->IsKnownUser(
654 last_login_attempt_username_);
655 if (!network_state_helper_->IsConnected()) {
656 if (is_known_user)
657 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
658 else
659 ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
660 } else {
661 // TODO(nkostylev): Cleanup rest of ClientLogin related code.
662 if (failure.reason() == AuthFailure::NETWORK_AUTH_FAILED &&
663 failure.error().state() ==
664 GoogleServiceAuthError::HOSTED_NOT_ALLOWED) {
665 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED, error);
666 } else {
667 if (!is_known_user)
668 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
669 else
670 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
673 login_display_->ClearAndEnablePassword();
674 StartPublicSessionAutoLoginTimer();
677 // Reset user flow to default, so that special flow will not affect next
678 // attempt.
679 ChromeUserManager::Get()->ResetUserFlow(last_login_attempt_username_);
681 if (auth_status_consumer_)
682 auth_status_consumer_->OnAuthFailure(failure);
684 // Clear the recorded displayed email so it won't affect any future attempts.
685 display_email_.clear();
688 void ExistingUserController::OnAuthSuccess(const UserContext& user_context) {
689 is_login_in_progress_ = false;
690 offline_failed_ = false;
691 login_display_->set_signin_completed(true);
693 // Login performer will be gone so cache this value to use
694 // once profile is loaded.
695 password_changed_ = login_performer_->password_changed();
696 auth_mode_ = login_performer_->auth_mode();
698 ChromeUserManager::Get()
699 ->GetUserFlow(user_context.GetUserID())
700 ->HandleLoginSuccess(user_context);
702 // TODO(xiyuan): Move into EasyUnlockUserLoginFlow.
703 if (last_login_attempt_auth_flow_ == UserContext::AUTH_FLOW_EASY_UNLOCK) {
704 DCHECK_EQ(last_login_attempt_username_, user_context.GetUserID());
705 DCHECK_EQ(last_login_attempt_auth_flow_, user_context.GetAuthFlow());
706 RecordEasySignInOutcome(last_login_attempt_username_, true);
709 StopPublicSessionAutoLoginTimer();
711 const bool has_auth_cookies =
712 login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION &&
713 user_context.GetAuthCode().empty();
715 // LoginPerformer instance will delete itself in case of successful auth.
716 login_performer_->set_delegate(NULL);
717 ignore_result(login_performer_.release());
719 // Will call OnProfilePrepared() in the end.
720 LoginUtils::Get()->PrepareProfile(user_context,
721 has_auth_cookies,
722 false, // Start session for user.
723 this);
725 // Update user's displayed email.
726 if (!display_email_.empty()) {
727 user_manager::UserManager::Get()->SaveUserDisplayEmail(
728 user_context.GetUserID(), display_email_);
729 display_email_.clear();
733 void ExistingUserController::OnProfilePrepared(Profile* profile,
734 bool browser_launched) {
735 // Reenable clicking on other windows and status area.
736 login_display_->SetUIEnabled(true);
738 if (browser_launched)
739 host_ = NULL;
741 // Inform |auth_status_consumer_| about successful login.
742 // TODO(nkostylev): Pass UserContext back crbug.com/424550
743 if (auth_status_consumer_) {
744 auth_status_consumer_->
745 OnAuthSuccess(UserContext(last_login_attempt_username_));
749 void ExistingUserController::OnOffTheRecordAuthSuccess() {
750 is_login_in_progress_ = false;
751 offline_failed_ = false;
753 // Mark the device as registered., i.e. the second part of OOBE as completed.
754 if (!StartupUtils::IsDeviceRegistered())
755 StartupUtils::MarkDeviceRegistered(base::Closure());
757 UserSessionManager::GetInstance()->CompleteGuestSessionLogin(guest_mode_url_);
759 if (auth_status_consumer_)
760 auth_status_consumer_->OnOffTheRecordAuthSuccess();
763 void ExistingUserController::OnPasswordChangeDetected() {
764 is_login_in_progress_ = false;
765 offline_failed_ = false;
767 // Must not proceed without signature verification.
768 if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
769 base::Bind(&ExistingUserController::OnPasswordChangeDetected,
770 weak_factory_.GetWeakPtr()))) {
771 // Value of owner email is still not verified.
772 // Another attempt will be invoked after verification completion.
773 return;
776 if (ChromeUserManager::Get()
777 ->GetUserFlow(last_login_attempt_username_)
778 ->HandlePasswordChangeDetected()) {
779 return;
782 // True if user has already made an attempt to enter old password and failed.
783 bool show_invalid_old_password_error =
784 login_performer_->password_changed_callback_count() > 1;
786 // Note: We allow owner using "full sync" mode which will recreate
787 // cryptohome and deal with owner private key being lost. This also allows
788 // us to recover from a lost owner password/homedir.
789 // TODO(gspencer): We shouldn't have to erase stateful data when
790 // doing this. See http://crosbug.com/9115 http://crosbug.com/7792
791 login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error);
793 if (auth_status_consumer_)
794 auth_status_consumer_->OnPasswordChangeDetected();
796 display_email_.clear();
799 void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
800 PerformLoginFinishedActions(true /* start public session timer */);
801 offline_failed_ = false;
803 ShowError(IDS_LOGIN_ERROR_WHITELIST, email);
805 login_display_->ShowSigninUI(email);
807 if (auth_status_consumer_) {
808 auth_status_consumer_->OnAuthFailure(
809 AuthFailure(AuthFailure::WHITELIST_CHECK_FAILED));
812 display_email_.clear();
815 void ExistingUserController::PolicyLoadFailed() {
816 ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, "");
818 PerformLoginFinishedActions(false /* don't start public session timer */);
819 offline_failed_ = false;
820 display_email_.clear();
823 void ExistingUserController::OnOnlineChecked(const std::string& username,
824 bool success) {
825 if (success && last_login_attempt_username_ == username) {
826 online_succeeded_for_ = username;
827 // Wait for login attempt to end, if it hasn't yet.
828 if (offline_failed_ && !is_login_in_progress_)
829 ShowGaiaPasswordChanged(username);
833 ////////////////////////////////////////////////////////////////////////////////
834 // ExistingUserController, private:
836 void ExistingUserController::DeviceSettingsChanged() {
837 if (host_ != NULL) {
838 // Signed settings or user list changed. Notify views and update them.
839 UpdateLoginDisplay(user_manager::UserManager::Get()->GetUsers());
840 ConfigurePublicSessionAutoLogin();
841 return;
845 LoginPerformer::AuthorizationMode ExistingUserController::auth_mode() const {
846 if (login_performer_)
847 return login_performer_->auth_mode();
849 return auth_mode_;
852 bool ExistingUserController::password_changed() const {
853 if (login_performer_)
854 return login_performer_->password_changed();
856 return password_changed_;
859 void ExistingUserController::LoginAsRetailModeUser() {
860 PerformPreLoginActions(UserContext(user_manager::USER_TYPE_RETAIL_MODE,
861 chromeos::login::kRetailModeUserName));
863 // TODO(rkc): Add a CHECK to make sure retail mode logins are allowed once
864 // the enterprise policy wiring is done for retail mode.
866 // Only one instance of LoginPerformer should exist at a time.
867 login_performer_.reset(NULL);
868 login_performer_.reset(new ChromeLoginPerformer(this));
869 login_performer_->LoginRetailMode();
870 SendAccessibilityAlert(
871 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_DEMOUSER));
874 void ExistingUserController::LoginAsGuest() {
875 PerformPreLoginActions(UserContext(user_manager::USER_TYPE_GUEST,
876 chromeos::login::kGuestUserName));
878 bool allow_guest;
879 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
880 if (!allow_guest) {
881 // Disallowed. The UI should normally not show the guest pod but if for some
882 // reason this has been made available to the user here is the time to tell
883 // this nicely.
884 login_display_->ShowError(IDS_LOGIN_ERROR_WHITELIST, 1,
885 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
886 PerformLoginFinishedActions(true /* start public session timer */);
887 display_email_.clear();
888 return;
891 // Only one instance of LoginPerformer should exist at a time.
892 login_performer_.reset(NULL);
893 login_performer_.reset(new ChromeLoginPerformer(this));
894 login_performer_->LoginOffTheRecord();
895 SendAccessibilityAlert(
896 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_OFFRECORD));
899 void ExistingUserController::LoginAsPublicSession(
900 const UserContext& user_context) {
901 PerformPreLoginActions(user_context);
903 // If there is no public account with the given user ID, logging in is not
904 // possible.
905 const user_manager::User* user =
906 user_manager::UserManager::Get()->FindUser(user_context.GetUserID());
907 if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
908 PerformLoginFinishedActions(true /* start public session timer */);
909 return;
912 UserContext new_user_context = user_context;
913 std::string locale = user_context.GetPublicSessionLocale();
914 if (locale.empty()) {
915 // When performing auto-login, no locale is chosen by the user. Check
916 // whether a list of recommended locales was set by policy. If so, use its
917 // first entry. Otherwise, |locale| will remain blank, indicating that the
918 // public session should use the current UI locale.
919 const policy::PolicyMap::Entry* entry = g_browser_process->platform_part()->
920 browser_policy_connector_chromeos()->
921 GetDeviceLocalAccountPolicyService()->
922 GetBrokerForUser(user_context.GetUserID())->core()->store()->
923 policy_map().Get(policy::key::kSessionLocales);
924 base::ListValue const* list = NULL;
925 if (entry &&
926 entry->level == policy::POLICY_LEVEL_RECOMMENDED &&
927 entry->value &&
928 entry->value->GetAsList(&list)) {
929 if (list->GetString(0, &locale))
930 new_user_context.SetPublicSessionLocale(locale);
934 if (!locale.empty() &&
935 new_user_context.GetPublicSessionInputMethod().empty()) {
936 // When |locale| is set, a suitable keyboard layout should be chosen. In
937 // most cases, this will already be the case because the UI shows a list of
938 // keyboard layouts suitable for the |locale| and ensures that one of them
939 // us selected. However, it is still possible that |locale| is set but no
940 // keyboard layout was chosen:
941 // * The list of keyboard layouts is updated asynchronously. If the user
942 // enters the public session before the list of keyboard layouts for the
943 // |locale| has been retrieved, the UI will indicate that no keyboard
944 // layout was chosen.
945 // * During auto-login, the |locale| is set in this method and a suitable
946 // keyboard layout must be chosen next.
948 // The list of suitable keyboard layouts is constructed asynchronously. Once
949 // it has been retrieved, |SetPublicSessionKeyboardLayoutAndLogin| will
950 // select the first layout from the list and continue login.
951 GetKeyboardLayoutsForLocale(
952 base::Bind(
953 &ExistingUserController::SetPublicSessionKeyboardLayoutAndLogin,
954 weak_factory_.GetWeakPtr(),
955 new_user_context),
956 locale);
957 return;
960 // The user chose a locale and a suitable keyboard layout or left both unset.
961 // Login can continue immediately.
962 LoginAsPublicSessionInternal(new_user_context);
965 void ExistingUserController::LoginAsKioskApp(const std::string& app_id,
966 bool diagnostic_mode) {
967 host_->StartAppLaunch(app_id, diagnostic_mode);
970 void ExistingUserController::ConfigurePublicSessionAutoLogin() {
971 std::string auto_login_account_id;
972 cros_settings_->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
973 &auto_login_account_id);
974 const std::vector<policy::DeviceLocalAccount> device_local_accounts =
975 policy::GetDeviceLocalAccounts(cros_settings_);
977 public_session_auto_login_username_.clear();
978 for (std::vector<policy::DeviceLocalAccount>::const_iterator
979 it = device_local_accounts.begin();
980 it != device_local_accounts.end(); ++it) {
981 if (it->account_id == auto_login_account_id) {
982 public_session_auto_login_username_ = it->user_id;
983 break;
987 const user_manager::User* user = user_manager::UserManager::Get()->FindUser(
988 public_session_auto_login_username_);
989 if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT)
990 public_session_auto_login_username_.clear();
992 if (!cros_settings_->GetInteger(
993 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
994 &public_session_auto_login_delay_)) {
995 public_session_auto_login_delay_ = 0;
998 if (!public_session_auto_login_username_.empty())
999 StartPublicSessionAutoLoginTimer();
1000 else
1001 StopPublicSessionAutoLoginTimer();
1004 void ExistingUserController::ResetPublicSessionAutoLoginTimer() {
1005 // Only restart the auto-login timer if it's already running.
1006 if (auto_login_timer_ && auto_login_timer_->IsRunning()) {
1007 StopPublicSessionAutoLoginTimer();
1008 StartPublicSessionAutoLoginTimer();
1012 void ExistingUserController::OnPublicSessionAutoLoginTimerFire() {
1013 CHECK(signin_screen_ready_ && !public_session_auto_login_username_.empty());
1014 Login(UserContext(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
1015 public_session_auto_login_username_),
1016 SigninSpecifics());
1019 void ExistingUserController::StopPublicSessionAutoLoginTimer() {
1020 if (auto_login_timer_)
1021 auto_login_timer_->Stop();
1024 void ExistingUserController::StartPublicSessionAutoLoginTimer() {
1025 if (!signin_screen_ready_ ||
1026 is_login_in_progress_ ||
1027 public_session_auto_login_username_.empty()) {
1028 return;
1031 // Start the auto-login timer.
1032 if (!auto_login_timer_)
1033 auto_login_timer_.reset(new base::OneShotTimer<ExistingUserController>);
1035 auto_login_timer_->Start(
1036 FROM_HERE,
1037 base::TimeDelta::FromMilliseconds(
1038 public_session_auto_login_delay_),
1039 base::Bind(
1040 &ExistingUserController::OnPublicSessionAutoLoginTimerFire,
1041 weak_factory_.GetWeakPtr()));
1044 gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
1045 return host_->GetNativeWindow();
1048 void ExistingUserController::ShowError(int error_id,
1049 const std::string& details) {
1050 // TODO(dpolukhin): show detailed error info. |details| string contains
1051 // low level error info that is not localized and even is not user friendly.
1052 // For now just ignore it because error_text contains all required information
1053 // for end users, developers can see details string in Chrome logs.
1054 VLOG(1) << details;
1055 HelpAppLauncher::HelpTopic help_topic_id;
1056 bool is_offline = !network_state_helper_->IsConnected();
1057 switch (login_performer_->error().state()) {
1058 case GoogleServiceAuthError::CONNECTION_FAILED:
1059 help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE;
1060 break;
1061 case GoogleServiceAuthError::ACCOUNT_DISABLED:
1062 help_topic_id = HelpAppLauncher::HELP_ACCOUNT_DISABLED;
1063 break;
1064 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
1065 help_topic_id = HelpAppLauncher::HELP_HOSTED_ACCOUNT;
1066 break;
1067 default:
1068 help_topic_id = is_offline ?
1069 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE :
1070 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT;
1071 break;
1074 if (error_id == IDS_LOGIN_ERROR_AUTHENTICATING) {
1075 if (num_login_attempts_ > 1) {
1076 const user_manager::User* user =
1077 user_manager::UserManager::Get()->FindUser(
1078 last_login_attempt_username_);
1079 if (user && (user->GetType() == user_manager::USER_TYPE_SUPERVISED))
1080 error_id = IDS_LOGIN_ERROR_AUTHENTICATING_2ND_TIME_SUPERVISED;
1084 login_display_->ShowError(error_id, num_login_attempts_, help_topic_id);
1087 void ExistingUserController::ShowGaiaPasswordChanged(
1088 const std::string& username) {
1089 // Invalidate OAuth token, since it can't be correct after password is
1090 // changed.
1091 user_manager::UserManager::Get()->SaveUserOAuthStatus(
1092 username, user_manager::User::OAUTH2_TOKEN_STATUS_INVALID);
1094 login_display_->SetUIEnabled(true);
1095 login_display_->ShowGaiaPasswordChanged(username);
1098 void ExistingUserController::SendAccessibilityAlert(
1099 const std::string& alert_text) {
1100 AccessibilityAlertInfo event(ProfileHelper::GetSigninProfile(), alert_text);
1101 SendControlAccessibilityNotification(
1102 ui::AX_EVENT_VALUE_CHANGED, &event);
1104 AutomationManagerAsh::GetInstance()->HandleAlert(
1105 ProfileHelper::GetSigninProfile(), alert_text);
1108 void ExistingUserController::SetPublicSessionKeyboardLayoutAndLogin(
1109 const UserContext& user_context,
1110 scoped_ptr<base::ListValue> keyboard_layouts) {
1111 UserContext new_user_context = user_context;
1112 std::string keyboard_layout;
1113 for (size_t i = 0; i < keyboard_layouts->GetSize(); ++i) {
1114 base::DictionaryValue* entry = NULL;
1115 keyboard_layouts->GetDictionary(i, &entry);
1116 bool selected = false;
1117 entry->GetBoolean("selected", &selected);
1118 if (selected) {
1119 entry->GetString("value", &keyboard_layout);
1120 break;
1123 DCHECK(!keyboard_layout.empty());
1124 new_user_context.SetPublicSessionInputMethod(keyboard_layout);
1126 LoginAsPublicSessionInternal(new_user_context);
1129 void ExistingUserController::LoginAsPublicSessionInternal(
1130 const UserContext& user_context) {
1131 // Only one instance of LoginPerformer should exist at a time.
1132 login_performer_.reset(NULL);
1133 login_performer_.reset(new ChromeLoginPerformer(this));
1134 login_performer_->LoginAsPublicSession(user_context);
1135 SendAccessibilityAlert(
1136 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_PUBLIC_ACCOUNT));
1139 void ExistingUserController::PerformPreLoginActions(
1140 const UserContext& user_context) {
1141 // Disable clicking on other windows and status tray.
1142 login_display_->SetUIEnabled(false);
1144 if (last_login_attempt_username_ != user_context.GetUserID()) {
1145 last_login_attempt_username_ = user_context.GetUserID();
1146 num_login_attempts_ = 0;
1148 // Also reset state variables, which are used to determine password change.
1149 offline_failed_ = false;
1150 online_succeeded_for_.clear();
1153 // Guard in cases when we're called twice but login process is still active.
1154 // This might happen when login process is paused till signed settings status
1155 // is verified which results in Login* method called again as a callback.
1156 if (!is_login_in_progress_)
1157 num_login_attempts_++;
1159 is_login_in_progress_ = true;
1161 // Stop the auto-login timer when attempting login.
1162 StopPublicSessionAutoLoginTimer();
1165 void ExistingUserController::PerformLoginFinishedActions(
1166 bool start_public_session_timer) {
1167 is_login_in_progress_ = false;
1169 // Reenable clicking on other windows and status area.
1170 login_display_->SetUIEnabled(true);
1172 if (start_public_session_timer)
1173 StartPublicSessionAutoLoginTimer();
1176 } // namespace chromeos