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"
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/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "base/version.h"
23 #include "chrome/browser/accessibility/accessibility_events.h"
24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/chrome_notification_types.h"
26 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
27 #include "chrome/browser/chromeos/boot_times_loader.h"
28 #include "chrome/browser/chromeos/customization_document.h"
29 #include "chrome/browser/chromeos/first_run/first_run.h"
30 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
31 #include "chrome/browser/chromeos/login/helper.h"
32 #include "chrome/browser/chromeos/login/login_display_host.h"
33 #include "chrome/browser/chromeos/login/login_utils.h"
34 #include "chrome/browser/chromeos/login/startup_utils.h"
35 #include "chrome/browser/chromeos/login/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/profiles/profile_helper.h"
40 #include "chrome/browser/chromeos/settings/cros_settings.h"
41 #include "chrome/browser/google/google_util.h"
42 #include "chrome/browser/prefs/session_startup_pref.h"
43 #include "chrome/common/chrome_switches.h"
44 #include "chrome/common/chrome_version_info.h"
45 #include "chrome/common/pref_names.h"
46 #include "chrome/common/url_constants.h"
47 #include "chromeos/chromeos_switches.h"
48 #include "chromeos/dbus/dbus_thread_manager.h"
49 #include "chromeos/dbus/power_manager_client.h"
50 #include "chromeos/dbus/session_manager_client.h"
51 #include "chromeos/settings/cros_settings_names.h"
52 #include "components/policy/core/common/policy_service.h"
53 #include "content/public/browser/browser_thread.h"
54 #include "content/public/browser/notification_service.h"
55 #include "content/public/browser/notification_types.h"
56 #include "content/public/browser/user_metrics.h"
57 #include "google_apis/gaia/gaia_auth_util.h"
58 #include "google_apis/gaia/google_service_auth_error.h"
59 #include "grit/generated_resources.h"
60 #include "net/http/http_auth_cache.h"
61 #include "net/http/http_network_session.h"
62 #include "net/http/http_transaction_factory.h"
63 #include "net/url_request/url_request_context.h"
64 #include "net/url_request/url_request_context_getter.h"
65 #include "ui/accessibility/ax_enums.h"
66 #include "ui/base/l10n/l10n_util.h"
67 #include "ui/views/widget/widget.h"
73 // URL for account creation.
74 const char kCreateAccountURL[] =
75 "https://accounts.google.com/NewAccount?service=mail";
77 // ChromeVox tutorial URL (used in place of "getting started" url when
78 // accessibility is enabled).
79 const char kChromeVoxTutorialURLPattern[] =
80 "http://www.chromevox.com/tutorial/index.html?lang=%s";
82 // Delay for transferring the auth cache to the system profile.
83 const long int kAuthCacheTransferDelayMs = 2000;
85 // Delay for restarting the ui if safe-mode login has failed.
86 const long int kSafeModeRestartUiDelayMs = 30000;
88 // Makes a call to the policy subsystem to reload the policy when we detect
89 // authentication change.
90 void RefreshPoliciesOnUIThread() {
91 if (g_browser_process->policy_service())
92 g_browser_process->policy_service()->RefreshPolicies(base::Closure());
95 // Copies any authentication details that were entered in the login profile in
96 // the mail profile to make sure all subsystems of Chrome can access the network
97 // with the provided authentication which are possibly for a proxy server.
98 void TransferContextAuthenticationsOnIOThread(
99 net::URLRequestContextGetter* default_profile_context_getter,
100 net::URLRequestContextGetter* browser_process_context_getter) {
101 net::HttpAuthCache* new_cache =
102 browser_process_context_getter->GetURLRequestContext()->
103 http_transaction_factory()->GetSession()->http_auth_cache();
104 net::HttpAuthCache* old_cache =
105 default_profile_context_getter->GetURLRequestContext()->
106 http_transaction_factory()->GetSession()->http_auth_cache();
107 new_cache->UpdateAllFrom(*old_cache);
108 VLOG(1) << "Main request context populated with authentication data.";
109 // Last but not least tell the policy subsystem to refresh now as it might
110 // have been stuck until now too.
111 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
112 base::Bind(&RefreshPoliciesOnUIThread));
118 ExistingUserController* ExistingUserController::current_controller_ = NULL;
120 ////////////////////////////////////////////////////////////////////////////////
121 // ExistingUserController, public:
123 ExistingUserController::ExistingUserController(LoginDisplayHost* host)
124 : login_status_consumer_(NULL),
126 login_display_(host_->CreateLoginDisplay(this)),
127 num_login_attempts_(0),
128 cros_settings_(CrosSettings::Get()),
130 offline_failed_(false),
131 is_login_in_progress_(false),
132 password_changed_(false),
133 do_auto_enrollment_(false),
134 signin_screen_ready_(false),
135 network_state_helper_(new login::NetworkStateHelper) {
136 DCHECK(current_controller_ == NULL);
137 current_controller_ = this;
140 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
141 content::NotificationService::AllSources());
143 chrome::NOTIFICATION_USER_LIST_CHANGED,
144 content::NotificationService::AllSources());
146 chrome::NOTIFICATION_AUTH_SUPPLIED,
147 content::NotificationService::AllSources());
149 chrome::NOTIFICATION_SESSION_STARTED,
150 content::NotificationService::AllSources());
151 show_user_names_subscription_ = cros_settings_->AddSettingsObserver(
152 kAccountsPrefShowUserNamesOnSignIn,
153 base::Bind(&ExistingUserController::DeviceSettingsChanged,
154 base::Unretained(this)));
155 allow_new_user_subscription_ = cros_settings_->AddSettingsObserver(
156 kAccountsPrefAllowNewUser,
157 base::Bind(&ExistingUserController::DeviceSettingsChanged,
158 base::Unretained(this)));
159 allow_guest_subscription_ = cros_settings_->AddSettingsObserver(
160 kAccountsPrefAllowGuest,
161 base::Bind(&ExistingUserController::DeviceSettingsChanged,
162 base::Unretained(this)));
163 users_subscription_ = cros_settings_->AddSettingsObserver(
165 base::Bind(&ExistingUserController::DeviceSettingsChanged,
166 base::Unretained(this)));
167 local_account_auto_login_id_subscription_ =
168 cros_settings_->AddSettingsObserver(
169 kAccountsPrefDeviceLocalAccountAutoLoginId,
170 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
171 base::Unretained(this)));
172 local_account_auto_login_delay_subscription_ =
173 cros_settings_->AddSettingsObserver(
174 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
175 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
176 base::Unretained(this)));
179 void ExistingUserController::Init(const UserList& users) {
180 time_init_ = base::Time::Now();
181 UpdateLoginDisplay(users);
182 ConfigurePublicSessionAutoLogin();
185 void ExistingUserController::UpdateLoginDisplay(const UserList& users) {
186 bool show_users_on_signin;
187 UserList filtered_users;
189 cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn,
190 &show_users_on_signin);
191 if (show_users_on_signin) {
192 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
193 // TODO(xiyuan): Clean user profile whose email is not in whitelist.
194 bool meets_locally_managed_requirements =
195 (*it)->GetType() != User::USER_TYPE_LOCALLY_MANAGED ||
196 UserManager::Get()->AreLocallyManagedUsersAllowed();
197 bool meets_whitelist_requirements =
198 LoginUtils::IsWhitelisted((*it)->email(), NULL) ||
199 (*it)->GetType() != User::USER_TYPE_REGULAR;
200 if (meets_locally_managed_requirements && meets_whitelist_requirements) {
201 filtered_users.push_back(*it);
206 // If no user pods are visible, fallback to single new user pod which will
207 // have guest session link.
209 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &show_guest);
211 cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_users);
212 show_guest &= !filtered_users.empty();
213 bool show_new_user = true;
214 login_display_->set_parent_window(GetNativeWindow());
215 login_display_->Init(filtered_users, show_guest, show_users, show_new_user);
216 host_->OnPreferencesChanged();
219 void ExistingUserController::DoAutoEnrollment() {
220 do_auto_enrollment_ = true;
223 void ExistingUserController::ResumeLogin() {
224 // This means the user signed-in, then auto-enrollment used his credentials
225 // to enroll and succeeded.
226 resume_login_callback_.Run();
227 resume_login_callback_.Reset();
230 ////////////////////////////////////////////////////////////////////////////////
231 // ExistingUserController, content::NotificationObserver implementation:
234 void ExistingUserController::Observe(
236 const content::NotificationSource& source,
237 const content::NotificationDetails& details) {
238 if (type == chrome::NOTIFICATION_SESSION_STARTED) {
239 // Stop listening to any notification once session has started.
240 // Sign in screen objects are marked for deletion with DeleteSoon so
241 // make sure no object would be used after session has started.
242 // http://crbug.com/125276
243 registrar_.RemoveAll();
246 if (type == chrome::NOTIFICATION_USER_LIST_CHANGED) {
247 DeviceSettingsChanged();
250 if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
251 // Possibly the user has authenticated against a proxy server and we might
252 // need the credentials for enrollment and other system requests from the
253 // main |g_browser_process| request context (see bug
254 // http://crosbug.com/24861). So we transfer any credentials to the global
255 // request context here.
256 // The issue we have here is that the NOTIFICATION_AUTH_SUPPLIED is sent
257 // just after the UI is closed but before the new credentials were stored
258 // in the profile. Therefore we have to give it some time to make sure it
259 // has been updated before we copy it.
260 VLOG(1) << "Authentication was entered manually, possibly for proxyauth.";
261 scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter =
262 g_browser_process->system_request_context();
263 Profile* signin_profile = ProfileHelper::GetSigninProfile();
264 scoped_refptr<net::URLRequestContextGetter> signin_profile_context_getter =
265 signin_profile->GetRequestContext();
266 DCHECK(browser_process_context_getter.get());
267 DCHECK(signin_profile_context_getter.get());
268 content::BrowserThread::PostDelayedTask(
269 content::BrowserThread::IO, FROM_HERE,
270 base::Bind(&TransferContextAuthenticationsOnIOThread,
271 signin_profile_context_getter,
272 browser_process_context_getter),
273 base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs));
275 if (type != chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED)
277 login_display_->OnUserImageChanged(*content::Details<User>(details).ptr());
280 ////////////////////////////////////////////////////////////////////////////////
281 // ExistingUserController, private:
283 ExistingUserController::~ExistingUserController() {
284 LoginUtils::Get()->DelegateDeleted(this);
286 if (current_controller_ == this) {
287 current_controller_ = NULL;
289 NOTREACHED() << "More than one controller are alive.";
291 DCHECK(login_display_.get());
294 ////////////////////////////////////////////////////////////////////////////////
295 // ExistingUserController, LoginDisplay::Delegate implementation:
298 void ExistingUserController::CancelPasswordChangedFlow() {
299 login_performer_.reset(NULL);
300 login_display_->SetUIEnabled(true);
301 StartPublicSessionAutoLoginTimer();
304 void ExistingUserController::CreateAccount() {
305 content::RecordAction(base::UserMetricsAction("Login.CreateAccount"));
307 google_util::AppendGoogleLocaleParam(GURL(kCreateAccountURL));
311 void ExistingUserController::CompleteLogin(const UserContext& user_context) {
312 login_display_->set_signin_completed(true);
314 // Complete login event was generated already from UI. Ignore notification.
318 // Stop the auto-login timer when attempting login.
319 StopPublicSessionAutoLoginTimer();
321 // Disable UI while loading user profile.
322 login_display_->SetUIEnabled(false);
324 if (!time_init_.is_null()) {
325 base::TimeDelta delta = base::Time::Now() - time_init_;
326 UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToCompleteLoginTime", delta);
327 time_init_ = base::Time(); // Reset to null.
330 host_->OnCompleteLogin();
332 // Do an ownership check now to avoid auto-enrolling if the device has
333 // already been owned.
334 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
335 base::Bind(&ExistingUserController::CompleteLoginInternal,
336 weak_factory_.GetWeakPtr(),
340 void ExistingUserController::CompleteLoginInternal(
341 const UserContext& user_context,
342 DeviceSettingsService::OwnershipStatus ownership_status) {
343 // Auto-enrollment must have made a decision by now. It's too late to enroll
344 // if the protocol isn't done at this point.
345 if (do_auto_enrollment_ &&
346 ownership_status == DeviceSettingsService::OWNERSHIP_NONE) {
347 VLOG(1) << "Forcing auto-enrollment before completing login";
348 // The only way to get out of the enrollment screen from now on is to either
349 // complete enrollment, or opt-out of it. So this controller shouldn't force
350 // enrollment again if it is reused for another sign-in.
351 do_auto_enrollment_ = false;
352 auto_enrollment_username_ = user_context.username;
353 resume_login_callback_ = base::Bind(
354 &ExistingUserController::PerformLogin,
355 weak_factory_.GetWeakPtr(),
356 user_context, LoginPerformer::AUTH_MODE_EXTENSION);
357 ShowEnrollmentScreen(true, user_context.username);
358 // Enable UI for the enrollment screen. SetUIEnabled(true) will post a
359 // request to show the sign-in screen again when invoked at the sign-in
360 // screen; invoke SetUIEnabled() after navigating to the enrollment screen.
361 login_display_->SetUIEnabled(true);
363 PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION);
367 base::string16 ExistingUserController::GetConnectedNetworkName() {
368 return network_state_helper_->GetCurrentNetworkName();
371 bool ExistingUserController::IsSigninInProgress() const {
372 return is_login_in_progress_;
375 void ExistingUserController::Login(const UserContext& user_context) {
376 if ((user_context.username.empty() || user_context.password.empty()) &&
377 user_context.auth_code.empty())
380 // Stop the auto-login timer when attempting login.
381 StopPublicSessionAutoLoginTimer();
383 // Disable clicking on other windows.
384 login_display_->SetUIEnabled(false);
386 BootTimesLoader::Get()->RecordLoginAttempted();
388 if (last_login_attempt_username_ != user_context.username) {
389 last_login_attempt_username_ = user_context.username;
390 num_login_attempts_ = 0;
391 // Also reset state variables, which are used to determine password change.
392 offline_failed_ = false;
393 online_succeeded_for_.clear();
395 num_login_attempts_++;
396 PerformLogin(user_context, LoginPerformer::AUTH_MODE_INTERNAL);
399 void ExistingUserController::PerformLogin(
400 const UserContext& user_context,
401 LoginPerformer::AuthorizationMode auth_mode) {
402 UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
405 // Disable UI while loading user profile.
406 login_display_->SetUIEnabled(false);
408 // Use the same LoginPerformer for subsequent login as it has state
409 // such as Authenticator instance.
410 if (!login_performer_.get() || num_login_attempts_ <= 1) {
411 LoginPerformer::Delegate* delegate = this;
412 if (login_performer_delegate_.get())
413 delegate = login_performer_delegate_.get();
414 // Only one instance of LoginPerformer should exist at a time.
415 login_performer_.reset(NULL);
416 login_performer_.reset(new LoginPerformer(delegate));
419 is_login_in_progress_ = true;
420 if (gaia::ExtractDomainName(user_context.username) ==
421 UserManager::kLocallyManagedUserDomain) {
422 login_performer_->LoginAsLocallyManagedUser(
423 UserContext(user_context.username,
424 user_context.password,
425 std::string())); // auth_code
427 login_performer_->PerformLogin(user_context, auth_mode);
429 SendAccessibilityAlert(
430 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN));
433 void ExistingUserController::LoginAsRetailModeUser() {
434 // Stop the auto-login timer when attempting login.
435 StopPublicSessionAutoLoginTimer();
437 // Disable clicking on other windows.
438 login_display_->SetUIEnabled(false);
439 // TODO(rkc): Add a CHECK to make sure retail mode logins are allowed once
440 // the enterprise policy wiring is done for retail mode.
442 // Only one instance of LoginPerformer should exist at a time.
443 login_performer_.reset(NULL);
444 login_performer_.reset(new LoginPerformer(this));
445 is_login_in_progress_ = true;
446 login_performer_->LoginRetailMode();
447 SendAccessibilityAlert(
448 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_DEMOUSER));
451 void ExistingUserController::LoginAsGuest() {
452 if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn())
455 // Stop the auto-login timer when attempting login.
456 StopPublicSessionAutoLoginTimer();
458 // Disable clicking on other windows.
459 login_display_->SetUIEnabled(false);
461 CrosSettingsProvider::TrustedStatus status =
462 cros_settings_->PrepareTrustedValues(
463 base::Bind(&ExistingUserController::LoginAsGuest,
464 weak_factory_.GetWeakPtr()));
465 // Must not proceed without signature verification.
466 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
467 login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1,
468 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
469 // Reenable clicking on other windows and status area.
470 login_display_->SetUIEnabled(true);
471 StartPublicSessionAutoLoginTimer();
472 display_email_.clear();
474 } else if (status != CrosSettingsProvider::TRUSTED) {
475 // Value of AllowNewUser setting is still not verified.
476 // Another attempt will be invoked after verification completion.
481 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
483 // Disallowed. The UI should normally not show the guest pod but if for some
484 // reason this has been made available to the user here is the time to tell
486 login_display_->ShowError(IDS_LOGIN_ERROR_WHITELIST, 1,
487 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
488 // Reenable clicking on other windows and status area.
489 login_display_->SetUIEnabled(true);
490 StartPublicSessionAutoLoginTimer();
491 display_email_.clear();
495 // Only one instance of LoginPerformer should exist at a time.
496 login_performer_.reset(NULL);
497 login_performer_.reset(new LoginPerformer(this));
498 is_login_in_progress_ = true;
499 login_performer_->LoginOffTheRecord();
500 SendAccessibilityAlert(
501 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_OFFRECORD));
504 void ExistingUserController::MigrateUserData(const std::string& old_password) {
505 // LoginPerformer instance has state of the user so it should exist.
506 if (login_performer_.get())
507 login_performer_->RecoverEncryptedData(old_password);
510 void ExistingUserController::LoginAsPublicAccount(
511 const std::string& username) {
512 if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn())
515 // Stop the auto-login timer when attempting login.
516 StopPublicSessionAutoLoginTimer();
518 // Disable clicking on other windows.
519 login_display_->SetUIEnabled(false);
521 CrosSettingsProvider::TrustedStatus status =
522 cros_settings_->PrepareTrustedValues(
523 base::Bind(&ExistingUserController::LoginAsPublicAccount,
524 weak_factory_.GetWeakPtr(),
526 // If device policy is permanently unavailable, logging into public accounts
528 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
529 login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1,
530 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
531 // Re-enable clicking on other windows.
532 login_display_->SetUIEnabled(true);
536 // If device policy is not verified yet, this function will be called again
537 // when verification finishes.
538 if (status != CrosSettingsProvider::TRUSTED)
541 // If there is no public account with the given |username|, logging in is not
543 const User* user = UserManager::Get()->FindUser(username);
544 if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT) {
545 // Re-enable clicking on other windows.
546 login_display_->SetUIEnabled(true);
547 StartPublicSessionAutoLoginTimer();
551 // Only one instance of LoginPerformer should exist at a time.
552 login_performer_.reset(NULL);
553 login_performer_.reset(new LoginPerformer(this));
554 is_login_in_progress_ = true;
555 login_performer_->LoginAsPublicAccount(username);
556 SendAccessibilityAlert(
557 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_PUBLIC_ACCOUNT));
560 void ExistingUserController::LoginAsKioskApp(const std::string& app_id,
561 bool diagnostic_mode) {
562 host_->StartAppLaunch(app_id, diagnostic_mode);
565 void ExistingUserController::OnSigninScreenReady() {
566 signin_screen_ready_ = true;
567 StartPublicSessionAutoLoginTimer();
570 void ExistingUserController::OnUserSelected(const std::string& username) {
571 login_performer_.reset(NULL);
572 num_login_attempts_ = 0;
575 void ExistingUserController::OnStartEnterpriseEnrollment() {
576 if (KioskAppManager::Get()->IsConsumerKioskDeviceWithAutoLaunch()) {
577 LOG(WARNING) << "Enterprise enrollment is not available after kiosk auto "
582 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
583 base::Bind(&ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
584 weak_factory_.GetWeakPtr()));
587 void ExistingUserController::OnStartKioskEnableScreen() {
588 KioskAppManager::Get()->GetConsumerKioskAutoLaunchStatus(
590 &ExistingUserController::OnConsumerKioskAutoLaunchCheckCompleted,
591 weak_factory_.GetWeakPtr()));
594 void ExistingUserController::OnStartDeviceReset() {
598 void ExistingUserController::OnStartKioskAutolaunchScreen() {
599 ShowKioskAutolaunchScreen();
602 void ExistingUserController::ResyncUserData() {
603 // LoginPerformer instance has state of the user so it should exist.
604 if (login_performer_.get())
605 login_performer_->ResyncEncryptedData();
608 void ExistingUserController::SetDisplayEmail(const std::string& email) {
609 display_email_ = email;
612 void ExistingUserController::ShowWrongHWIDScreen() {
613 scoped_ptr<base::DictionaryValue> params;
614 host_->StartWizard(WizardController::kWrongHWIDScreenName, params.Pass());
615 login_display_->OnFadeOut();
618 void ExistingUserController::Signout() {
622 void ExistingUserController::OnConsumerKioskAutoLaunchCheckCompleted(
623 KioskAppManager::ConsumerKioskAutoLaunchStatus status) {
624 if (status == KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE)
625 ShowKioskEnableScreen();
628 void ExistingUserController::OnEnrollmentOwnershipCheckCompleted(
629 DeviceSettingsService::OwnershipStatus status) {
630 if (status == DeviceSettingsService::OWNERSHIP_NONE) {
631 ShowEnrollmentScreen(false, std::string());
632 } else if (status == DeviceSettingsService::OWNERSHIP_TAKEN) {
633 // On a device that is already owned we might want to allow users to
634 // re-enroll if the policy information is invalid.
635 CrosSettingsProvider::TrustedStatus trusted_status =
636 CrosSettings::Get()->PrepareTrustedValues(
638 &ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
639 weak_factory_.GetWeakPtr(), status));
640 if (trusted_status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
641 ShowEnrollmentScreen(false, std::string());
644 // OwnershipService::GetStatusAsync is supposed to return either
645 // OWNERSHIP_NONE or OWNERSHIP_TAKEN.
650 void ExistingUserController::ShowEnrollmentScreen(bool is_auto_enrollment,
651 const std::string& user) {
652 scoped_ptr<base::DictionaryValue> params;
653 if (is_auto_enrollment) {
654 params.reset(new base::DictionaryValue());
655 params->SetBoolean("is_auto_enrollment", true);
656 params->SetString("user", user);
658 host_->StartWizard(WizardController::kEnrollmentScreenName,
660 login_display_->OnFadeOut();
663 void ExistingUserController::ShowResetScreen() {
664 scoped_ptr<base::DictionaryValue> params;
665 host_->StartWizard(WizardController::kResetScreenName, params.Pass());
666 login_display_->OnFadeOut();
669 void ExistingUserController::ShowKioskEnableScreen() {
670 scoped_ptr<base::DictionaryValue> params;
671 host_->StartWizard(WizardController::kKioskEnableScreenName, params.Pass());
672 login_display_->OnFadeOut();
675 void ExistingUserController::ShowKioskAutolaunchScreen() {
676 scoped_ptr<base::DictionaryValue> params;
677 host_->StartWizard(WizardController::kKioskAutolaunchScreenName,
679 login_display_->OnFadeOut();
682 void ExistingUserController::ShowTPMError() {
683 login_display_->SetUIEnabled(false);
684 login_display_->ShowErrorScreen(LoginDisplay::TPM_ERROR);
687 ////////////////////////////////////////////////////////////////////////////////
688 // ExistingUserController, LoginPerformer::Delegate implementation:
691 void ExistingUserController::OnLoginFailure(const LoginFailure& failure) {
692 is_login_in_progress_ = false;
693 offline_failed_ = true;
695 guest_mode_url_ = GURL::EmptyGURL();
696 std::string error = failure.GetErrorString();
698 if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
699 HandleLoginFailure(failure)) {
700 login_display_->SetUIEnabled(true);
704 if (failure.reason() == LoginFailure::OWNER_REQUIRED) {
705 ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error);
706 content::BrowserThread::PostDelayedTask(
707 content::BrowserThread::UI, FROM_HERE,
708 base::Bind(&SessionManagerClient::StopSession,
709 base::Unretained(DBusThreadManager::Get()->
710 GetSessionManagerClient())),
711 base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs));
712 } else if (failure.reason() == LoginFailure::TPM_ERROR) {
714 } else if (!online_succeeded_for_.empty()) {
715 ShowGaiaPasswordChanged(online_succeeded_for_);
717 // Check networking after trying to login in case user is
718 // cached locally or the local admin account.
720 UserManager::Get()->IsKnownUser(last_login_attempt_username_);
721 if (!network_state_helper_->IsConnected()) {
723 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
725 ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
727 // TODO(nkostylev): Cleanup rest of ClientLogin related code.
728 if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED &&
729 failure.error().state() ==
730 GoogleServiceAuthError::HOSTED_NOT_ALLOWED) {
731 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED, error);
734 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
736 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
739 // Reenable clicking on other windows and status area.
740 login_display_->SetUIEnabled(true);
741 login_display_->ClearAndEnablePassword();
742 StartPublicSessionAutoLoginTimer();
745 // Reset user flow to default, so that special flow will not affect next
747 UserManager::Get()->ResetUserFlow(last_login_attempt_username_);
749 if (login_status_consumer_)
750 login_status_consumer_->OnLoginFailure(failure);
752 // Clear the recorded displayed email so it won't affect any future attempts.
753 display_email_.clear();
756 void ExistingUserController::OnLoginSuccess(const UserContext& user_context) {
757 is_login_in_progress_ = false;
758 offline_failed_ = false;
759 login_display_->set_signin_completed(true);
761 UserManager::Get()->GetUserFlow(user_context.username)->HandleLoginSuccess(
764 StopPublicSessionAutoLoginTimer();
767 login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION &&
768 user_context.auth_code.empty();
770 // Login performer will be gone so cache this value to use
771 // once profile is loaded.
772 password_changed_ = login_performer_->password_changed();
774 // LoginPerformer instance will delete itself once online auth result is OK.
775 // In case of failure it'll bring up ScreenLock and ask for
776 // correct password/display error message.
777 // Even in case when following online,offline protocol and returning
778 // requests_pending = false, let LoginPerformer delete itself.
779 login_performer_->set_delegate(NULL);
780 ignore_result(login_performer_.release());
782 // Will call OnProfilePrepared() in the end.
783 LoginUtils::Get()->PrepareProfile(user_context,
786 false, // Start session for user.
789 display_email_.clear();
791 // Notify LoginDisplay to allow it provide visual feedback to user.
792 login_display_->OnLoginSuccess(user_context.username);
795 void ExistingUserController::OnProfilePrepared(Profile* profile) {
796 // Reenable clicking on other windows and status area.
797 login_display_->SetUIEnabled(true);
799 UserManager* user_manager = UserManager::Get();
800 if (user_manager->IsCurrentUserNew() &&
801 user_manager->IsLoggedInAsLocallyManagedUser()) {
802 // Supervised users should launch into empty desktop on first run.
803 CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kSilentLaunch);
806 if (user_manager->IsCurrentUserNew() &&
807 !user_manager->GetCurrentUserFlow()->ShouldSkipPostLoginScreens() &&
808 !WizardController::default_controller()->skip_post_login_screens()) {
809 // Don't specify start URLs if the administrator has configured the start
811 if (!SessionStartupPref::TypeIsManaged(profile->GetPrefs()))
812 InitializeStartUrls();
814 // Mark the device as registered., i.e. the second part of OOBE as
816 if (!StartupUtils::IsDeviceRegistered())
817 StartupUtils::MarkDeviceRegistered();
819 if (CommandLine::ForCurrentProcess()->HasSwitch(
820 chromeos::switches::kOobeSkipPostLogin)) {
821 LoginUtils::Get()->DoBrowserLaunch(profile, host_);
824 ActivateWizard(WizardController::kTermsOfServiceScreenName);
827 LoginUtils::Get()->DoBrowserLaunch(profile, host_);
830 // Inform |login_status_consumer_| about successful login.
831 if (login_status_consumer_)
832 login_status_consumer_->OnLoginSuccess(UserContext());
833 login_display_->OnFadeOut();
836 void ExistingUserController::OnOffTheRecordLoginSuccess() {
837 is_login_in_progress_ = false;
838 offline_failed_ = false;
840 // Mark the device as registered., i.e. the second part of OOBE as completed.
841 if (!StartupUtils::IsDeviceRegistered())
842 StartupUtils::MarkDeviceRegistered();
844 LoginUtils::Get()->CompleteOffTheRecordLogin(guest_mode_url_);
846 if (login_status_consumer_)
847 login_status_consumer_->OnOffTheRecordLoginSuccess();
850 void ExistingUserController::OnPasswordChangeDetected() {
851 is_login_in_progress_ = false;
852 offline_failed_ = false;
854 // Must not proceed without signature verification.
855 if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
856 base::Bind(&ExistingUserController::OnPasswordChangeDetected,
857 weak_factory_.GetWeakPtr()))) {
858 // Value of owner email is still not verified.
859 // Another attempt will be invoked after verification completion.
863 if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
864 HandlePasswordChangeDetected()) {
868 // True if user has already made an attempt to enter old password and failed.
869 bool show_invalid_old_password_error =
870 login_performer_->password_changed_callback_count() > 1;
872 // Note: We allow owner using "full sync" mode which will recreate
873 // cryptohome and deal with owner private key being lost. This also allows
874 // us to recover from a lost owner password/homedir.
875 // TODO(gspencer): We shouldn't have to erase stateful data when
876 // doing this. See http://crosbug.com/9115 http://crosbug.com/7792
877 login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error);
879 if (login_status_consumer_)
880 login_status_consumer_->OnPasswordChangeDetected();
882 display_email_.clear();
885 void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
886 is_login_in_progress_ = false;
887 offline_failed_ = false;
889 ShowError(IDS_LOGIN_ERROR_WHITELIST, email);
891 // Reenable clicking on other windows and status area.
892 login_display_->SetUIEnabled(true);
893 login_display_->ShowSigninUI(email);
895 if (login_status_consumer_) {
896 login_status_consumer_->OnLoginFailure(LoginFailure(
897 LoginFailure::WHITELIST_CHECK_FAILED));
900 display_email_.clear();
902 StartPublicSessionAutoLoginTimer();
905 void ExistingUserController::PolicyLoadFailed() {
906 ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, "");
908 // Reenable clicking on other windows and status area.
909 is_login_in_progress_ = false;
910 offline_failed_ = false;
911 login_display_->SetUIEnabled(true);
913 display_email_.clear();
915 // Policy load failure stops login attempts -- restart the timer.
916 StartPublicSessionAutoLoginTimer();
919 void ExistingUserController::OnOnlineChecked(const std::string& username,
921 if (success && last_login_attempt_username_ == username) {
922 online_succeeded_for_ = username;
923 // Wait for login attempt to end, if it hasn't yet.
924 if (offline_failed_ && !is_login_in_progress_)
925 ShowGaiaPasswordChanged(username);
929 ////////////////////////////////////////////////////////////////////////////////
930 // ExistingUserController, private:
932 void ExistingUserController::DeviceSettingsChanged() {
934 // Signed settings or user list changed. Notify views and update them.
935 UpdateLoginDisplay(chromeos::UserManager::Get()->GetUsers());
936 ConfigurePublicSessionAutoLogin();
941 void ExistingUserController::ActivateWizard(const std::string& screen_name) {
942 scoped_ptr<base::DictionaryValue> params;
943 host_->StartWizard(screen_name, params.Pass());
946 void ExistingUserController::ConfigurePublicSessionAutoLogin() {
947 std::string auto_login_account_id;
948 cros_settings_->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
949 &auto_login_account_id);
950 const std::vector<policy::DeviceLocalAccount> device_local_accounts =
951 policy::GetDeviceLocalAccounts(cros_settings_);
953 public_session_auto_login_username_.clear();
954 for (std::vector<policy::DeviceLocalAccount>::const_iterator
955 it = device_local_accounts.begin();
956 it != device_local_accounts.end(); ++it) {
957 if (it->account_id == auto_login_account_id) {
958 public_session_auto_login_username_ = it->user_id;
964 UserManager::Get()->FindUser(public_session_auto_login_username_);
965 if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT)
966 public_session_auto_login_username_.clear();
968 if (!cros_settings_->GetInteger(
969 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
970 &public_session_auto_login_delay_)) {
971 public_session_auto_login_delay_ = 0;
974 if (!public_session_auto_login_username_.empty())
975 StartPublicSessionAutoLoginTimer();
977 StopPublicSessionAutoLoginTimer();
980 void ExistingUserController::ResetPublicSessionAutoLoginTimer() {
981 // Only restart the auto-login timer if it's already running.
982 if (auto_login_timer_ && auto_login_timer_->IsRunning()) {
983 StopPublicSessionAutoLoginTimer();
984 StartPublicSessionAutoLoginTimer();
988 void ExistingUserController::OnPublicSessionAutoLoginTimerFire() {
989 CHECK(signin_screen_ready_ &&
990 !is_login_in_progress_ &&
991 !public_session_auto_login_username_.empty());
992 LoginAsPublicAccount(public_session_auto_login_username_);
995 void ExistingUserController::StopPublicSessionAutoLoginTimer() {
996 if (auto_login_timer_)
997 auto_login_timer_->Stop();
1000 void ExistingUserController::StartPublicSessionAutoLoginTimer() {
1001 if (!signin_screen_ready_ ||
1002 is_login_in_progress_ ||
1003 public_session_auto_login_username_.empty()) {
1007 // Start the auto-login timer.
1008 if (!auto_login_timer_)
1009 auto_login_timer_.reset(new base::OneShotTimer<ExistingUserController>);
1011 auto_login_timer_->Start(
1013 base::TimeDelta::FromMilliseconds(
1014 public_session_auto_login_delay_),
1016 &ExistingUserController::OnPublicSessionAutoLoginTimerFire,
1017 weak_factory_.GetWeakPtr()));
1020 gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
1021 return host_->GetNativeWindow();
1024 void ExistingUserController::InitializeStartUrls() const {
1025 std::vector<std::string> start_urls;
1027 const base::ListValue *urls;
1028 UserManager* user_manager = UserManager::Get();
1029 bool can_show_getstarted_guide =
1030 user_manager->GetActiveUser()->GetType() == User::USER_TYPE_REGULAR &&
1031 !user_manager->IsCurrentUserNonCryptohomeDataEphemeral();
1032 if (user_manager->IsLoggedInAsDemoUser()) {
1033 if (CrosSettings::Get()->GetList(kStartUpUrls, &urls)) {
1034 // The retail mode user will get start URLs from a special policy if it is
1036 for (base::ListValue::const_iterator it = urls->begin();
1037 it != urls->end(); ++it) {
1039 if ((*it)->GetAsString(&url))
1040 start_urls.push_back(url);
1043 can_show_getstarted_guide = false;
1044 // Skip the default first-run behavior for public accounts.
1045 } else if (!user_manager->IsLoggedInAsPublicAccount()) {
1046 if (AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
1047 const char* url = kChromeVoxTutorialURLPattern;
1048 PrefService* prefs = g_browser_process->local_state();
1049 const std::string current_locale =
1050 StringToLowerASCII(prefs->GetString(prefs::kApplicationLocale));
1051 std::string vox_url = base::StringPrintf(url, current_locale.c_str());
1052 start_urls.push_back(vox_url);
1053 can_show_getstarted_guide = false;
1057 // Only show getting started guide for a new user.
1058 const bool should_show_getstarted_guide = user_manager->IsCurrentUserNew();
1060 if (can_show_getstarted_guide && should_show_getstarted_guide) {
1061 // Don't open default Chrome window if we're going to launch the first-run
1062 // app. Because we dont' want the first-run app to be hidden in the
1064 CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kSilentLaunch);
1065 first_run::MaybeLaunchDialogAfterSessionStart();
1067 for (size_t i = 0; i < start_urls.size(); ++i) {
1068 CommandLine::ForCurrentProcess()->AppendArg(start_urls[i]);
1073 void ExistingUserController::ShowError(int error_id,
1074 const std::string& details) {
1075 // TODO(dpolukhin): show detailed error info. |details| string contains
1076 // low level error info that is not localized and even is not user friendly.
1077 // For now just ignore it because error_text contains all required information
1078 // for end users, developers can see details string in Chrome logs.
1080 HelpAppLauncher::HelpTopic help_topic_id;
1081 bool is_offline = !network_state_helper_->IsConnected();
1082 switch (login_performer_->error().state()) {
1083 case GoogleServiceAuthError::CONNECTION_FAILED:
1084 help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE;
1086 case GoogleServiceAuthError::ACCOUNT_DISABLED:
1087 help_topic_id = HelpAppLauncher::HELP_ACCOUNT_DISABLED;
1089 case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
1090 help_topic_id = HelpAppLauncher::HELP_HOSTED_ACCOUNT;
1093 help_topic_id = is_offline ?
1094 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE :
1095 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT;
1099 login_display_->ShowError(error_id, num_login_attempts_, help_topic_id);
1102 void ExistingUserController::ShowGaiaPasswordChanged(
1103 const std::string& username) {
1104 // Invalidate OAuth token, since it can't be correct after password is
1106 UserManager::Get()->SaveUserOAuthStatus(
1108 User::OAUTH2_TOKEN_STATUS_INVALID);
1110 login_display_->SetUIEnabled(true);
1111 login_display_->ShowGaiaPasswordChanged(username);
1114 void ExistingUserController::SendAccessibilityAlert(
1115 const std::string& alert_text) {
1116 AccessibilityAlertInfo event(ProfileHelper::GetSigninProfile(), alert_text);
1117 SendControlAccessibilityNotification(
1118 ui::AX_EVENT_VALUE_CHANGED, &event);
1121 } // namespace chromeos