Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / login / existing_user_controller.cc
blob013756a7c1f63cbd58873e6605b7231550d4da62
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/login/existing_user_controller.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/command_line.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/histogram.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "base/version.h"
23 #include "chrome/browser/accessibility/accessibility_events.h"
24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/chrome_notification_types.h"
26 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
27 #include "chrome/browser/chromeos/boot_times_loader.h"
28 #include "chrome/browser/chromeos/customization_document.h"
29 #include "chrome/browser/chromeos/first_run/first_run.h"
30 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
31 #include "chrome/browser/chromeos/login/helper.h"
32 #include "chrome/browser/chromeos/login/login_display_host.h"
33 #include "chrome/browser/chromeos/login/login_utils.h"
34 #include "chrome/browser/chromeos/login/startup_utils.h"
35 #include "chrome/browser/chromeos/login/user_manager.h"
36 #include "chrome/browser/chromeos/login/wizard_controller.h"
37 #include "chrome/browser/chromeos/policy/device_local_account.h"
38 #include "chrome/browser/chromeos/profiles/profile_helper.h"
39 #include "chrome/browser/chromeos/settings/cros_settings.h"
40 #include "chrome/browser/google/google_util.h"
41 #include "chrome/browser/prefs/session_startup_pref.h"
42 #include "chrome/common/chrome_switches.h"
43 #include "chrome/common/chrome_version_info.h"
44 #include "chrome/common/pref_names.h"
45 #include "chrome/common/url_constants.h"
46 #include "chromeos/chromeos_switches.h"
47 #include "chromeos/dbus/dbus_thread_manager.h"
48 #include "chromeos/dbus/power_manager_client.h"
49 #include "chromeos/dbus/session_manager_client.h"
50 #include "chromeos/settings/cros_settings_names.h"
51 #include "components/policy/core/common/policy_service.h"
52 #include "content/public/browser/browser_thread.h"
53 #include "content/public/browser/notification_service.h"
54 #include "content/public/browser/notification_types.h"
55 #include "content/public/browser/user_metrics.h"
56 #include "google_apis/gaia/gaia_auth_util.h"
57 #include "google_apis/gaia/google_service_auth_error.h"
58 #include "grit/generated_resources.h"
59 #include "net/http/http_auth_cache.h"
60 #include "net/http/http_network_session.h"
61 #include "net/http/http_transaction_factory.h"
62 #include "net/url_request/url_request_context.h"
63 #include "net/url_request/url_request_context_getter.h"
64 #include "ui/base/accessibility/accessibility_types.h"
65 #include "ui/base/l10n/l10n_util.h"
66 #include "ui/views/widget/widget.h"
68 namespace chromeos {
70 namespace {
72 // URL for account creation.
73 const char kCreateAccountURL[] =
74 "https://accounts.google.com/NewAccount?service=mail";
76 // ChromeVox tutorial URL (used in place of "getting started" url when
77 // accessibility is enabled).
78 const char kChromeVoxTutorialURLPattern[] =
79 "http://www.chromevox.com/tutorial/index.html?lang=%s";
81 // Delay for transferring the auth cache to the system profile.
82 const long int kAuthCacheTransferDelayMs = 2000;
84 // Delay for restarting the ui if safe-mode login has failed.
85 const long int kSafeModeRestartUiDelayMs = 30000;
87 // Makes a call to the policy subsystem to reload the policy when we detect
88 // authentication change.
89 void RefreshPoliciesOnUIThread() {
90 if (g_browser_process->policy_service())
91 g_browser_process->policy_service()->RefreshPolicies(base::Closure());
94 // Copies any authentication details that were entered in the login profile in
95 // the mail profile to make sure all subsystems of Chrome can access the network
96 // with the provided authentication which are possibly for a proxy server.
97 void TransferContextAuthenticationsOnIOThread(
98 net::URLRequestContextGetter* default_profile_context_getter,
99 net::URLRequestContextGetter* browser_process_context_getter) {
100 net::HttpAuthCache* new_cache =
101 browser_process_context_getter->GetURLRequestContext()->
102 http_transaction_factory()->GetSession()->http_auth_cache();
103 net::HttpAuthCache* old_cache =
104 default_profile_context_getter->GetURLRequestContext()->
105 http_transaction_factory()->GetSession()->http_auth_cache();
106 new_cache->UpdateAllFrom(*old_cache);
107 VLOG(1) << "Main request context populated with authentication data.";
108 // Last but not least tell the policy subsystem to refresh now as it might
109 // have been stuck until now too.
110 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
111 base::Bind(&RefreshPoliciesOnUIThread));
114 } // namespace
116 // static
117 ExistingUserController* ExistingUserController::current_controller_ = NULL;
119 ////////////////////////////////////////////////////////////////////////////////
120 // ExistingUserController, public:
122 ExistingUserController::ExistingUserController(LoginDisplayHost* host)
123 : login_status_consumer_(NULL),
124 host_(host),
125 login_display_(host_->CreateLoginDisplay(this)),
126 num_login_attempts_(0),
127 cros_settings_(CrosSettings::Get()),
128 weak_factory_(this),
129 offline_failed_(false),
130 is_login_in_progress_(false),
131 password_changed_(false),
132 do_auto_enrollment_(false),
133 signin_screen_ready_(false),
134 network_state_helper_(new login::NetworkStateHelper) {
135 DCHECK(current_controller_ == NULL);
136 current_controller_ = this;
138 registrar_.Add(this,
139 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
140 content::NotificationService::AllSources());
141 registrar_.Add(this,
142 chrome::NOTIFICATION_USER_LIST_CHANGED,
143 content::NotificationService::AllSources());
144 registrar_.Add(this,
145 chrome::NOTIFICATION_AUTH_SUPPLIED,
146 content::NotificationService::AllSources());
147 registrar_.Add(this,
148 chrome::NOTIFICATION_SESSION_STARTED,
149 content::NotificationService::AllSources());
150 show_user_names_subscription_ = cros_settings_->AddSettingsObserver(
151 kAccountsPrefShowUserNamesOnSignIn,
152 base::Bind(&ExistingUserController::DeviceSettingsChanged,
153 base::Unretained(this)));
154 allow_new_user_subscription_ = cros_settings_->AddSettingsObserver(
155 kAccountsPrefAllowNewUser,
156 base::Bind(&ExistingUserController::DeviceSettingsChanged,
157 base::Unretained(this)));
158 allow_guest_subscription_ = cros_settings_->AddSettingsObserver(
159 kAccountsPrefAllowGuest,
160 base::Bind(&ExistingUserController::DeviceSettingsChanged,
161 base::Unretained(this)));
162 users_subscription_ = cros_settings_->AddSettingsObserver(
163 kAccountsPrefUsers,
164 base::Bind(&ExistingUserController::DeviceSettingsChanged,
165 base::Unretained(this)));
166 local_account_auto_login_id_subscription_ =
167 cros_settings_->AddSettingsObserver(
168 kAccountsPrefDeviceLocalAccountAutoLoginId,
169 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
170 base::Unretained(this)));
171 local_account_auto_login_delay_subscription_ =
172 cros_settings_->AddSettingsObserver(
173 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
174 base::Bind(&ExistingUserController::ConfigurePublicSessionAutoLogin,
175 base::Unretained(this)));
178 void ExistingUserController::Init(const UserList& users) {
179 time_init_ = base::Time::Now();
180 UpdateLoginDisplay(users);
181 ConfigurePublicSessionAutoLogin();
183 DBusThreadManager::Get()->GetSessionManagerClient()->EmitLoginPromptReady();
186 void ExistingUserController::UpdateLoginDisplay(const UserList& users) {
187 bool show_users_on_signin;
188 UserList filtered_users;
190 cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn,
191 &show_users_on_signin);
192 if (show_users_on_signin) {
193 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
194 // TODO(xiyuan): Clean user profile whose email is not in whitelist.
195 bool meets_locally_managed_requirements =
196 (*it)->GetType() != User::USER_TYPE_LOCALLY_MANAGED ||
197 UserManager::Get()->AreLocallyManagedUsersAllowed();
198 bool meets_whitelist_requirements =
199 LoginUtils::IsWhitelisted((*it)->email()) ||
200 (*it)->GetType() != User::USER_TYPE_REGULAR;
201 if (meets_locally_managed_requirements && meets_whitelist_requirements) {
202 filtered_users.push_back(*it);
207 // If no user pods are visible, fallback to single new user pod which will
208 // have guest session link.
209 bool show_guest;
210 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &show_guest);
211 bool show_users;
212 cros_settings_->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_users);
213 show_guest &= !filtered_users.empty();
214 bool show_new_user = true;
215 login_display_->set_parent_window(GetNativeWindow());
216 login_display_->Init(filtered_users, show_guest, show_users, show_new_user);
217 host_->OnPreferencesChanged();
220 void ExistingUserController::DoAutoEnrollment() {
221 do_auto_enrollment_ = true;
224 void ExistingUserController::ResumeLogin() {
225 // This means the user signed-in, then auto-enrollment used his credentials
226 // to enroll and succeeded.
227 resume_login_callback_.Run();
228 resume_login_callback_.Reset();
231 ////////////////////////////////////////////////////////////////////////////////
232 // ExistingUserController, content::NotificationObserver implementation:
235 void ExistingUserController::Observe(
236 int type,
237 const content::NotificationSource& source,
238 const content::NotificationDetails& details) {
239 if (type == chrome::NOTIFICATION_SESSION_STARTED) {
240 // Stop listening to any notification once session has started.
241 // Sign in screen objects are marked for deletion with DeleteSoon so
242 // make sure no object would be used after session has started.
243 // http://crbug.com/125276
244 registrar_.RemoveAll();
245 return;
247 if (type == chrome::NOTIFICATION_USER_LIST_CHANGED) {
248 DeviceSettingsChanged();
249 return;
251 if (type == chrome::NOTIFICATION_AUTH_SUPPLIED) {
252 // Possibly the user has authenticated against a proxy server and we might
253 // need the credentials for enrollment and other system requests from the
254 // main |g_browser_process| request context (see bug
255 // http://crosbug.com/24861). So we transfer any credentials to the global
256 // request context here.
257 // The issue we have here is that the NOTIFICATION_AUTH_SUPPLIED is sent
258 // just after the UI is closed but before the new credentials were stored
259 // in the profile. Therefore we have to give it some time to make sure it
260 // has been updated before we copy it.
261 VLOG(1) << "Authentication was entered manually, possibly for proxyauth.";
262 scoped_refptr<net::URLRequestContextGetter> browser_process_context_getter =
263 g_browser_process->system_request_context();
264 Profile* signin_profile = ProfileHelper::GetSigninProfile();
265 scoped_refptr<net::URLRequestContextGetter> signin_profile_context_getter =
266 signin_profile->GetRequestContext();
267 DCHECK(browser_process_context_getter.get());
268 DCHECK(signin_profile_context_getter.get());
269 content::BrowserThread::PostDelayedTask(
270 content::BrowserThread::IO, FROM_HERE,
271 base::Bind(&TransferContextAuthenticationsOnIOThread,
272 signin_profile_context_getter,
273 browser_process_context_getter),
274 base::TimeDelta::FromMilliseconds(kAuthCacheTransferDelayMs));
276 if (type != chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED)
277 return;
278 login_display_->OnUserImageChanged(*content::Details<User>(details).ptr());
281 ////////////////////////////////////////////////////////////////////////////////
282 // ExistingUserController, private:
284 ExistingUserController::~ExistingUserController() {
285 LoginUtils::Get()->DelegateDeleted(this);
287 if (current_controller_ == this) {
288 current_controller_ = NULL;
289 } else {
290 NOTREACHED() << "More than one controller are alive.";
292 DCHECK(login_display_.get());
295 ////////////////////////////////////////////////////////////////////////////////
296 // ExistingUserController, LoginDisplay::Delegate implementation:
299 void ExistingUserController::CancelPasswordChangedFlow() {
300 login_performer_.reset(NULL);
301 login_display_->SetUIEnabled(true);
302 StartPublicSessionAutoLoginTimer();
305 void ExistingUserController::CreateAccount() {
306 content::RecordAction(base::UserMetricsAction("Login.CreateAccount"));
307 guest_mode_url_ =
308 google_util::AppendGoogleLocaleParam(GURL(kCreateAccountURL));
309 LoginAsGuest();
312 void ExistingUserController::CompleteLogin(const UserContext& user_context) {
313 login_display_->set_signin_completed(true);
314 if (!host_) {
315 // Complete login event was generated already from UI. Ignore notification.
316 return;
319 // Stop the auto-login timer when attempting login.
320 StopPublicSessionAutoLoginTimer();
322 // Disable UI while loading user profile.
323 login_display_->SetUIEnabled(false);
325 if (!time_init_.is_null()) {
326 base::TimeDelta delta = base::Time::Now() - time_init_;
327 UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToCompleteLoginTime", delta);
328 time_init_ = base::Time(); // Reset to null.
331 host_->OnCompleteLogin();
333 // Do an ownership check now to avoid auto-enrolling if the device has
334 // already been owned.
335 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
336 base::Bind(&ExistingUserController::CompleteLoginInternal,
337 weak_factory_.GetWeakPtr(),
338 user_context));
341 void ExistingUserController::CompleteLoginInternal(
342 const UserContext& user_context,
343 DeviceSettingsService::OwnershipStatus ownership_status) {
344 // Auto-enrollment must have made a decision by now. It's too late to enroll
345 // if the protocol isn't done at this point.
346 if (do_auto_enrollment_ &&
347 ownership_status == DeviceSettingsService::OWNERSHIP_NONE) {
348 VLOG(1) << "Forcing auto-enrollment before completing login";
349 // The only way to get out of the enrollment screen from now on is to either
350 // complete enrollment, or opt-out of it. So this controller shouldn't force
351 // enrollment again if it is reused for another sign-in.
352 do_auto_enrollment_ = false;
353 auto_enrollment_username_ = user_context.username;
354 resume_login_callback_ = base::Bind(
355 &ExistingUserController::PerformLogin,
356 weak_factory_.GetWeakPtr(),
357 user_context, LoginPerformer::AUTH_MODE_EXTENSION);
358 ShowEnrollmentScreen(true, user_context.username);
359 // Enable UI for the enrollment screen. SetUIEnabled(true) will post a
360 // request to show the sign-in screen again when invoked at the sign-in
361 // screen; invoke SetUIEnabled() after navigating to the enrollment screen.
362 login_display_->SetUIEnabled(true);
363 } else {
364 PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION);
368 base::string16 ExistingUserController::GetConnectedNetworkName() {
369 return network_state_helper_->GetCurrentNetworkName();
372 bool ExistingUserController::IsSigninInProgress() const {
373 return is_login_in_progress_;
376 void ExistingUserController::Login(const UserContext& user_context) {
377 if ((user_context.username.empty() || user_context.password.empty()) &&
378 user_context.auth_code.empty())
379 return;
381 // Stop the auto-login timer when attempting login.
382 StopPublicSessionAutoLoginTimer();
384 // Disable clicking on other windows.
385 login_display_->SetUIEnabled(false);
387 BootTimesLoader::Get()->RecordLoginAttempted();
389 if (last_login_attempt_username_ != user_context.username) {
390 last_login_attempt_username_ = user_context.username;
391 num_login_attempts_ = 0;
392 // Also reset state variables, which are used to determine password change.
393 offline_failed_ = false;
394 online_succeeded_for_.clear();
396 num_login_attempts_++;
397 PerformLogin(user_context, LoginPerformer::AUTH_MODE_INTERNAL);
400 void ExistingUserController::PerformLogin(
401 const UserContext& user_context,
402 LoginPerformer::AuthorizationMode auth_mode) {
403 UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
404 set_host(host_);
406 // Disable UI while loading user profile.
407 login_display_->SetUIEnabled(false);
409 // Use the same LoginPerformer for subsequent login as it has state
410 // such as Authenticator instance.
411 if (!login_performer_.get() || num_login_attempts_ <= 1) {
412 LoginPerformer::Delegate* delegate = this;
413 if (login_performer_delegate_.get())
414 delegate = login_performer_delegate_.get();
415 // Only one instance of LoginPerformer should exist at a time.
416 login_performer_.reset(NULL);
417 login_performer_.reset(new LoginPerformer(delegate));
420 is_login_in_progress_ = true;
421 if (gaia::ExtractDomainName(user_context.username) ==
422 UserManager::kLocallyManagedUserDomain) {
423 login_performer_->LoginAsLocallyManagedUser(
424 UserContext(user_context.username,
425 user_context.password,
426 std::string())); // auth_code
427 } else {
428 login_performer_->PerformLogin(user_context, auth_mode);
430 SendAccessibilityAlert(
431 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN));
434 void ExistingUserController::LoginAsRetailModeUser() {
435 // Stop the auto-login timer when attempting login.
436 StopPublicSessionAutoLoginTimer();
438 // Disable clicking on other windows.
439 login_display_->SetUIEnabled(false);
440 // TODO(rkc): Add a CHECK to make sure retail mode logins are allowed once
441 // the enterprise policy wiring is done for retail mode.
443 // Only one instance of LoginPerformer should exist at a time.
444 login_performer_.reset(NULL);
445 login_performer_.reset(new LoginPerformer(this));
446 is_login_in_progress_ = true;
447 login_performer_->LoginRetailMode();
448 SendAccessibilityAlert(
449 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_DEMOUSER));
452 void ExistingUserController::LoginAsGuest() {
453 if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn())
454 return;
456 // Stop the auto-login timer when attempting login.
457 StopPublicSessionAutoLoginTimer();
459 // Disable clicking on other windows.
460 login_display_->SetUIEnabled(false);
462 CrosSettingsProvider::TrustedStatus status =
463 cros_settings_->PrepareTrustedValues(
464 base::Bind(&ExistingUserController::LoginAsGuest,
465 weak_factory_.GetWeakPtr()));
466 // Must not proceed without signature verification.
467 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
468 login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1,
469 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
470 // Reenable clicking on other windows and status area.
471 login_display_->SetUIEnabled(true);
472 StartPublicSessionAutoLoginTimer();
473 display_email_.clear();
474 return;
475 } else if (status != CrosSettingsProvider::TRUSTED) {
476 // Value of AllowNewUser setting is still not verified.
477 // Another attempt will be invoked after verification completion.
478 return;
481 bool allow_guest;
482 cros_settings_->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
483 if (!allow_guest) {
484 // Disallowed. The UI should normally not show the guest pod but if for some
485 // reason this has been made available to the user here is the time to tell
486 // this nicely.
487 login_display_->ShowError(IDS_LOGIN_ERROR_WHITELIST, 1,
488 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
489 // Reenable clicking on other windows and status area.
490 login_display_->SetUIEnabled(true);
491 StartPublicSessionAutoLoginTimer();
492 display_email_.clear();
493 return;
496 // Only one instance of LoginPerformer should exist at a time.
497 login_performer_.reset(NULL);
498 login_performer_.reset(new LoginPerformer(this));
499 is_login_in_progress_ = true;
500 login_performer_->LoginOffTheRecord();
501 SendAccessibilityAlert(
502 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_OFFRECORD));
505 void ExistingUserController::MigrateUserData(const std::string& old_password) {
506 // LoginPerformer instance has state of the user so it should exist.
507 if (login_performer_.get())
508 login_performer_->RecoverEncryptedData(old_password);
511 void ExistingUserController::LoginAsPublicAccount(
512 const std::string& username) {
513 if (is_login_in_progress_ || UserManager::Get()->IsUserLoggedIn())
514 return;
516 // Stop the auto-login timer when attempting login.
517 StopPublicSessionAutoLoginTimer();
519 // Disable clicking on other windows.
520 login_display_->SetUIEnabled(false);
522 CrosSettingsProvider::TrustedStatus status =
523 cros_settings_->PrepareTrustedValues(
524 base::Bind(&ExistingUserController::LoginAsPublicAccount,
525 weak_factory_.GetWeakPtr(),
526 username));
527 // If device policy is permanently unavailable, logging into public accounts
528 // is not possible.
529 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
530 login_display_->ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, 1,
531 HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
532 // Re-enable clicking on other windows.
533 login_display_->SetUIEnabled(true);
534 return;
537 // If device policy is not verified yet, this function will be called again
538 // when verification finishes.
539 if (status != CrosSettingsProvider::TRUSTED)
540 return;
542 // If there is no public account with the given |username|, logging in is not
543 // possible.
544 const User* user = UserManager::Get()->FindUser(username);
545 if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT) {
546 // Re-enable clicking on other windows.
547 login_display_->SetUIEnabled(true);
548 StartPublicSessionAutoLoginTimer();
549 return;
552 // Only one instance of LoginPerformer should exist at a time.
553 login_performer_.reset(NULL);
554 login_performer_.reset(new LoginPerformer(this));
555 is_login_in_progress_ = true;
556 login_performer_->LoginAsPublicAccount(username);
557 SendAccessibilityAlert(
558 l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNIN_PUBLIC_ACCOUNT));
561 void ExistingUserController::LoginAsKioskApp(const std::string& app_id) {
562 host_->StartAppLaunch(app_id);
565 void ExistingUserController::OnSigninScreenReady() {
566 signin_screen_ready_ = true;
567 StartPublicSessionAutoLoginTimer();
570 void ExistingUserController::OnUserSelected(const std::string& username) {
571 login_performer_.reset(NULL);
572 num_login_attempts_ = 0;
575 void ExistingUserController::OnStartEnterpriseEnrollment() {
576 DeviceSettingsService::Get()->GetOwnershipStatusAsync(
577 base::Bind(&ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
578 weak_factory_.GetWeakPtr()));
581 void ExistingUserController::OnStartKioskEnableScreen() {
582 KioskAppManager::Get()->GetConsumerKioskModeStatus(
583 base::Bind(&ExistingUserController::OnConsumerKioskModeCheckCompleted,
584 weak_factory_.GetWeakPtr()));
587 void ExistingUserController::OnStartDeviceReset() {
588 ShowResetScreen();
591 void ExistingUserController::OnStartKioskAutolaunchScreen() {
592 ShowKioskAutolaunchScreen();
595 void ExistingUserController::ResyncUserData() {
596 // LoginPerformer instance has state of the user so it should exist.
597 if (login_performer_.get())
598 login_performer_->ResyncEncryptedData();
601 void ExistingUserController::SetDisplayEmail(const std::string& email) {
602 display_email_ = email;
605 void ExistingUserController::ShowWrongHWIDScreen() {
606 scoped_ptr<base::DictionaryValue> params;
607 host_->StartWizard(WizardController::kWrongHWIDScreenName, params.Pass());
608 login_display_->OnFadeOut();
611 void ExistingUserController::Signout() {
612 NOTREACHED();
615 void ExistingUserController::OnConsumerKioskModeCheckCompleted(
616 KioskAppManager::ConsumerKioskModeStatus status) {
617 if (status == KioskAppManager::CONSUMER_KIOSK_MODE_CONFIGURABLE)
618 ShowKioskEnableScreen();
621 void ExistingUserController::OnEnrollmentOwnershipCheckCompleted(
622 DeviceSettingsService::OwnershipStatus status) {
623 if (status == DeviceSettingsService::OWNERSHIP_NONE) {
624 ShowEnrollmentScreen(false, std::string());
625 } else if (status == DeviceSettingsService::OWNERSHIP_TAKEN) {
626 // On a device that is already owned we might want to allow users to
627 // re-enroll if the policy information is invalid.
628 CrosSettingsProvider::TrustedStatus trusted_status =
629 CrosSettings::Get()->PrepareTrustedValues(
630 base::Bind(
631 &ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
632 weak_factory_.GetWeakPtr(), status));
633 if (trusted_status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
634 ShowEnrollmentScreen(false, std::string());
636 } else {
637 // OwnershipService::GetStatusAsync is supposed to return either
638 // OWNERSHIP_NONE or OWNERSHIP_TAKEN.
639 NOTREACHED();
643 void ExistingUserController::ShowEnrollmentScreen(bool is_auto_enrollment,
644 const std::string& user) {
645 scoped_ptr<base::DictionaryValue> params;
646 if (is_auto_enrollment) {
647 params.reset(new base::DictionaryValue());
648 params->SetBoolean("is_auto_enrollment", true);
649 params->SetString("user", user);
651 host_->StartWizard(WizardController::kEnrollmentScreenName,
652 params.Pass());
653 login_display_->OnFadeOut();
656 void ExistingUserController::ShowResetScreen() {
657 scoped_ptr<base::DictionaryValue> params;
658 host_->StartWizard(WizardController::kResetScreenName, params.Pass());
659 login_display_->OnFadeOut();
662 void ExistingUserController::ShowKioskEnableScreen() {
663 scoped_ptr<base::DictionaryValue> params;
664 host_->StartWizard(WizardController::kKioskEnableScreenName, params.Pass());
665 login_display_->OnFadeOut();
668 void ExistingUserController::ShowKioskAutolaunchScreen() {
669 scoped_ptr<base::DictionaryValue> params;
670 host_->StartWizard(WizardController::kKioskAutolaunchScreenName,
671 params.Pass());
672 login_display_->OnFadeOut();
675 void ExistingUserController::ShowTPMError() {
676 login_display_->SetUIEnabled(false);
677 login_display_->ShowErrorScreen(LoginDisplay::TPM_ERROR);
680 ////////////////////////////////////////////////////////////////////////////////
681 // ExistingUserController, LoginPerformer::Delegate implementation:
684 void ExistingUserController::OnLoginFailure(const LoginFailure& failure) {
685 is_login_in_progress_ = false;
686 offline_failed_ = true;
688 guest_mode_url_ = GURL::EmptyGURL();
689 std::string error = failure.GetErrorString();
691 if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
692 HandleLoginFailure(failure)) {
693 login_display_->SetUIEnabled(true);
694 return;
697 if (failure.reason() == LoginFailure::OWNER_REQUIRED) {
698 ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error);
699 content::BrowserThread::PostDelayedTask(
700 content::BrowserThread::UI, FROM_HERE,
701 base::Bind(&SessionManagerClient::StopSession,
702 base::Unretained(DBusThreadManager::Get()->
703 GetSessionManagerClient())),
704 base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs));
705 } else if (failure.reason() == LoginFailure::TPM_ERROR) {
706 ShowTPMError();
707 } else if (!online_succeeded_for_.empty()) {
708 ShowGaiaPasswordChanged(online_succeeded_for_);
709 } else {
710 // Check networking after trying to login in case user is
711 // cached locally or the local admin account.
712 bool is_known_user =
713 UserManager::Get()->IsKnownUser(last_login_attempt_username_);
714 if (!network_state_helper_->IsConnected()) {
715 if (is_known_user)
716 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
717 else
718 ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
719 } else {
720 // TODO(nkostylev): Cleanup rest of ClientLogin related code.
721 if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED &&
722 failure.error().state() ==
723 GoogleServiceAuthError::HOSTED_NOT_ALLOWED) {
724 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_HOSTED, error);
725 } else {
726 if (!is_known_user)
727 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING_NEW, error);
728 else
729 ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
732 // Reenable clicking on other windows and status area.
733 login_display_->SetUIEnabled(true);
734 login_display_->ClearAndEnablePassword();
735 StartPublicSessionAutoLoginTimer();
738 // Reset user flow to default, so that special flow will not affect next
739 // attempt.
740 UserManager::Get()->ResetUserFlow(last_login_attempt_username_);
742 if (login_status_consumer_)
743 login_status_consumer_->OnLoginFailure(failure);
745 // Clear the recorded displayed email so it won't affect any future attempts.
746 display_email_.clear();
749 void ExistingUserController::OnLoginSuccess(const UserContext& user_context) {
750 is_login_in_progress_ = false;
751 offline_failed_ = false;
752 login_display_->set_signin_completed(true);
754 StopPublicSessionAutoLoginTimer();
756 bool has_cookies =
757 login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION &&
758 user_context.auth_code.empty();
760 // Login performer will be gone so cache this value to use
761 // once profile is loaded.
762 password_changed_ = login_performer_->password_changed();
764 // LoginPerformer instance will delete itself once online auth result is OK.
765 // In case of failure it'll bring up ScreenLock and ask for
766 // correct password/display error message.
767 // Even in case when following online,offline protocol and returning
768 // requests_pending = false, let LoginPerformer delete itself.
769 login_performer_->set_delegate(NULL);
770 ignore_result(login_performer_.release());
772 // Will call OnProfilePrepared() in the end.
773 LoginUtils::Get()->PrepareProfile(user_context,
774 display_email_,
775 has_cookies,
776 false, // Start session for user.
777 this);
779 display_email_.clear();
781 // Notify LoginDisplay to allow it provide visual feedback to user.
782 login_display_->OnLoginSuccess(user_context.username);
785 void ExistingUserController::OnProfilePrepared(Profile* profile) {
786 // Reenable clicking on other windows and status area.
787 login_display_->SetUIEnabled(true);
789 UserManager* user_manager = UserManager::Get();
790 if (user_manager->IsCurrentUserNew() &&
791 user_manager->IsLoggedInAsLocallyManagedUser()) {
792 // Supervised users should launch into empty desktop on first run.
793 CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kSilentLaunch);
796 if (user_manager->IsCurrentUserNew() &&
797 !user_manager->GetCurrentUserFlow()->ShouldSkipPostLoginScreens() &&
798 !WizardController::default_controller()->skip_post_login_screens()) {
799 // Don't specify start URLs if the administrator has configured the start
800 // URLs via policy.
801 if (!SessionStartupPref::TypeIsManaged(profile->GetPrefs()))
802 InitializeStartUrls();
804 // Mark the device as registered., i.e. the second part of OOBE as
805 // completed.
806 if (!StartupUtils::IsDeviceRegistered())
807 StartupUtils::MarkDeviceRegistered();
809 if (CommandLine::ForCurrentProcess()->HasSwitch(
810 chromeos::switches::kOobeSkipPostLogin)) {
811 LoginUtils::Get()->DoBrowserLaunch(profile, host_);
812 host_ = NULL;
813 } else {
814 ActivateWizard(WizardController::kTermsOfServiceScreenName);
816 } else {
817 LoginUtils::Get()->DoBrowserLaunch(profile, host_);
818 host_ = NULL;
820 // Inform |login_status_consumer_| about successful login.
821 if (login_status_consumer_)
822 login_status_consumer_->OnLoginSuccess(UserContext());
823 login_display_->OnFadeOut();
826 void ExistingUserController::OnOffTheRecordLoginSuccess() {
827 is_login_in_progress_ = false;
828 offline_failed_ = false;
830 // Mark the device as registered., i.e. the second part of OOBE as completed.
831 if (!StartupUtils::IsDeviceRegistered())
832 StartupUtils::MarkDeviceRegistered();
834 LoginUtils::Get()->CompleteOffTheRecordLogin(guest_mode_url_);
836 if (login_status_consumer_)
837 login_status_consumer_->OnOffTheRecordLoginSuccess();
840 void ExistingUserController::OnPasswordChangeDetected() {
841 is_login_in_progress_ = false;
842 offline_failed_ = false;
844 // Must not proceed without signature verification.
845 if (CrosSettingsProvider::TRUSTED != cros_settings_->PrepareTrustedValues(
846 base::Bind(&ExistingUserController::OnPasswordChangeDetected,
847 weak_factory_.GetWeakPtr()))) {
848 // Value of owner email is still not verified.
849 // Another attempt will be invoked after verification completion.
850 return;
853 if (UserManager::Get()->GetUserFlow(last_login_attempt_username_)->
854 HandlePasswordChangeDetected()) {
855 return;
858 // True if user has already made an attempt to enter old password and failed.
859 bool show_invalid_old_password_error =
860 login_performer_->password_changed_callback_count() > 1;
862 // Note: We allow owner using "full sync" mode which will recreate
863 // cryptohome and deal with owner private key being lost. This also allows
864 // us to recover from a lost owner password/homedir.
865 // TODO(gspencer): We shouldn't have to erase stateful data when
866 // doing this. See http://crosbug.com/9115 http://crosbug.com/7792
867 login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error);
869 if (login_status_consumer_)
870 login_status_consumer_->OnPasswordChangeDetected();
872 display_email_.clear();
875 void ExistingUserController::WhiteListCheckFailed(const std::string& email) {
876 is_login_in_progress_ = false;
877 offline_failed_ = false;
879 ShowError(IDS_LOGIN_ERROR_WHITELIST, email);
881 // Reenable clicking on other windows and status area.
882 login_display_->SetUIEnabled(true);
883 login_display_->ShowSigninUI(email);
885 if (login_status_consumer_) {
886 login_status_consumer_->OnLoginFailure(LoginFailure(
887 LoginFailure::WHITELIST_CHECK_FAILED));
890 display_email_.clear();
892 StartPublicSessionAutoLoginTimer();
895 void ExistingUserController::PolicyLoadFailed() {
896 ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST, "");
898 // Reenable clicking on other windows and status area.
899 is_login_in_progress_ = false;
900 offline_failed_ = false;
901 login_display_->SetUIEnabled(true);
903 display_email_.clear();
905 // Policy load failure stops login attempts -- restart the timer.
906 StartPublicSessionAutoLoginTimer();
909 void ExistingUserController::OnOnlineChecked(const std::string& username,
910 bool success) {
911 if (success && last_login_attempt_username_ == username) {
912 online_succeeded_for_ = username;
913 // Wait for login attempt to end, if it hasn't yet.
914 if (offline_failed_ && !is_login_in_progress_)
915 ShowGaiaPasswordChanged(username);
919 ////////////////////////////////////////////////////////////////////////////////
920 // ExistingUserController, private:
922 void ExistingUserController::DeviceSettingsChanged() {
923 if (host_ != NULL) {
924 // Signed settings or user list changed. Notify views and update them.
925 UpdateLoginDisplay(chromeos::UserManager::Get()->GetUsers());
926 ConfigurePublicSessionAutoLogin();
927 return;
931 void ExistingUserController::ActivateWizard(const std::string& screen_name) {
932 scoped_ptr<base::DictionaryValue> params;
933 host_->StartWizard(screen_name, params.Pass());
936 void ExistingUserController::ConfigurePublicSessionAutoLogin() {
937 std::string auto_login_account_id;
938 cros_settings_->GetString(kAccountsPrefDeviceLocalAccountAutoLoginId,
939 &auto_login_account_id);
940 const std::vector<policy::DeviceLocalAccount> device_local_accounts =
941 policy::GetDeviceLocalAccounts(cros_settings_);
943 public_session_auto_login_username_.clear();
944 for (std::vector<policy::DeviceLocalAccount>::const_iterator
945 it = device_local_accounts.begin();
946 it != device_local_accounts.end(); ++it) {
947 if (it->account_id == auto_login_account_id) {
948 public_session_auto_login_username_ = it->user_id;
949 break;
953 const User* user =
954 UserManager::Get()->FindUser(public_session_auto_login_username_);
955 if (!user || user->GetType() != User::USER_TYPE_PUBLIC_ACCOUNT)
956 public_session_auto_login_username_.clear();
958 if (!cros_settings_->GetInteger(
959 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
960 &public_session_auto_login_delay_)) {
961 public_session_auto_login_delay_ = 0;
964 if (!public_session_auto_login_username_.empty())
965 StartPublicSessionAutoLoginTimer();
966 else
967 StopPublicSessionAutoLoginTimer();
970 void ExistingUserController::ResetPublicSessionAutoLoginTimer() {
971 // Only restart the auto-login timer if it's already running.
972 if (auto_login_timer_ && auto_login_timer_->IsRunning()) {
973 StopPublicSessionAutoLoginTimer();
974 StartPublicSessionAutoLoginTimer();
978 void ExistingUserController::OnPublicSessionAutoLoginTimerFire() {
979 CHECK(signin_screen_ready_ &&
980 !is_login_in_progress_ &&
981 !public_session_auto_login_username_.empty());
982 LoginAsPublicAccount(public_session_auto_login_username_);
985 void ExistingUserController::StopPublicSessionAutoLoginTimer() {
986 if (auto_login_timer_)
987 auto_login_timer_->Stop();
990 void ExistingUserController::StartPublicSessionAutoLoginTimer() {
991 if (!signin_screen_ready_ ||
992 is_login_in_progress_ ||
993 public_session_auto_login_username_.empty()) {
994 return;
997 // Start the auto-login timer.
998 if (!auto_login_timer_)
999 auto_login_timer_.reset(new base::OneShotTimer<ExistingUserController>);
1001 auto_login_timer_->Start(
1002 FROM_HERE,
1003 base::TimeDelta::FromMilliseconds(
1004 public_session_auto_login_delay_),
1005 base::Bind(
1006 &ExistingUserController::OnPublicSessionAutoLoginTimerFire,
1007 weak_factory_.GetWeakPtr()));
1010 gfx::NativeWindow ExistingUserController::GetNativeWindow() const {
1011 return host_->GetNativeWindow();
1014 void ExistingUserController::InitializeStartUrls() const {
1015 std::vector<std::string> start_urls;
1017 const base::ListValue *urls;
1018 bool can_show_getstarted_guide = true;
1019 if (UserManager::Get()->IsLoggedInAsDemoUser()) {
1020 if (CrosSettings::Get()->GetList(kStartUpUrls, &urls)) {
1021 // The retail mode user will get start URLs from a special policy if it is
1022 // set.
1023 for (base::ListValue::const_iterator it = urls->begin();
1024 it != urls->end(); ++it) {
1025 std::string url;
1026 if ((*it)->GetAsString(&url))
1027 start_urls.push_back(url);
1030 can_show_getstarted_guide = false;
1031 // Skip the default first-run behavior for public accounts.
1032 } else if (!UserManager::Get()->IsLoggedInAsPublicAccount()) {
1033 if (AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
1034 const char* url = kChromeVoxTutorialURLPattern;
1035 PrefService* prefs = g_browser_process->local_state();
1036 const std::string current_locale =
1037 StringToLowerASCII(prefs->GetString(prefs::kApplicationLocale));
1038 std::string vox_url = base::StringPrintf(url, current_locale.c_str());
1039 start_urls.push_back(vox_url);
1040 can_show_getstarted_guide = false;
1044 ServicesCustomizationDocument* customization =
1045 ServicesCustomizationDocument::GetInstance();
1046 if (!ServicesCustomizationDocument::WasApplied() &&
1047 customization->IsReady()) {
1048 // Since we don't use OEM start URL anymore, just mark as applied.
1049 customization->ApplyCustomization();
1052 // Only show getting started guide for a new user.
1053 const bool should_show_getstarted_guide =
1054 UserManager::Get()->IsCurrentUserNew();
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]);
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;
1095 login_display_->ShowError(error_id, num_login_attempts_, help_topic_id);
1098 void ExistingUserController::ShowGaiaPasswordChanged(
1099 const std::string& username) {
1100 // Invalidate OAuth token, since it can't be correct after password is
1101 // changed.
1102 UserManager::Get()->SaveUserOAuthStatus(
1103 username,
1104 User::OAUTH2_TOKEN_STATUS_INVALID);
1106 login_display_->SetUIEnabled(true);
1107 login_display_->ShowGaiaPasswordChanged(username);
1110 void ExistingUserController::SendAccessibilityAlert(
1111 const std::string& alert_text) {
1112 AccessibilityAlertInfo event(ProfileHelper::GetSigninProfile(), alert_text);
1113 SendControlAccessibilityNotification(
1114 ui::AccessibilityTypes::EVENT_VALUE_CHANGED, &event);
1117 } // namespace chromeos