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