Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / existing_user_controller.cc
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.
4
5 #include "chrome/browser/chromeos/login/existing_user_controller.h"
6
7 #include <vector>
8
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_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/webui/chromeos/login/l10n_util.h"
47 #include "chrome/common/chrome_switches.h"
48 #include "chrome/common/chrome_version_info.h"
49 #include "chrome/common/url_constants.h"
50 #include "chrome/grit/generated_resources.h"
51 #include "chromeos/chromeos_switches.h"
52 #include "chromeos/dbus/dbus_thread_manager.h"
53 #include "chromeos/dbus/power_manager_client.h"
54 #include "chromeos/dbus/session_manager_client.h"
55 #include "chromeos/login/user_names.h"
56 #include "chromeos/settings/cros_settings_names.h"
57 #include "components/google/core/browser/google_util.h"
58 #include "components/policy/core/common/cloud/cloud_policy_core.h"
59 #include "components/policy/core/common/cloud/cloud_policy_store.h"
60 #include "components/policy/core/common/policy_map.h"
61 #include "components/policy/core/common/policy_service.h"
62 #include "components/policy/core/common/policy_types.h"
63 #include "components/user_manager/user_manager.h"
64 #include "components/user_manager/user_type.h"
65 #include "content/public/browser/browser_thread.h"
66 #include "content/public/browser/notification_service.h"
67 #include "content/public/browser/notification_types.h"
68 #include "content/public/browser/user_metrics.h"
69 #include "google_apis/gaia/gaia_auth_util.h"
70 #include "google_apis/gaia/google_service_auth_error.h"
71 #include "net/http/http_auth_cache.h"
72 #include "net/http/http_network_session.h"
73 #include "net/http/http_transaction_factory.h"
74 #include "net/url_request/url_request_context.h"
75 #include "net/url_request/url_request_context_getter.h"
76 #include "policy/policy_constants.h"
77 #include "ui/accessibility/ax_enums.h"
78 #include "ui/base/l10n/l10n_util.h"
79 #include "ui/views/widget/widget.h"
80
81 namespace chromeos {
82
83 namespace {
84
85 // URL for account creation.
86 const char kCreateAccountURL[] =
87     "https://accounts.google.com/NewAccount?service=mail";
88
89 // Delay for transferring the auth cache to the system profile.
90 const long int kAuthCacheTransferDelayMs = 2000;
91
92 // Delay for restarting the ui if safe-mode login has failed.
93 const long int kSafeModeRestartUiDelayMs = 30000;
94
95 // Makes a call to the policy subsystem to reload the policy when we detect
96 // authentication change.
97 void RefreshPoliciesOnUIThread() {
98   if (g_browser_process->policy_service())
99     g_browser_process->policy_service()->RefreshPolicies(base::Closure());
100 }
101
102 // Copies any authentication details that were entered in the login profile in
103 // the mail profile to make sure all subsystems of Chrome can access the network
104 // with the provided authentication which are possibly for a proxy server.
105 void TransferContextAuthenticationsOnIOThread(
106     net::URLRequestContextGetter* default_profile_context_getter,
107     net::URLRequestContextGetter* browser_process_context_getter) {
108   net::HttpAuthCache* new_cache =
109       browser_process_context_getter->GetURLRequestContext()->
110       http_transaction_factory()->GetSession()->http_auth_cache();
111   net::HttpAuthCache* old_cache =
112       default_profile_context_getter->GetURLRequestContext()->
113       http_transaction_factory()->GetSession()->http_auth_cache();
114   new_cache->UpdateAllFrom(*old_cache);
115   VLOG(1) << "Main request context populated with authentication data.";
116   // Last but not least tell the policy subsystem to refresh now as it might
117   // have been stuck until now too.
118   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
119                                    base::Bind(&RefreshPoliciesOnUIThread));
120 }
121
122 // Record UMA for Easy sign-in outcome.
123 void RecordEasySignInOutcome(const std::string& user_id, bool success) {
124   EasyUnlockService* easy_unlock_service =
125       EasyUnlockService::Get(ProfileHelper::GetSigninProfile());
126   if (!easy_unlock_service)
127     return;
128   easy_unlock_service->RecordEasySignInOutcome(user_id, success);
129 }
130
131 // Record UMA for password login of regular user when Easy sign-in is enabled.
132 void RecordPasswordLoginEvent(const UserContext& user_context) {
133   EasyUnlockService* easy_unlock_service =
134       EasyUnlockService::Get(ProfileHelper::GetSigninProfile());
135   if (user_context.GetUserType() == user_manager::USER_TYPE_REGULAR &&
136       user_context.GetAuthFlow() == UserContext::AUTH_FLOW_OFFLINE &&
137       easy_unlock_service) {
138     easy_unlock_service->RecordPasswordLoginEvent(user_context.GetUserID());
139   }
140 }
141
142 }  // namespace
143
144 // static
145 ExistingUserController* ExistingUserController::current_controller_ = NULL;
146
147 ////////////////////////////////////////////////////////////////////////////////
148 // ExistingUserController, public:
149
150 ExistingUserController::ExistingUserController(LoginDisplayHost* host)
151     : auth_status_consumer_(NULL),
152       last_login_attempt_auth_flow_(UserContext::AUTH_FLOW_OFFLINE),
153       host_(host),
154       login_display_(host_->CreateLoginDisplay(this)),
155       num_login_attempts_(0),
156       cros_settings_(CrosSettings::Get()),
157       offline_failed_(false),
158       is_login_in_progress_(false),
159       password_changed_(false),
160       auth_mode_(LoginPerformer::AUTH_MODE_EXTENSION),
161       do_auto_enrollment_(false),
162       signin_screen_ready_(false),
163       network_state_helper_(new login::NetworkStateHelper),
164       weak_factory_(this) {
165   DCHECK(current_controller_ == NULL);
166   current_controller_ = this;
167
168   registrar_.Add(this,
169                  chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
170                  content::NotificationService::AllSources());
171   registrar_.Add(this,
172                  chrome::NOTIFICATION_USER_LIST_CHANGED,
173                  content::NotificationService::AllSources());
174   registrar_.Add(this,
175                  chrome::NOTIFICATION_AUTH_SUPPLIED,
176                  content::NotificationService::AllSources());
177   registrar_.Add(this,
178                  chrome::NOTIFICATION_SESSION_STARTED,
179                  content::NotificationService::AllSources());
180   show_user_names_subscription_ = cros_settings_->AddSettingsObserver(
181       kAccountsPrefShowUserNamesOnSignIn,
182       base::Bind(&ExistingUserController::DeviceSettingsChanged,
183                  base::Unretained(this)));
184   allow_new_user_subscription_ = cros_settings_->AddSettingsObserver(
185       kAccountsPrefAllowNewUser,
186       base::Bind(&ExistingUserController::DeviceSettingsChanged,
187                  base::Unretained(this)));
188   allow_guest_subscription_ = cros_settings_->AddSettingsObserver(
189       kAccountsPrefAllowGuest,
190       base::Bind(&ExistingUserController::DeviceSettingsChanged,
191                  base::Unretained(this)));
192   allow_supervised_user_subscription_ = cros_settings_->AddSettingsObserver(
193       kAccountsPrefSupervisedUsersEnabled,
194       base::Bind(&ExistingUserController::DeviceSettingsChanged,
195                  base::Unretained(this)));
196   users_subscription_ = cros_settings_->AddSettingsObserver(
197       kAccountsPrefUsers,
198       base::Bind(&ExistingUserController::DeviceSettingsChanged,
199                  base::Unretained(this)));
200   local_account_auto_login_id_subscription_ =
201       cros_settings_->AddSettingsObserver(
202           kAccountsPrefDeviceLocalAccountAutoLoginId,
203           base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
204                      base::Unretained(this)));
205   local_account_auto_login_delay_subscription_ =
206       cros_settings_->AddSettingsObserver(
207           kAccountsPrefDeviceLocalAccountAutoLoginDelay,
208           base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
209                      base::Unretained(this)));
210 }
211
212 void ExistingUserController::Init(const user_manager::UserList& users) {
213   time_init_ = base::Time::Now();
214   UpdateLoginDisplay(users);
215   ConfigurePublicSessionAutoLogin();
216 }
217
218 void ExistingUserController::UpdateLoginDisplay(
219     const user_manager::UserList& users) {
220   bool show_users_on_signin;
221   user_manager::UserList filtered_users;
222
223   cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn,
224                              &show_users_on_signin);
225   for (user_manager::UserList::const_iterator it = users.begin();
226        it != users.end();
227        ++it) {
228     // TODO(xiyuan): Clean user profile whose email is not in whitelist.
229     bool meets_supervised_requirements =
230         (*it)->GetType() != user_manager::USER_TYPE_SUPERVISED ||
231         user_manager::UserManager::Get()->AreSupervisedUsersAllowed();
232     bool meets_whitelist_requirements =
233         LoginUtils::IsWhitelisted((*it)->email(), NULL) ||
234         (*it)->GetType() != user_manager::USER_TYPE_REGULAR;
235
236     // Public session accounts are always shown on login screen.
237     bool meets_show_users_requirements =
238         show_users_on_signin ||
239         (*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
240     if (meets_supervised_requirements &&
241         meets_whitelist_requirements &&
242         meets_show_users_requirements) {
243       filtered_users.push_back(*it);
244     }
245   }
246
247   // If no user pods are visible, fallback to single new user pod which will
248   // have guest session link.
249   bool show_guest;
250   cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &show_guest);
251   show_users_on_signin |= !filtered_users.empty();
252   show_guest &= !filtered_users.empty();
253   bool show_new_user = true;
254   login_display_->set_parent_window(GetNativeWindow());
255   login_display_->Init(
256       filtered_users, show_guest, show_users_on_signin, show_new_user);
257   host_->OnPreferencesChanged();
258 }
259
260 void ExistingUserController::DoAutoEnrollment() {
261   do_auto_enrollment_ = true;
262 }
263
264 void ExistingUserController::ResumeLogin() {
265   // This means the user signed-in, then auto-enrollment used his credentials
266   // to enroll and succeeded.
267   resume_login_callback_.Run();
268   resume_login_callback_.Reset();
269 }
270
271 ////////////////////////////////////////////////////////////////////////////////
272 // ExistingUserController, content::NotificationObserver implementation:
273 //
274
275 void ExistingUserController::Observe(
276     int type,
277     const content::NotificationSource& source,
278     const content::NotificationDetails& details) {
279   if (type == chrome::NOTIFICATION_SESSION_STARTED) {
280     // Stop listening to any notification once session has started.
281     // Sign in screen objects are marked for deletion with DeleteSoon so
282     // make sure no object would be used after session has started.
283     // http://crbug.com/125276
284     registrar_.RemoveAll();
285     return;
286   }
287   if (type == chrome::NOTIFICATION_USER_LIST_CHANGED) {
288     DeviceSettingsChanged();
289     return;
290   }
291   if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
292     // Possibly the user has authenticated against a proxy server and we might
293     // need the credentials for enrollment and other system requests from the
294     // main |g_browser_process| request context (see bug
295     // http://crosbug.com/24861). So we transfer any credentials to the global
296     // request context here.
297     // The issue we have here is that the NOTIFICATION_AUTH_SUPPLIED is sent
298     // just after the UI is closed but before the new credentials were stored
299     // in the profile. Therefore we have to give it some time to make sure it
300     // has been updated before we copy it.
301     VLOG(1) << "Authentication was entered manually, possibly for proxyauth.";
302     scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter =
303         g_browser_process->system_request_context();
304     Profile* signin_profile = ProfileHelper::GetSigninProfile();
305     scoped_refptr<net::URLRequestContextGetter> signin_profile_context_getter =
306         signin_profile->GetRequestContext();
307     DCHECK(browser_process_context_getter.get());
308     DCHECK(signin_profile_context_getter.get());
309     content::BrowserThread::PostDelayedTask(
310         content::BrowserThread::IO, FROM_HERE,
311         base::Bind(&TransferContextAuthenticationsOnIOThread,
312                    signin_profile_context_getter,
313                    browser_process_context_getter),
314         base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs));
315   }
316   if (type != chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED)
317     return;
318   login_display_->OnUserImageChanged(
319       *content::Details<user_manager::User>(details).ptr());
320 }
321
322 ////////////////////////////////////////////////////////////////////////////////
323 // ExistingUserController, private:
324
325 ExistingUserController::~ExistingUserController() {
326   LoginUtils::Get()->DelegateDeleted(this);
327
328   if (current_controller_ == this) {
329     current_controller_ = NULL;
330   } else {
331     NOTREACHED() << "More than one controller are alive.";
332   }
333   DCHECK(login_display_.get());
334 }
335
336 ////////////////////////////////////////////////////////////////////////////////
337 // ExistingUserController, LoginDisplay::Delegate implementation:
338 //
339
340 void ExistingUserController::CancelPasswordChangedFlow() {
341   login_performer_.reset(NULL);
342   PerformLoginFinishedActions(true /* start public session timer */);
343 }
344
345 void ExistingUserController::CreateAccount() {
346   content::RecordAction(base::UserMetricsAction("Login.CreateAccount"));
347   guest_mode_url_ = google_util::AppendGoogleLocaleParam(
348       GURL(kCreateAccountURL), g_browser_process->GetApplicationLocale());
349   Login(UserContext(user_manager::USER_TYPE_GUEST, std::string()),
350         SigninSpecifics());
351 }
352
353 void ExistingUserController::CompleteLogin(const UserContext& user_context) {
354   login_display_->set_signin_completed(true);
355   if (!host_) {
356     // Complete login event was generated already from UI. Ignore notification.
357     return;
358   }
359
360   PerformPreLoginActions(user_context);
361
362   if (!time_init_.is_null()) {
363     base::TimeDelta delta = base::Time::Now() - time_init_;
364     UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToCompleteLoginTime", delta);
365     time_init_ = base::Time();  // Reset to null.
366   }
367
368   host_->OnCompleteLogin();
369
370   // Do an ownership check now to avoid auto-enrolling if the device has
371   // already been owned.
372   DeviceSettingsService::Get()->GetOwnershipStatusAsync(
373       base::Bind(&ExistingUserController::CompleteLoginInternal,
374                  weak_factory_.GetWeakPtr(),
375                  user_context));
376 }
377
378 void ExistingUserController::CompleteLoginInternal(
379     const UserContext& user_context,
380     DeviceSettingsService::OwnershipStatus ownership_status) {
381   // Auto-enrollment must have made a decision by now. It's too late to enroll
382   // if the protocol isn't done at this point.
383   if (do_auto_enrollment_ &&
384       ownership_status == DeviceSettingsService::OWNERSHIP_NONE) {
385     VLOG(1) << "Forcing auto-enrollment before completing login";
386     // The only way to get out of the enrollment screen from now on is to either
387     // complete enrollment, or opt-out of it. So this controller shouldn't force
388     // enrollment again if it is reused for another sign-in.
389     do_auto_enrollment_ = false;
390     auto_enrollment_username_ = user_context.GetUserID();
391     resume_login_callback_ = base::Bind(
392         &ExistingUserController::PerformLogin,
393         weak_factory_.GetWeakPtr(),
394         user_context, LoginPerformer::AUTH_MODE_EXTENSION);
395     ShowEnrollmentScreen(true, user_context.GetUserID());
396     // Enable UI for the enrollment screen. SetUIEnabled(true) will post a
397     // request to show the sign-in screen again when invoked at the sign-in
398     // screen; invoke SetUIEnabled() after navigating to the enrollment screen.
399     PerformLoginFinishedActions(false /* don't start public session timer */);
400   } else {
401     PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION);
402   }
403 }
404
405 base::string16 ExistingUserController::GetConnectedNetworkName() {
406   return network_state_helper_->GetCurrentNetworkName();
407 }
408
409 bool ExistingUserController::IsSigninInProgress() const {
410   return is_login_in_progress_;
411 }
412
413 void ExistingUserController::Login(const UserContext& user_context,
414                                    const SigninSpecifics& specifics) {
415   // Disable clicking on other windows and status tray.
416   login_display_->SetUIEnabled(false);
417
418   // Stop the auto-login timer.
419   StopPublicSessionAutoLoginTimer();
420
421   // Wait for the |cros_settings_| to become either trusted or permanently
422   // untrusted.
423   const CrosSettingsProvider::TrustedStatus status =
424       cros_settings_->PrepareTrustedValues(base::Bind(
425           &ExistingUserController::Login,
426           weak_factory_.GetWeakPtr(),
427           user_context,
428           specifics));
429   if (status == CrosSettingsProvider::TEMPORARILY_UNTRUSTED)
430     return;
431
432   if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
433     // If the |cros_settings_| are permanently untrusted, show an error message
434     // and refuse to log in.
435     login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST,
436                               1,
437                               HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
438
439     // Re-enable clicking on other windows and the status area. Do not start the
440     // auto-login timer though. Without trusted |cros_settings_|, no auto-login
441     // can succeed.
442     login_display_->SetUIEnabled(true);
443     return;
444   }
445
446   bool device_disabled = false;
447   cros_settings_->GetBoolean(kDeviceDisabled, &device_disabled);
448   if (device_disabled && system::DeviceDisablingManager::
449                              HonorDeviceDisablingDuringNormalOperation()) {
450     // If the device is disabled, bail out. A device disabled screen will be
451     // shown by the DeviceDisablingManager.
452
453     // Re-enable clicking on other windows and the status area. Do not start the
454     // auto-login timer though. On a disabled device, no auto-login can succeed.
455     login_display_->SetUIEnabled(true);
456     return;
457   }
458
459   if (is_login_in_progress_) {
460     // If there is another login in progress, bail out. Do not re-enable
461     // clicking on other windows and the status area. Do not start the
462     // auto-login timer.
463     return;
464   }
465
466   if (user_context.GetUserType() != user_manager::USER_TYPE_REGULAR &&
467       user_manager::UserManager::Get()->IsUserLoggedIn()) {
468     // Multi-login is only allowed for regular users. If we are attempting to
469     // do multi-login as another type of user somehow, bail out. Do not
470     // re-enable clicking on other windows and the status area. Do not start the
471     // auto-login timer.
472     return;
473   }
474
475   if (user_context.GetUserType() == user_manager::USER_TYPE_GUEST) {
476     if (!specifics.guest_mode_url.empty()) {
477       guest_mode_url_ = GURL(specifics.guest_mode_url);
478       if (specifics.guest_mode_url_append_locale)
479         guest_mode_url_ = google_util::AppendGoogleLocaleParam(
480             guest_mode_url_, g_browser_process->GetApplicationLocale());
481     }
482     LoginAsGuest();
483     return;
484   }
485
486   if (user_context.GetUserType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
487     LoginAsPublicSession(user_context);
488     return;
489   }
490
491   if (user_context.GetUserType() == user_manager::USER_TYPE_RETAIL_MODE) {
492     LoginAsRetailModeUser();
493     return;
494   }
495
496   if (user_context.GetUserType() == user_manager::USER_TYPE_KIOSK_APP) {
497     LoginAsKioskApp(user_context.GetUserID(), specifics.kiosk_diagnostic_mode);
498     return;
499   }
500
501   // Regular user or supervised user login.
502
503   if (!user_context.HasCredentials()) {
504     // If credentials are missing, refuse to log in.
505
506     // Reenable clicking on other windows and status area.
507     login_display_->SetUIEnabled(true);
508     // Restart the auto-login timer.
509     StartPublicSessionAutoLoginTimer();
510   }
511
512   PerformPreLoginActions(user_context);
513   PerformLogin(user_context, LoginPerformer::AUTH_MODE_INTERNAL);
514 }
515
516 void ExistingUserController::PerformLogin(
517     const UserContext& user_context,
518     LoginPerformer::AuthorizationMode auth_mode) {
519   // TODO(antrim): remove this output once crash reason is found.
520   LOG(ERROR) << "Setting flow from PerformLogin";
521   ChromeUserManager::Get()
522       ->GetUserFlow(user_context.GetUserID())
523       ->SetHost(host_);
524
525   BootTimesLoader::Get()->RecordLoginAttempted();
526
527   last_login_attempt_auth_flow_ = user_context.GetAuthFlow();
528
529   // Use the same LoginPerformer for subsequent login as it has state
530   // such as Authenticator instance.
531   if (!login_performer_.get() || num_login_attempts_ <= 1) {
532     // Only one instance of LoginPerformer should exist at a time.
533     login_performer_.reset(NULL);
534     login_performer_.reset(new ChromeLoginPerformer(this));
535   }
536
537   if (gaia::ExtractDomainName(user_context.GetUserID()) ==
538       chromeos::login::kSupervisedUserDomain) {
539     login_performer_->LoginAsSupervisedUser(user_context);
540   } else {
541     login_performer_->PerformLogin(user_context, auth_mode);
542     RecordPasswordLoginEvent(user_context);
543   }
544   SendAccessibilityAlert(
545       l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN));
546 }
547
548 void ExistingUserController::MigrateUserData(const std::string& old_password) {
549   // LoginPerformer instance has state of the user so it should exist.
550   if (login_performer_.get())
551     login_performer_->RecoverEncryptedData(old_password);
552 }
553
554
555 void ExistingUserController::OnSigninScreenReady() {
556   signin_screen_ready_ = true;
557   StartPublicSessionAutoLoginTimer();
558 }
559
560 void ExistingUserController::OnStartEnterpriseEnrollment() {
561   if (KioskAppManager::Get()->IsConsumerKioskDeviceWithAutoLaunch()) {
562     LOG(WARNING) << "Enterprise enrollment is not available after kiosk auto "
563                     "launch is set.";
564     return;
565   }
566
567   DeviceSettingsService::Get()->GetOwnershipStatusAsync(
568       base::Bind(&ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
569                  weak_factory_.GetWeakPtr()));
570 }
571
572 void ExistingUserController::OnStartKioskEnableScreen() {
573   KioskAppManager::Get()->GetConsumerKioskAutoLaunchStatus(
574       base::Bind(
575           &ExistingUserController::OnConsumerKioskAutoLaunchCheckCompleted,
576           weak_factory_.GetWeakPtr()));
577 }
578
579 void ExistingUserController::OnStartKioskAutolaunchScreen() {
580   ShowKioskAutolaunchScreen();
581 }
582
583 void ExistingUserController::ResyncUserData() {
584   // LoginPerformer instance has state of the user so it should exist.
585   if (login_performer_.get())
586     login_performer_->ResyncEncryptedData();
587 }
588
589 void ExistingUserController::SetDisplayEmail(const std::string& email) {
590   display_email_ = email;
591 }
592
593 void ExistingUserController::ShowWrongHWIDScreen() {
594   scoped_ptr<base::DictionaryValue> params;
595   host_->StartWizard(WizardController::kWrongHWIDScreenName, params.Pass());
596 }
597
598 void ExistingUserController::Signout() {
599   NOTREACHED();
600 }
601
602 void ExistingUserController::OnConsumerKioskAutoLaunchCheckCompleted(
603     KioskAppManager::ConsumerKioskAutoLaunchStatus status) {
604   if (status == KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE)
605     ShowKioskEnableScreen();
606 }
607
608 void ExistingUserController::OnEnrollmentOwnershipCheckCompleted(
609     DeviceSettingsService::OwnershipStatus status) {
610   if (status == DeviceSettingsService::OWNERSHIP_NONE) {
611     ShowEnrollmentScreen(false, std::string());
612   } else if (status == DeviceSettingsService::OWNERSHIP_TAKEN) {
613     // On a device that is already owned we might want to allow users to
614     // re-enroll if the policy information is invalid.
615     CrosSettingsProvider::TrustedStatus trusted_status =
616         CrosSettings::Get()->PrepareTrustedValues(
617             base::Bind(
618                 &ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
619                 weak_factory_.GetWeakPtr(), status));
620     if (trusted_status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
621       ShowEnrollmentScreen(false, std::string());
622     }
623   } else {
624     // OwnershipService::GetStatusAsync is supposed to return either
625     // OWNERSHIP_NONE or OWNERSHIP_TAKEN.
626     NOTREACHED();
627   }
628 }
629
630 void ExistingUserController::ShowEnrollmentScreen(bool is_auto_enrollment,
631                                                   const std::string& user) {
632   scoped_ptr<base::DictionaryValue> params;
633   if (is_auto_enrollment) {
634     params.reset(new base::DictionaryValue());
635     params->SetBoolean("is_auto_enrollment", true);
636     params->SetString("user", user);
637   }
638   host_->StartWizard(WizardController::kEnrollmentScreenName,
639                      params.Pass());
640 }
641
642 void ExistingUserController::ShowResetScreen() {
643   scoped_ptr<base::DictionaryValue> params;
644   host_->StartWizard(WizardController::kResetScreenName, params.Pass());
645 }
646
647 void ExistingUserController::ShowKioskEnableScreen() {
648   scoped_ptr<base::DictionaryValue> params;
649   host_->StartWizard(WizardController::kKioskEnableScreenName, params.Pass());
650 }
651
652 void ExistingUserController::ShowKioskAutolaunchScreen() {
653   scoped_ptr<base::DictionaryValue> params;
654   host_->StartWizard(WizardController::kKioskAutolaunchScreenName,
655                      params.Pass());
656 }
657
658 void ExistingUserController::ShowTPMError() {
659   login_display_->SetUIEnabled(false);
660   login_display_->ShowErrorScreen(LoginDisplay::TPM_ERROR);
661 }
662
663 ////////////////////////////////////////////////////////////////////////////////
664 // ExistingUserController, LoginPerformer::Delegate implementation:
665 //
666
667 void ExistingUserController::OnAuthFailure(const AuthFailure& failure) {
668   offline_failed_ = true;
669   guest_mode_url_ = GURL::EmptyGURL();
670   std::string error = failure.GetErrorString();
671
672   PerformLoginFinishedActions(false /* don't start public session timer */);
673
674   // TODO(xiyuan): Move into EasyUnlockUserLoginFlow.
675   if (last_login_attempt_auth_flow_ == UserContext::AUTH_FLOW_EASY_UNLOCK)
676     RecordEasySignInOutcome(last_login_attempt_username_, false);
677
678   if (ChromeUserManager::Get()
679           ->GetUserFlow(last_login_attempt_username_)
680           ->HandleLoginFailure(failure)) {
681     return;
682   }
683
684   if (failure.reason() == AuthFailure::OWNER_REQUIRED) {
685     ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error);
686     content::BrowserThread::PostDelayedTask(
687         content::BrowserThread::UI, FROM_HERE,
688         base::Bind(&SessionManagerClient::StopSession,
689                    base::Unretained(DBusThreadManager::Get()->
690                                     GetSessionManagerClient())),
691         base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs));
692   } else if (failure.reason() == AuthFailure::TPM_ERROR) {
693     ShowTPMError();
694   } else if (!online_succeeded_for_.empty()) {
695     ShowGaiaPasswordChanged(online_succeeded_for_);
696   } else {
697     // Check networking after trying to login in case user is
698     // cached locally or the local admin account.
699     bool is_known_user = user_manager::UserManager::Get()->IsKnownUser(
700         last_login_attempt_username_);
701     if (!network_state_helper_->IsConnected()) {
702       if (is_known_user)
703         ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
704       else
705         ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
706     } else {
707       // TODO(nkostylev): Cleanup rest of ClientLogin related code.
708       if (failure.reason() == AuthFailure::NETWORK_AUTH_FAILED &&
709           failure.error().state() ==
710               GoogleServiceAuthError::HOSTED_NOT_ALLOWED) {
711         ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED, error);
712       } else {
713         if (!is_known_user)
714           ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
715         else
716           ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
717       }
718     }
719     login_display_->ClearAndEnablePassword();
720     StartPublicSessionAutoLoginTimer();
721   }
722
723   // Reset user flow to default, so that special flow will not affect next
724   // attempt.
725   ChromeUserManager::Get()->ResetUserFlow(last_login_attempt_username_);
726
727   if (auth_status_consumer_)
728     auth_status_consumer_->OnAuthFailure(failure);
729
730   // Clear the recorded displayed email so it won't affect any future attempts.
731   display_email_.clear();
732 }
733
734 void ExistingUserController::OnAuthSuccess(const UserContext& user_context) {
735   is_login_in_progress_ = false;
736   offline_failed_ = false;
737   login_display_->set_signin_completed(true);
738
739   // Login performer will be gone so cache this value to use
740   // once profile is loaded.
741   password_changed_ = login_performer_->password_changed();
742   auth_mode_ = login_performer_->auth_mode();
743
744   ChromeUserManager::Get()
745       ->GetUserFlow(user_context.GetUserID())
746       ->HandleLoginSuccess(user_context);
747
748   // TODO(xiyuan): Move into EasyUnlockUserLoginFlow.
749   if (last_login_attempt_auth_flow_ == UserContext::AUTH_FLOW_EASY_UNLOCK) {
750     DCHECK_EQ(last_login_attempt_username_, user_context.GetUserID());
751     DCHECK_EQ(last_login_attempt_auth_flow_, user_context.GetAuthFlow());
752     RecordEasySignInOutcome(last_login_attempt_username_, true);
753   }
754
755   StopPublicSessionAutoLoginTimer();
756
757   const bool has_auth_cookies =
758       login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION &&
759       user_context.GetAuthCode().empty();
760
761   // LoginPerformer instance will delete itself once online auth result is OK.
762   // In case of failure it'll bring up ScreenLock and ask for
763   // correct password/display error message.
764   // Even in case when following online,offline protocol and returning
765   // requests_pending = false, let LoginPerformer delete itself.
766   login_performer_->set_delegate(NULL);
767   ignore_result(login_performer_.release());
768
769   // Will call OnProfilePrepared() in the end.
770   LoginUtils::Get()->PrepareProfile(user_context,
771                                     has_auth_cookies,
772                                     false,          // Start session for user.
773                                     this);
774
775   // Update user's displayed email.
776   if (!display_email_.empty()) {
777     user_manager::UserManager::Get()->SaveUserDisplayEmail(
778         user_context.GetUserID(), display_email_);
779     display_email_.clear();
780   }
781 }
782
783 void ExistingUserController::OnProfilePrepared(Profile* profile,
784                                                bool browser_launched) {
785   // Reenable clicking on other windows and status area.
786   login_display_->SetUIEnabled(true);
787
788   if (browser_launched)
789     host_ = NULL;
790
791   // Inform |auth_status_consumer_| about successful login.
792   // TODO(nkostylev): Pass UserContext back crbug.com/424550
793   if (auth_status_consumer_) {
794     auth_status_consumer_->
795         OnAuthSuccess(UserContext(last_login_attempt_username_));
796   }
797 }
798
799 void ExistingUserController::OnOffTheRecordAuthSuccess() {
800   is_login_in_progress_ = false;
801   offline_failed_ = false;
802
803   // Mark the device as registered., i.e. the second part of OOBE as completed.
804   if (!StartupUtils::IsDeviceRegistered())
805     StartupUtils::MarkDeviceRegistered(base::Closure());
806
807   UserSessionManager::GetInstance()->CompleteGuestSessionLogin(guest_mode_url_);
808
809   if (auth_status_consumer_)
810     auth_status_consumer_->OnOffTheRecordAuthSuccess();
811 }
812
813 void ExistingUserController::OnPasswordChangeDetected() {
814   is_login_in_progress_ = false;
815   offline_failed_ = false;
816
817   // Must not proceed without signature verification.
818   if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
819       base::Bind(&ExistingUserController::OnPasswordChangeDetected,
820                  weak_factory_.GetWeakPtr()))) {
821     // Value of owner email is still not verified.
822     // Another attempt will be invoked after verification completion.
823     return;
824   }
825
826   if (ChromeUserManager::Get()
827           ->GetUserFlow(last_login_attempt_username_)
828           ->HandlePasswordChangeDetected()) {
829     return;
830   }
831
832   // True if user has already made an attempt to enter old password and failed.
833   bool show_invalid_old_password_error =
834       login_performer_->password_changed_callback_count() > 1;
835
836   // Note: We allow owner using "full sync" mode which will recreate
837   // cryptohome and deal with owner private key being lost. This also allows
838   // us to recover from a lost owner password/homedir.
839   // TODO(gspencer): We shouldn't have to erase stateful data when
840   // doing this.  See http://crosbug.com/9115 http://crosbug.com/7792
841   login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error);
842
843   if (auth_status_consumer_)
844     auth_status_consumer_->OnPasswordChangeDetected();
845
846   display_email_.clear();
847 }
848
849 void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
850   PerformLoginFinishedActions(true /* start public session timer */);
851   offline_failed_ = false;
852
853   ShowError(IDS_LOGIN_ERROR_WHITELIST, email);
854
855   login_display_->ShowSigninUI(email);
856
857   if (auth_status_consumer_) {
858     auth_status_consumer_->OnAuthFailure(
859         AuthFailure(AuthFailure::WHITELIST_CHECK_FAILED));
860   }
861
862   display_email_.clear();
863 }
864
865 void ExistingUserController::PolicyLoadFailed() {
866   ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, "");
867
868   PerformLoginFinishedActions(false /* don't start public session timer */);
869   offline_failed_ = false;
870   display_email_.clear();
871 }
872
873 void ExistingUserController::OnOnlineChecked(const std::string& username,
874                                              bool success) {
875   if (success && last_login_attempt_username_ == username) {
876     online_succeeded_for_ = username;
877     // Wait for login attempt to end, if it hasn't yet.
878     if (offline_failed_ && !is_login_in_progress_)
879       ShowGaiaPasswordChanged(username);
880   }
881 }
882
883 ////////////////////////////////////////////////////////////////////////////////
884 // ExistingUserController, private:
885
886 void ExistingUserController::DeviceSettingsChanged() {
887   if (host_ != NULL) {
888     // Signed settings or user list changed. Notify views and update them.
889     UpdateLoginDisplay(user_manager::UserManager::Get()->GetUsers());
890     ConfigurePublicSessionAutoLogin();
891     return;
892   }
893 }
894
895 LoginPerformer::AuthorizationMode ExistingUserController::auth_mode() const {
896   if (login_performer_)
897     return login_performer_->auth_mode();
898
899   return auth_mode_;
900 }
901
902 bool ExistingUserController::password_changed() const {
903   if (login_performer_)
904     return login_performer_->password_changed();
905
906   return password_changed_;
907 }
908
909 void ExistingUserController::LoginAsRetailModeUser() {
910   PerformPreLoginActions(UserContext(user_manager::USER_TYPE_RETAIL_MODE,
911                                      chromeos::login::kRetailModeUserName));
912
913   // TODO(rkc): Add a CHECK to make sure retail mode logins are allowed once
914   // the enterprise policy wiring is done for retail mode.
915
916   // Only one instance of LoginPerformer should exist at a time.
917   login_performer_.reset(NULL);
918   login_performer_.reset(new ChromeLoginPerformer(this));
919   login_performer_->LoginRetailMode();
920   SendAccessibilityAlert(
921       l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_DEMOUSER));
922 }
923
924 void ExistingUserController::LoginAsGuest() {
925   PerformPreLoginActions(UserContext(user_manager::USER_TYPE_GUEST,
926                                      chromeos::login::kGuestUserName));
927
928   bool allow_guest;
929   cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
930   if (!allow_guest) {
931     // Disallowed. The UI should normally not show the guest pod but if for some
932     // reason this has been made available to the user here is the time to tell
933     // this nicely.
934     login_display_->ShowError(IDS_LOGIN_ERROR_WHITELIST, 1,
935                               HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
936     PerformLoginFinishedActions(true /* start public session timer */);
937     display_email_.clear();
938     return;
939   }
940
941   // Only one instance of LoginPerformer should exist at a time.
942   login_performer_.reset(NULL);
943   login_performer_.reset(new ChromeLoginPerformer(this));
944   login_performer_->LoginOffTheRecord();
945   SendAccessibilityAlert(
946       l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_OFFRECORD));
947 }
948
949 void ExistingUserController::LoginAsPublicSession(
950     const UserContext& user_context) {
951   PerformPreLoginActions(user_context);
952
953   // If there is no public account with the given user ID, logging in is not
954   // possible.
955   const user_manager::User* user =
956       user_manager::UserManager::Get()->FindUser(user_context.GetUserID());
957   if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
958     PerformLoginFinishedActions(true /* start public session timer */);
959     return;
960   }
961
962   UserContext new_user_context = user_context;
963   std::string locale = user_context.GetPublicSessionLocale();
964   if (locale.empty()) {
965     // When performing auto-login, no locale is chosen by the user. Check
966     // whether a list of recommended locales was set by policy. If so, use its
967     // first entry. Otherwise, |locale| will remain blank, indicating that the
968     // public session should use the current UI locale.
969     const policy::PolicyMap::Entry* entry = g_browser_process->platform_part()->
970         browser_policy_connector_chromeos()->
971             GetDeviceLocalAccountPolicyService()->
972                 GetBrokerForUser(user_context.GetUserID())->core()->store()->
973                     policy_map().Get(policy::key::kSessionLocales);
974     base::ListValue const* list = NULL;
975     if (entry &&
976         entry->level == policy::POLICY_LEVEL_RECOMMENDED &&
977         entry->value &&
978         entry->value->GetAsList(&list)) {
979       if (list->GetString(0, &locale))
980         new_user_context.SetPublicSessionLocale(locale);
981     }
982   }
983
984   if (!locale.empty() &&
985       new_user_context.GetPublicSessionInputMethod().empty()) {
986     // When |locale| is set, a suitable keyboard layout should be chosen. In
987     // most cases, this will already be the case because the UI shows a list of
988     // keyboard layouts suitable for the |locale| and ensures that one of them
989     // us selected. However, it is still possible that |locale| is set but no
990     // keyboard layout was chosen:
991     // * The list of keyboard layouts is updated asynchronously. If the user
992     //   enters the public session before the list of keyboard layouts for the
993     //   |locale| has been retrieved, the UI will indicate that no keyboard
994     //   layout was chosen.
995     // * During auto-login, the |locale| is set in this method and a suitable
996     //   keyboard layout must be chosen next.
997     //
998     // The list of suitable keyboard layouts is constructed asynchronously. Once
999     // it has been retrieved, |SetPublicSessionKeyboardLayoutAndLogin| will
1000     // select the first layout from the list and continue login.
1001     GetKeyboardLayoutsForLocale(
1002         base::Bind(
1003             &ExistingUserController::SetPublicSessionKeyboardLayoutAndLogin,
1004             weak_factory_.GetWeakPtr(),
1005             new_user_context),
1006         locale);
1007     return;
1008   }
1009
1010   // The user chose a locale and a suitable keyboard layout or left both unset.
1011   // Login can continue immediately.
1012   LoginAsPublicSessionInternal(new_user_context);
1013 }
1014
1015 void ExistingUserController::LoginAsKioskApp(const std::string& app_id,
1016                                              bool diagnostic_mode) {
1017   host_->StartAppLaunch(app_id, diagnostic_mode);
1018 }
1019
1020 void ExistingUserController::ConfigurePublicSessionAutoLogin() {
1021   std::string auto_login_account_id;
1022   cros_settings_->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
1023                             &auto_login_account_id);
1024   const std::vector<policy::DeviceLocalAccount> device_local_accounts =
1025       policy::GetDeviceLocalAccounts(cros_settings_);
1026
1027   public_session_auto_login_username_.clear();
1028   for (std::vector<policy::DeviceLocalAccount>::const_iterator
1029            it = device_local_accounts.begin();
1030        it != device_local_accounts.end(); ++it) {
1031     if (it->account_id == auto_login_account_id) {
1032       public_session_auto_login_username_ = it->user_id;
1033       break;
1034     }
1035   }
1036
1037   const user_manager::User* user = user_manager::UserManager::Get()->FindUser(
1038       public_session_auto_login_username_);
1039   if (!user || user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT)
1040     public_session_auto_login_username_.clear();
1041
1042   if (!cros_settings_->GetInteger(
1043           kAccountsPrefDeviceLocalAccountAutoLoginDelay,
1044           &public_session_auto_login_delay_)) {
1045     public_session_auto_login_delay_ = 0;
1046   }
1047
1048   if (!public_session_auto_login_username_.empty())
1049     StartPublicSessionAutoLoginTimer();
1050   else
1051     StopPublicSessionAutoLoginTimer();
1052 }
1053
1054 void ExistingUserController::ResetPublicSessionAutoLoginTimer() {
1055   // Only restart the auto-login timer if it's already running.
1056   if (auto_login_timer_ && auto_login_timer_->IsRunning()) {
1057     StopPublicSessionAutoLoginTimer();
1058     StartPublicSessionAutoLoginTimer();
1059   }
1060 }
1061
1062 void ExistingUserController::OnPublicSessionAutoLoginTimerFire() {
1063   CHECK(signin_screen_ready_ && !public_session_auto_login_username_.empty());
1064   Login(UserContext(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
1065                     public_session_auto_login_username_),
1066         SigninSpecifics());
1067 }
1068
1069 void ExistingUserController::StopPublicSessionAutoLoginTimer() {
1070   if (auto_login_timer_)
1071     auto_login_timer_->Stop();
1072 }
1073
1074 void ExistingUserController::StartPublicSessionAutoLoginTimer() {
1075   if (!signin_screen_ready_ ||
1076       is_login_in_progress_ ||
1077       public_session_auto_login_username_.empty()) {
1078     return;
1079   }
1080
1081   // Start the auto-login timer.
1082   if (!auto_login_timer_)
1083     auto_login_timer_.reset(new base::OneShotTimer<ExistingUserController>);
1084
1085   auto_login_timer_->Start(
1086       FROM_HERE,
1087       base::TimeDelta::FromMilliseconds(
1088           public_session_auto_login_delay_),
1089       base::Bind(
1090           &ExistingUserController::OnPublicSessionAutoLoginTimerFire,
1091           weak_factory_.GetWeakPtr()));
1092 }
1093
1094 gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
1095   return host_->GetNativeWindow();
1096 }
1097
1098 void ExistingUserController::ShowError(int error_id,
1099                                        const std::string& details) {
1100   // TODO(dpolukhin): show detailed error info. |details| string contains
1101   // low level error info that is not localized and even is not user friendly.
1102   // For now just ignore it because error_text contains all required information
1103   // for end users, developers can see details string in Chrome logs.
1104   VLOG(1) << details;
1105   HelpAppLauncher::HelpTopic help_topic_id;
1106   bool is_offline = !network_state_helper_->IsConnected();
1107   switch (login_performer_->error().state()) {
1108     case GoogleServiceAuthError::CONNECTION_FAILED:
1109       help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE;
1110       break;
1111     case GoogleServiceAuthError::ACCOUNT_DISABLED:
1112       help_topic_id = HelpAppLauncher::HELP_ACCOUNT_DISABLED;
1113       break;
1114     case GoogleServiceAuthError::HOSTED_NOT_ALLOWED:
1115       help_topic_id = HelpAppLauncher::HELP_HOSTED_ACCOUNT;
1116       break;
1117     default:
1118       help_topic_id = is_offline ?
1119           HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE :
1120           HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT;
1121       break;
1122   }
1123
1124   if (error_id == IDS_LOGIN_ERROR_AUTHENTICATING) {
1125     if (num_login_attempts_ > 1) {
1126       const user_manager::User* user =
1127           user_manager::UserManager::Get()->FindUser(
1128               last_login_attempt_username_);
1129       if (user && (user->GetType() == user_manager::USER_TYPE_SUPERVISED))
1130         error_id = IDS_LOGIN_ERROR_AUTHENTICATING_2ND_TIME_SUPERVISED;
1131     }
1132   }
1133
1134   login_display_->ShowError(error_id, num_login_attempts_, help_topic_id);
1135 }
1136
1137 void ExistingUserController::ShowGaiaPasswordChanged(
1138     const std::string& username) {
1139   // Invalidate OAuth token, since it can't be correct after password is
1140   // changed.
1141   user_manager::UserManager::Get()->SaveUserOAuthStatus(
1142       username, user_manager::User::OAUTH2_TOKEN_STATUS_INVALID);
1143
1144   login_display_->SetUIEnabled(true);
1145   login_display_->ShowGaiaPasswordChanged(username);
1146 }
1147
1148 void ExistingUserController::SendAccessibilityAlert(
1149     const std::string& alert_text) {
1150   AccessibilityAlertInfo event(ProfileHelper::GetSigninProfile(), alert_text);
1151   SendControlAccessibilityNotification(
1152       ui::AX_EVENT_VALUE_CHANGED, &event);
1153 }
1154
1155 void ExistingUserController::SetPublicSessionKeyboardLayoutAndLogin(
1156     const UserContext& user_context,
1157     scoped_ptr<base::ListValue> keyboard_layouts) {
1158   UserContext new_user_context = user_context;
1159   std::string keyboard_layout;
1160   for (size_t i = 0; i < keyboard_layouts->GetSize(); ++i) {
1161     base::DictionaryValue* entry = NULL;
1162     keyboard_layouts->GetDictionary(i, &entry);
1163     bool selected = false;
1164     entry->GetBoolean("selected", &selected);
1165     if (selected) {
1166       entry->GetString("value", &keyboard_layout);
1167       break;
1168     }
1169   }
1170   DCHECK(!keyboard_layout.empty());
1171   new_user_context.SetPublicSessionInputMethod(keyboard_layout);
1172
1173   LoginAsPublicSessionInternal(new_user_context);
1174 }
1175
1176 void ExistingUserController::LoginAsPublicSessionInternal(
1177     const UserContext& user_context) {
1178   // Only one instance of LoginPerformer should exist at a time.
1179   login_performer_.reset(NULL);
1180   login_performer_.reset(new ChromeLoginPerformer(this));
1181   login_performer_->LoginAsPublicSession(user_context);
1182   SendAccessibilityAlert(
1183       l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_PUBLIC_ACCOUNT));
1184 }
1185
1186 void ExistingUserController::PerformPreLoginActions(
1187     const UserContext& user_context) {
1188   // Disable clicking on other windows and status tray.
1189   login_display_->SetUIEnabled(false);
1190
1191   if (last_login_attempt_username_ != user_context.GetUserID()) {
1192     last_login_attempt_username_ = user_context.GetUserID();
1193     num_login_attempts_ = 0;
1194
1195     // Also reset state variables, which are used to determine password change.
1196     offline_failed_ = false;
1197     online_succeeded_for_.clear();
1198   }
1199
1200   // Guard in cases when we're called twice but login process is still active.
1201   // This might happen when login process is paused till signed settings status
1202   // is verified which results in Login* method called again as a callback.
1203   if (!is_login_in_progress_)
1204     num_login_attempts_++;
1205
1206   is_login_in_progress_ = true;
1207
1208   // Stop the auto-login timer when attempting login.
1209   StopPublicSessionAutoLoginTimer();
1210 }
1211
1212 void ExistingUserController::PerformLoginFinishedActions(
1213     bool start_public_session_timer) {
1214   is_login_in_progress_ = false;
1215
1216   // Reenable clicking on other windows and status area.
1217   login_display_->SetUIEnabled(true);
1218
1219   if (start_public_session_timer)
1220     StartPublicSessionAutoLoginTimer();
1221 }
1222
1223 }  // namespace chromeos