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