1 // Copyright (c) 2013 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/ui/webui/chromeos/login/signin_screen_handler.h"
7 #include "base/callback.h"
8 #include "base/command_line.h"
9 #include "base/debug/trace_event.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/histogram.h"
13 #include "base/prefs/pref_registry_simple.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/prefs/scoped_user_pref_update.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/browser_process_platform_part_chromeos.h"
22 #include "chrome/browser/browser_shutdown.h"
23 #include "chrome/browser/chrome_notification_types.h"
24 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
25 #include "chrome/browser/chromeos/input_method/input_method_util.h"
26 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
27 #include "chrome/browser/chromeos/login/hwid_checker.h"
28 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
29 #include "chrome/browser/chromeos/login/screen_locker.h"
30 #include "chrome/browser/chromeos/login/screens/core_oobe_actor.h"
31 #include "chrome/browser/chromeos/login/user.h"
32 #include "chrome/browser/chromeos/login/webui_login_display.h"
33 #include "chrome/browser/chromeos/login/wizard_controller.h"
34 #include "chrome/browser/chromeos/net/network_portal_detector.h"
35 #include "chrome/browser/chromeos/profiles/profile_helper.h"
36 #include "chrome/browser/chromeos/settings/cros_settings.h"
37 #include "chrome/browser/io_thread.h"
38 #include "chrome/browser/policy/browser_policy_connector.h"
39 #include "chrome/browser/profiles/profile.h"
40 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
41 #include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
42 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
43 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
44 #include "chrome/common/chrome_switches.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/ime/input_method_manager.h"
51 #include "chromeos/ime/xkeyboard.h"
52 #include "chromeos/network/network_state.h"
53 #include "chromeos/network/network_state_handler.h"
54 #include "content/public/browser/render_view_host.h"
55 #include "content/public/browser/web_contents.h"
56 #include "google_apis/gaia/gaia_auth_util.h"
57 #include "google_apis/gaia/gaia_switches.h"
58 #include "google_apis/gaia/gaia_urls.h"
59 #include "grit/chromium_strings.h"
60 #include "grit/generated_resources.h"
61 #include "third_party/cros_system_api/dbus/service_constants.h"
62 #include "ui/base/l10n/l10n_util.h"
65 #include "ash/shell.h"
66 #include "ash/wm/lock_state_controller.h"
69 using content::BrowserThread;
70 using content::RenderViewHost;
74 // User dictionary keys.
75 const char kKeyUsername[] = "username";
76 const char kKeyDisplayName[] = "displayName";
77 const char kKeyEmailAddress[] = "emailAddress";
78 const char kKeyEnterpriseDomain[] = "enterpriseDomain";
79 const char kKeyPublicAccount[] = "publicAccount";
80 const char kKeyLocallyManagedUser[] = "locallyManagedUser";
81 const char kKeySignedIn[] = "signedIn";
82 const char kKeyCanRemove[] = "canRemove";
83 const char kKeyIsOwner[] = "isOwner";
84 const char kKeyOauthTokenStatus[] = "oauthTokenStatus";
86 // Max number of users to show.
87 const size_t kMaxUsers = 18;
89 // Timeout to delay first notification about offline state for a
91 const int kOfflineTimeoutSec = 5;
93 // Timeout used to prevent infinite connecting to a flaky network.
94 const int kConnectingTimeoutSec = 60;
96 // Type of the login screen UI that is currently presented to user.
97 const char kSourceGaiaSignin[] = "gaia-signin";
98 const char kSourceAccountPicker[] = "account-picker";
100 // The Task posted to PostTaskAndReply in StartClearingDnsCache on the IO
102 void ClearDnsCache(IOThread* io_thread) {
103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
104 if (browser_shutdown::IsTryingToQuit())
107 io_thread->ClearHostCache();
110 static bool Contains(const std::vector<std::string>& container,
111 const std::string& value) {
112 return std::find(container.begin(), container.end(), value) !=
122 const char kNetworkStateOffline[] = "offline";
123 const char kNetworkStateOnline[] = "online";
124 const char kNetworkStateCaptivePortal[] = "behind captive portal";
125 const char kNetworkStateConnecting[] = "connecting";
126 const char kNetworkStateProxyAuthRequired[] = "proxy auth required";
128 const char kErrorReasonProxyAuthCancelled[] = "proxy auth cancelled";
129 const char kErrorReasonProxyAuthSupplied[] = "proxy auth supplied";
130 const char kErrorReasonProxyConnectionFailed[] = "proxy connection failed";
131 const char kErrorReasonProxyConfigChanged[] = "proxy config changed";
132 const char kErrorReasonLoadingTimeout[] = "loading timeout";
133 const char kErrorReasonPortalDetected[] = "portal detected";
134 const char kErrorReasonNetworkStateChanged[] = "network state changed";
135 const char kErrorReasonUpdate[] = "update";
136 const char kErrorReasonFrameError[] = "frame error";
138 const char* NetworkStateStatusString(NetworkStateInformer::State state) {
140 case NetworkStateInformer::OFFLINE:
141 return kNetworkStateOffline;
142 case NetworkStateInformer::ONLINE:
143 return kNetworkStateOnline;
144 case NetworkStateInformer::CAPTIVE_PORTAL:
145 return kNetworkStateCaptivePortal;
146 case NetworkStateInformer::CONNECTING:
147 return kNetworkStateConnecting;
148 case NetworkStateInformer::PROXY_AUTH_REQUIRED:
149 return kNetworkStateProxyAuthRequired;
156 const char* ErrorReasonString(ErrorScreenActor::ErrorReason reason) {
158 case ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED:
159 return kErrorReasonProxyAuthCancelled;
160 case ErrorScreenActor::ERROR_REASON_PROXY_AUTH_SUPPLIED:
161 return kErrorReasonProxyAuthSupplied;
162 case ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED:
163 return kErrorReasonProxyConnectionFailed;
164 case ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED:
165 return kErrorReasonProxyConfigChanged;
166 case ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT:
167 return kErrorReasonLoadingTimeout;
168 case ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED:
169 return kErrorReasonPortalDetected;
170 case ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED:
171 return kErrorReasonNetworkStateChanged;
172 case ErrorScreenActor::ERROR_REASON_UPDATE:
173 return kErrorReasonUpdate;
174 case ErrorScreenActor::ERROR_REASON_FRAME_ERROR:
175 return kErrorReasonFrameError;
182 // Updates params dictionary passed to the auth extension with related
183 // preferences from CrosSettings.
184 void UpdateAuthParamsFromSettings(DictionaryValue* params,
185 const CrosSettings* cros_settings) {
186 bool allow_new_user = true;
187 cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
188 bool allow_guest = true;
189 cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
190 // Account creation depends on Guest sign-in (http://crosbug.com/24570).
191 params->SetBoolean("createAccount", allow_new_user && allow_guest);
192 params->SetBoolean("guestSignin", allow_guest);
195 bool IsOnline(NetworkStateInformer::State state,
196 ErrorScreenActor::ErrorReason reason) {
197 return state == NetworkStateInformer::ONLINE &&
198 reason != ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED &&
199 reason != ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT;
202 bool IsUnderCaptivePortal(NetworkStateInformer::State state,
203 ErrorScreenActor::ErrorReason reason) {
204 return state == NetworkStateInformer::CAPTIVE_PORTAL ||
205 reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED;
208 bool IsProxyError(NetworkStateInformer::State state,
209 ErrorScreenActor::ErrorReason reason,
210 net::Error frame_error) {
211 return state == NetworkStateInformer::PROXY_AUTH_REQUIRED ||
212 reason == ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED ||
213 reason == ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED ||
214 (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
215 (frame_error == net::ERR_PROXY_CONNECTION_FAILED ||
216 frame_error == net::ERR_TUNNEL_CONNECTION_FAILED));
219 bool IsSigninScreen(const OobeUI::Screen screen) {
220 return screen == OobeUI::SCREEN_GAIA_SIGNIN ||
221 screen == OobeUI::SCREEN_ACCOUNT_PICKER;
224 bool IsSigninScreenError(ErrorScreen::ErrorState error_state) {
225 return error_state == ErrorScreen::ERROR_STATE_PORTAL ||
226 error_state == ErrorScreen::ERROR_STATE_OFFLINE ||
227 error_state == ErrorScreen::ERROR_STATE_PROXY ||
228 error_state == ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
231 // Returns network name by service path.
232 std::string GetNetworkName(const std::string& service_path) {
233 const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
234 GetNetworkState(service_path);
236 return std::string();
237 return network->name();
240 // Returns captive portal state for a network by its service path.
241 NetworkPortalDetector::CaptivePortalState GetCaptivePortalState(
242 const std::string& service_path) {
243 NetworkPortalDetector* detector = NetworkPortalDetector::Get();
244 const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
245 GetNetworkState(service_path);
246 if (!detector || !network)
247 return NetworkPortalDetector::CaptivePortalState();
248 return detector->GetCaptivePortalState(network);
251 void RecordDiscrepancyWithShill(
252 const NetworkState* network,
253 const NetworkPortalDetector::CaptivePortalStatus status) {
254 if (network->connection_state() == shill::kStateOnline) {
255 UMA_HISTOGRAM_ENUMERATION(
256 "CaptivePortal.OOBE.DiscrepancyWithShill_Online",
258 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
259 } else if (network->connection_state() == shill::kStatePortal) {
260 UMA_HISTOGRAM_ENUMERATION(
261 "CaptivePortal.OOBE.DiscrepancyWithShill_RestrictedPool",
263 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
265 UMA_HISTOGRAM_ENUMERATION(
266 "CaptivePortal.OOBE.DiscrepancyWithShill_Offline",
268 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
272 // Record state and descripancies with shill (e.g. shill thinks that
273 // network is online but NetworkPortalDetector claims that it's behind
274 // portal) for the network identified by |service_path|.
275 void RecordNetworkPortalDetectorStats(const std::string& service_path) {
276 const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
277 GetNetworkState(service_path);
280 NetworkPortalDetector::CaptivePortalState state =
281 GetCaptivePortalState(service_path);
282 if (state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN)
285 UMA_HISTOGRAM_ENUMERATION("CaptivePortal.OOBE.DetectionResult",
287 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
289 switch (state.status) {
290 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
293 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
294 if (network->connection_state() == shill::kStateOnline ||
295 network->connection_state() == shill::kStatePortal)
296 RecordDiscrepancyWithShill(network, state.status);
298 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
299 if (network->connection_state() != shill::kStateOnline)
300 RecordDiscrepancyWithShill(network, state.status);
302 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
303 if (network->connection_state() != shill::kStatePortal)
304 RecordDiscrepancyWithShill(network, state.status);
306 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
307 if (network->connection_state() != shill::kStateOnline)
308 RecordDiscrepancyWithShill(network, state.status);
310 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
316 static bool SetUserInputMethodImpl(
317 const std::string& username,
318 chromeos::input_method::InputMethodManager* manager) {
319 PrefService* const local_state = g_browser_process->local_state();
321 const base::DictionaryValue* users_lru_input_methods =
322 local_state->GetDictionary(prefs::kUsersLRUInputMethod);
324 if (users_lru_input_methods == NULL) {
325 DLOG(WARNING) << "SetUserInputMethod('" << username
326 << "'): no kUsersLRUInputMethod";
330 std::string input_method;
332 if (!users_lru_input_methods->GetStringWithoutPathExpansion(username,
334 DLOG(INFO) << "SetUserInputMethod('" << username
335 << "'): no input method for this user";
339 if (input_method.empty())
342 if (!manager->IsLoginKeyboard(input_method)) {
343 LOG(WARNING) << "SetUserInputMethod('" << username
344 << "'): stored user LRU input method '" << input_method
345 << "' is no longer Full Latin Keyboard Language"
346 << " (entry dropped). Use hardware default instead.";
348 DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
350 base::DictionaryValue* const users_lru_input_methods = updater.Get();
351 if (users_lru_input_methods != NULL) {
352 users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
357 if (!Contains(manager->GetActiveInputMethodIds(), input_method)) {
358 if (!manager->EnableInputMethod(input_method)) {
359 DLOG(ERROR) << "SigninScreenHandler::SetUserInputMethod('" << username
360 << "'): user input method '" << input_method
361 << "' is not enabled and enabling failed (ignored!).";
364 manager->ChangeInputMethod(input_method);
371 // SigninScreenHandler implementation ------------------------------------------
373 SigninScreenHandler::SigninScreenHandler(
374 const scoped_refptr<NetworkStateInformer>& network_state_informer,
375 ErrorScreenActor* error_screen_actor,
376 CoreOobeActor* core_oobe_actor)
377 : ui_state_(UI_STATE_UNKNOWN),
378 frame_state_(FRAME_STATE_UNKNOWN),
379 frame_error_(net::OK),
381 native_window_delegate_(NULL),
382 show_on_init_(false),
384 focus_stolen_(false),
385 gaia_silent_load_(false),
386 is_account_picker_showing_first_time_(false),
388 dns_clear_task_running_(false),
389 cookies_cleared_(false),
390 network_state_informer_(network_state_informer),
391 test_expects_complete_login_(false),
393 webui_visible_(false),
394 preferences_changed_delayed_(false),
395 error_screen_actor_(error_screen_actor),
396 core_oobe_actor_(core_oobe_actor),
397 is_first_update_state_call_(true),
398 offline_login_active_(false),
399 last_network_state_(NetworkStateInformer::UNKNOWN),
400 has_pending_auth_ui_(false),
401 wait_for_auto_enrollment_check_(false) {
402 DCHECK(network_state_informer_.get());
403 DCHECK(error_screen_actor_);
404 DCHECK(core_oobe_actor_);
405 network_state_informer_->AddObserver(this);
406 allow_new_user_subscription_ = CrosSettings::Get()->AddSettingsObserver(
407 kAccountsPrefAllowNewUser,
408 base::Bind(&SigninScreenHandler::UserSettingsChanged,
409 base::Unretained(this)));
410 allow_guest_subscription_ = CrosSettings::Get()->AddSettingsObserver(
411 kAccountsPrefAllowGuest,
412 base::Bind(&SigninScreenHandler::UserSettingsChanged,
413 base::Unretained(this)));
416 chrome::NOTIFICATION_AUTH_NEEDED,
417 content::NotificationService::AllSources());
419 chrome::NOTIFICATION_AUTH_SUPPLIED,
420 content::NotificationService::AllSources());
422 chrome::NOTIFICATION_AUTH_CANCELLED,
423 content::NotificationService::AllSources());
426 SigninScreenHandler::~SigninScreenHandler() {
427 weak_factory_.InvalidateWeakPtrs();
428 SystemKeyEventListener* key_event_listener =
429 SystemKeyEventListener::GetInstance();
430 if (key_event_listener)
431 key_event_listener->RemoveCapsLockObserver(this);
433 delegate_->SetWebUIHandler(NULL);
434 network_state_informer_->RemoveObserver(this);
437 void SigninScreenHandler::DeclareLocalizedValues(
438 LocalizedValuesBuilder* builder) {
439 builder->Add("signinScreenTitle", IDS_SIGNIN_SCREEN_TITLE);
440 builder->Add("signinScreenPasswordChanged",
441 IDS_SIGNIN_SCREEN_PASSWORD_CHANGED);
442 builder->Add("passwordHint", IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT);
443 builder->Add("podMenuButtonAccessibleName",
444 IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME);
445 builder->Add("podMenuRemoveItemAccessibleName",
446 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME);
447 builder->Add("passwordFieldAccessibleName",
448 IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME);
449 builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER);
450 builder->Add("signinButton", IDS_LOGIN_BUTTON);
451 builder->Add("shutDown", IDS_SHUTDOWN_BUTTON);
452 builder->Add("addUser", IDS_ADD_USER_BUTTON);
453 builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON);
454 builder->Add("cancel", IDS_CANCEL);
455 builder->Add("signOutUser", IDS_SCREEN_LOCK_SIGN_OUT);
456 builder->Add("createAccount", IDS_CREATE_ACCOUNT_HTML);
457 builder->Add("guestSignin", IDS_BROWSE_WITHOUT_SIGNING_IN_HTML);
458 builder->Add("createLocallyManagedUser",
459 IDS_CREATE_LOCALLY_MANAGED_USER_HTML);
460 builder->Add("createManagedUserFeatureName",
461 IDS_CREATE_LOCALLY_MANAGED_USER_FEATURE_NAME);
462 builder->Add("offlineLogin", IDS_OFFLINE_LOGIN_HTML);
463 builder->Add("ownerUserPattern", IDS_LOGIN_POD_OWNER_USER);
464 builder->Add("removeUser", IDS_LOGIN_POD_REMOVE_USER);
465 builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE);
466 builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT);
467 builder->Add("errorTpmFailureRebootButton",
468 IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON);
470 "disabledAddUserTooltip",
471 g_browser_process->browser_policy_connector()->IsEnterpriseManaged() ?
472 IDS_DISABLED_ADD_USER_TOOLTIP_ENTERPRISE :
473 IDS_DISABLED_ADD_USER_TOOLTIP);
474 builder->Add("supervisedUserExpiredTokenWarning",
475 IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING);
476 builder->Add("multiple-signin-banner-text", IDS_LOGIN_USER_ADDING_BANNER);
478 // Strings used by password changed dialog.
479 builder->Add("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE);
480 builder->Add("passwordChangedDesc", IDS_LOGIN_PASSWORD_CHANGED_DESC);
481 builder->AddF("passwordChangedMoreInfo",
482 IDS_LOGIN_PASSWORD_CHANGED_MORE_INFO,
483 IDS_SHORT_PRODUCT_OS_NAME);
485 builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT);
486 builder->Add("oldPasswordIncorrect",
487 IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD);
488 builder->Add("passwordChangedCantRemember",
489 IDS_LOGIN_PASSWORD_CHANGED_CANT_REMEMBER);
490 builder->Add("passwordChangedBackButton",
491 IDS_LOGIN_PASSWORD_CHANGED_BACK_BUTTON);
492 builder->Add("passwordChangedsOkButton", IDS_OK);
493 builder->Add("passwordChangedProceedAnyway",
494 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY);
495 builder->Add("proceedAnywayButton",
496 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON);
497 builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT);
498 builder->Add("publicAccountReminder",
499 IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER);
500 builder->Add("publicAccountEnter", IDS_LOGIN_PUBLIC_ACCOUNT_ENTER);
501 builder->Add("publicAccountEnterAccessibleName",
502 IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME);
503 builder->AddF("removeUserWarningText",
504 IDS_LOGIN_POD_USER_REMOVE_WARNING,
505 UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
506 builder->Add("removeUserWarningButtonTitle",
507 IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON);
509 // Strings used by confirm password dialog.
510 builder->Add("confirmPasswordTitle", IDS_LOGIN_CONFIRM_PASSWORD_TITLE);
511 builder->Add("confirmPasswordHint", IDS_LOGIN_CONFIRM_PASSWORD_HINT);
512 builder->Add("confirmPasswordConfirmButton",
513 IDS_LOGIN_CONFIRM_PASSWORD_CONFIRM_BUTTON);
515 // Strings used by no password warning dialog.
516 builder->Add("noPasswordWarningTitle", IDS_LOGIN_NO_PASSWORD_WARNING_TITLE);
517 builder->Add("noPasswordWarningBody", IDS_LOGIN_NO_PASSWORD_WARNING);
518 builder->Add("noPasswordWarningOkButton",
519 IDS_LOGIN_NO_PASSWORD_WARNING_DISMISS_BUTTON);
521 if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
522 builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE);
525 void SigninScreenHandler::Show(bool oobe_ui) {
528 if (!page_is_ready()) {
529 show_on_init_ = true;
534 // Shows new user sign-in for OOBE.
535 HandleShowAddUser(NULL);
537 // Populates account picker. Animation is turned off for now until we
538 // figure out how to make it fast enough.
541 // Reset Caps Lock state when login screen is shown.
542 input_method::InputMethodManager::Get()->GetXKeyboard()->
543 SetCapsLockEnabled(false);
545 DictionaryValue params;
546 params.SetBoolean("disableAddUser", AllWhitelistedUsersPresent());
547 UpdateUIState(UI_STATE_ACCOUNT_PICKER, ¶ms);
551 void SigninScreenHandler::ShowRetailModeLoginSpinner() {
552 CallJS("showLoginSpinner");
555 void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) {
556 delegate_ = delegate;
558 delegate_->SetWebUIHandler(this);
561 void SigninScreenHandler::SetNativeWindowDelegate(
562 NativeWindowDelegate* native_window_delegate) {
563 native_window_delegate_ = native_window_delegate;
566 void SigninScreenHandler::OnNetworkReady() {
567 MaybePreloadAuthExtension();
570 void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
571 UpdateStateInternal(reason, false);
574 // SigninScreenHandler, private: -----------------------------------------------
576 void SigninScreenHandler::UpdateUIState(UIState ui_state,
577 DictionaryValue* params) {
579 case UI_STATE_GAIA_SIGNIN:
580 ui_state_ = UI_STATE_GAIA_SIGNIN;
581 ShowScreen(OobeUI::kScreenGaiaSignin, params);
583 case UI_STATE_ACCOUNT_PICKER:
584 ui_state_ = UI_STATE_ACCOUNT_PICKER;
585 ShowScreen(OobeUI::kScreenAccountPicker, params);
593 // TODO (ygorshenin@): split this method into small parts.
594 void SigninScreenHandler::UpdateStateInternal(
595 ErrorScreenActor::ErrorReason reason,
597 // Do nothing once user has signed in or sign in is in progress.
598 // TODO(ygorshenin): We will end up here when processing network state
599 // notification but no ShowSigninScreen() was called so delegate_ will be
600 // NULL. Network state processing logic does not belong here.
602 (delegate_->IsUserSigninCompleted() || delegate_->IsSigninInProgress())) {
606 NetworkStateInformer::State state = network_state_informer_->state();
607 const std::string network_path = network_state_informer_->network_path();
608 const std::string network_name = GetNetworkName(network_path);
610 // Skip "update" notification about OFFLINE state from
611 // NetworkStateInformer if previous notification already was
613 if ((state == NetworkStateInformer::OFFLINE || has_pending_auth_ui_) &&
615 !update_state_closure_.IsCancelled()) {
619 // TODO (ygorshenin@): switch log level to INFO once signin screen
620 // will be tested well.
621 LOG(WARNING) << "SigninScreenHandler::UpdateStateInternal(): "
622 << "state=" << NetworkStateStatusString(state) << ", "
623 << "network_name=" << network_name << ", "
624 << "reason=" << ErrorReasonString(reason) << ", "
625 << "force_update=" << force_update;
626 update_state_closure_.Cancel();
628 if ((state == NetworkStateInformer::OFFLINE && !force_update) ||
629 has_pending_auth_ui_) {
630 update_state_closure_.Reset(
632 &SigninScreenHandler::UpdateStateInternal,
633 weak_factory_.GetWeakPtr(), reason, true));
634 base::MessageLoop::current()->PostDelayedTask(
636 update_state_closure_.callback(),
637 base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
641 // Don't show or hide error screen if we're in connecting state.
642 if (state == NetworkStateInformer::CONNECTING && !force_update) {
643 if (connecting_closure_.IsCancelled()) {
644 // First notification about CONNECTING state.
645 connecting_closure_.Reset(
646 base::Bind(&SigninScreenHandler::UpdateStateInternal,
647 weak_factory_.GetWeakPtr(), reason, true));
648 base::MessageLoop::current()->PostDelayedTask(
650 connecting_closure_.callback(),
651 base::TimeDelta::FromSeconds(kConnectingTimeoutSec));
655 connecting_closure_.Cancel();
657 const bool is_online = IsOnline(state, reason);
658 const bool is_under_captive_portal = IsUnderCaptivePortal(state, reason);
659 const bool is_gaia_loading_timeout =
660 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
661 const bool is_gaia_error = frame_error_ != net::OK &&
662 frame_error_ != net::ERR_NETWORK_CHANGED;
663 const bool is_gaia_signin = IsGaiaVisible() || IsGaiaHiddenByError();
664 const bool error_screen_should_overlay =
665 !offline_login_active_ && IsGaiaVisible();
666 const bool from_not_online_to_online_transition =
667 is_online && last_network_state_ != NetworkStateInformer::ONLINE;
668 last_network_state_ = state;
670 if (is_online || !is_under_captive_portal)
671 error_screen_actor_->HideCaptivePortal();
673 // Hide offline message (if needed) and return if current screen is
675 if (!is_gaia_signin) {
676 if (!IsSigninScreenHiddenByError())
677 HideOfflineMessage(state, reason);
681 // Reload frame if network state is changed from {!ONLINE} -> ONLINE state.
682 if (reason == ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED &&
683 from_not_online_to_online_transition) {
684 // Schedules a immediate retry.
685 LOG(WARNING) << "Retry page load since network has been changed.";
689 if (reason == ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED &&
690 error_screen_should_overlay) {
691 // Schedules a immediate retry.
692 LOG(WARNING) << "Retry page load since proxy settings has been changed.";
696 if (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
697 !IsProxyError(state, reason, frame_error_)) {
698 LOG(WARNING) << "Retry page load due to reason: "
699 << ErrorReasonString(reason);
703 if ((!is_online || is_gaia_loading_timeout || is_gaia_error) &&
704 !offline_login_active_) {
705 SetupAndShowOfflineMessage(state, reason);
707 HideOfflineMessage(state, reason);
711 void SigninScreenHandler::SetupAndShowOfflineMessage(
712 NetworkStateInformer:: State state,
713 ErrorScreenActor::ErrorReason reason) {
714 const std::string network_path = network_state_informer_->network_path();
715 const bool is_under_captive_portal = IsUnderCaptivePortal(state, reason);
716 const bool is_proxy_error = IsProxyError(state, reason, frame_error_);
717 const bool is_gaia_loading_timeout =
718 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
720 // Record portal detection stats only if we're going to show or
721 // change state of the error screen.
722 RecordNetworkPortalDetectorStats(network_path);
724 if (is_proxy_error) {
725 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
727 } else if (is_under_captive_portal) {
728 // Do not bother a user with obsessive captive portal showing. This
729 // check makes captive portal being shown only once: either when error
730 // screen is shown for the first time or when switching from another
731 // error screen (offline, proxy).
732 if (IsGaiaVisible() ||
733 (error_screen_actor_->error_state() !=
734 ErrorScreen::ERROR_STATE_PORTAL)) {
735 error_screen_actor_->FixCaptivePortal();
737 const std::string network_name = GetNetworkName(network_path);
738 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
740 } else if (is_gaia_loading_timeout) {
741 error_screen_actor_->SetErrorState(
742 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT, std::string());
744 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
748 const bool guest_signin_allowed = IsGuestSigninAllowed() &&
749 IsSigninScreenError(error_screen_actor_->error_state());
750 error_screen_actor_->AllowGuestSignin(guest_signin_allowed);
752 const bool offline_login_allowed = IsOfflineLoginAllowed() &&
753 IsSigninScreenError(error_screen_actor_->error_state()) &&
754 error_screen_actor_->error_state() !=
755 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
756 error_screen_actor_->AllowOfflineLogin(offline_login_allowed);
758 if (GetCurrentScreen() != OobeUI::SCREEN_ERROR_MESSAGE) {
759 DictionaryValue params;
760 const std::string network_type = network_state_informer_->network_type();
761 params.SetString("lastNetworkType", network_type);
762 error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_SIGNIN);
763 error_screen_actor_->Show(OobeUI::SCREEN_GAIA_SIGNIN, ¶ms);
767 void SigninScreenHandler::HideOfflineMessage(
768 NetworkStateInformer::State state,
769 ErrorScreenActor::ErrorReason reason) {
770 if (!IsSigninScreenHiddenByError())
773 error_screen_actor_->Hide();
775 // Forces a reload for Gaia screen on hiding error message.
776 if (IsGaiaVisible() || IsGaiaHiddenByError())
780 void SigninScreenHandler::ReloadGaiaScreen() {
781 if (frame_state_ == FRAME_STATE_LOADING)
783 NetworkStateInformer::State state = network_state_informer_->state();
784 if (state != NetworkStateInformer::ONLINE) {
785 LOG(WARNING) << "Skipping reload of auth extension frame since "
786 << "network state=" << NetworkStateStatusString(state);
789 LOG(WARNING) << "Reload auth extension frame.";
790 frame_state_ = FRAME_STATE_LOADING;
791 CallJS("login.GaiaSigninScreen.doReload");
794 void SigninScreenHandler::Initialize() {
795 // If delegate_ is NULL here (e.g. WebUIScreenLocker has been destroyed),
796 // don't do anything, just return.
800 // Register for Caps Lock state change notifications;
801 SystemKeyEventListener* key_event_listener =
802 SystemKeyEventListener::GetInstance();
803 if (key_event_listener)
804 key_event_listener->AddCapsLockObserver(this);
807 show_on_init_ = false;
812 gfx::NativeWindow SigninScreenHandler::GetNativeWindow() {
813 if (native_window_delegate_)
814 return native_window_delegate_->GetNativeWindow();
818 void SigninScreenHandler::RegisterMessages() {
819 AddCallback("authenticateUser", &SigninScreenHandler::HandleAuthenticateUser);
820 AddCallback("completeLogin", &SigninScreenHandler::HandleCompleteLogin);
821 AddCallback("completeAuthentication",
822 &SigninScreenHandler::HandleCompleteAuthentication);
823 AddCallback("getUsers", &SigninScreenHandler::HandleGetUsers);
824 AddCallback("launchDemoUser", &SigninScreenHandler::HandleLaunchDemoUser);
825 AddCallback("launchIncognito", &SigninScreenHandler::HandleLaunchIncognito);
826 AddCallback("showLocallyManagedUserCreationScreen",
827 &SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen);
828 AddCallback("launchPublicAccount",
829 &SigninScreenHandler::HandleLaunchPublicAccount);
830 AddRawCallback("offlineLogin", &SigninScreenHandler::HandleOfflineLogin);
831 AddCallback("rebootSystem", &SigninScreenHandler::HandleRebootSystem);
832 AddRawCallback("showAddUser", &SigninScreenHandler::HandleShowAddUser);
833 AddCallback("shutdownSystem", &SigninScreenHandler::HandleShutdownSystem);
834 AddCallback("loadWallpaper", &SigninScreenHandler::HandleLoadWallpaper);
835 AddCallback("removeUser", &SigninScreenHandler::HandleRemoveUser);
836 AddCallback("toggleEnrollmentScreen",
837 &SigninScreenHandler::HandleToggleEnrollmentScreen);
838 AddCallback("toggleKioskEnableScreen",
839 &SigninScreenHandler::HandleToggleKioskEnableScreen);
840 AddCallback("toggleResetScreen",
841 &SigninScreenHandler::HandleToggleResetScreen);
842 AddCallback("launchHelpApp", &SigninScreenHandler::HandleLaunchHelpApp);
843 AddCallback("createAccount", &SigninScreenHandler::HandleCreateAccount);
844 AddCallback("accountPickerReady",
845 &SigninScreenHandler::HandleAccountPickerReady);
846 AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady);
847 AddCallback("loginWebuiReady", &SigninScreenHandler::HandleLoginWebuiReady);
848 AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser);
849 AddCallback("networkErrorShown",
850 &SigninScreenHandler::HandleNetworkErrorShown);
851 AddCallback("openProxySettings",
852 &SigninScreenHandler::HandleOpenProxySettings);
853 AddCallback("loginVisible", &SigninScreenHandler::HandleLoginVisible);
854 AddCallback("cancelPasswordChangedFlow",
855 &SigninScreenHandler::HandleCancelPasswordChangedFlow);
856 AddCallback("cancelUserAdding",
857 &SigninScreenHandler::HandleCancelUserAdding);
858 AddCallback("migrateUserData", &SigninScreenHandler::HandleMigrateUserData);
859 AddCallback("resyncUserData", &SigninScreenHandler::HandleResyncUserData);
860 AddCallback("loginUIStateChanged",
861 &SigninScreenHandler::HandleLoginUIStateChanged);
862 AddCallback("unlockOnLoginSuccess",
863 &SigninScreenHandler::HandleUnlockOnLoginSuccess);
864 AddCallback("frameLoadingCompleted",
865 &SigninScreenHandler::HandleFrameLoadingCompleted);
866 AddCallback("showLoadingTimeoutError",
867 &SigninScreenHandler::HandleShowLoadingTimeoutError);
868 AddCallback("updateOfflineLogin",
869 &SigninScreenHandler::HandleUpdateOfflineLogin);
870 AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod);
872 // This message is sent by the kiosk app menu, but is handled here
873 // so we can tell the delegate to launch the app.
874 AddCallback("launchKioskApp", &SigninScreenHandler::HandleLaunchKioskApp);
877 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
878 registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
881 void SigninScreenHandler::HandleGetUsers() {
885 void SigninScreenHandler::ClearAndEnablePassword() {
886 core_oobe_actor_->ResetSignInUI(false);
889 void SigninScreenHandler::ClearUserPodPassword() {
890 core_oobe_actor_->ClearUserPodPassword();
893 void SigninScreenHandler::RefocusCurrentPod() {
894 core_oobe_actor_->RefocusCurrentPod();
897 void SigninScreenHandler::OnLoginSuccess(const std::string& username) {
898 core_oobe_actor_->OnLoginSuccess(username);
901 void SigninScreenHandler::OnUserRemoved(const std::string& username) {
905 void SigninScreenHandler::OnUserImageChanged(const User& user) {
907 CallJS("login.AccountPickerScreen.updateUserImage", user.email());
910 void SigninScreenHandler::OnPreferencesChanged() {
911 // Make sure that one of the login UI is fully functional now, otherwise
912 // preferences update would be picked up next time it will be shown.
913 if (!webui_visible_) {
914 LOG(WARNING) << "Login UI is not active - postponed prefs change.";
915 preferences_changed_delayed_ = true;
919 if (delegate_ && !delegate_->IsShowUsers()) {
920 HandleShowAddUser(NULL);
923 UpdateUIState(UI_STATE_ACCOUNT_PICKER, NULL);
925 preferences_changed_delayed_ = false;
928 void SigninScreenHandler::ResetSigninScreenHandlerDelegate() {
932 void SigninScreenHandler::ShowError(int login_attempts,
933 const std::string& error_text,
934 const std::string& help_link_text,
935 HelpAppLauncher::HelpTopic help_topic_id) {
936 core_oobe_actor_->ShowSignInError(login_attempts, error_text, help_link_text,
940 void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) {
942 case LoginDisplay::TPM_ERROR:
943 core_oobe_actor_->ShowTpmError();
946 NOTREACHED() << "Unknown sign in error";
951 void SigninScreenHandler::ShowSigninUI(const std::string& email) {
952 core_oobe_actor_->ShowSignInUI(email);
955 void SigninScreenHandler::ShowGaiaPasswordChanged(const std::string& username) {
957 password_changed_for_.insert(email_);
958 core_oobe_actor_->ShowSignInUI(email_);
959 CallJS("login.AccountPickerScreen.updateUserGaiaNeeded", email_);
962 void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) {
963 core_oobe_actor_->ShowPasswordChangedScreen(show_password_error);
966 void SigninScreenHandler::ShowSigninScreenForCreds(
967 const std::string& username,
968 const std::string& password) {
969 VLOG(2) << "ShowSigninScreenForCreds for user " << username
970 << ", frame_state=" << frame_state_;
972 test_user_ = username;
973 test_pass_ = password;
974 test_expects_complete_login_ = true;
976 // Submit login form for test if gaia is ready. If gaia is loading, login
977 // will be attempted in HandleLoginWebuiReady after gaia is ready. Otherwise,
978 // reload gaia then follow the loading case.
979 if (frame_state_ == FRAME_STATE_LOADED)
980 SubmitLoginFormForTest();
981 else if (frame_state_ != FRAME_STATE_LOADING)
982 HandleShowAddUser(NULL);
985 void SigninScreenHandler::OnCookiesCleared(base::Closure on_clear_callback) {
986 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
987 cookies_cleared_ = true;
988 on_clear_callback.Run();
991 void SigninScreenHandler::OnCapsLockChange(bool enabled) {
993 CallJS("login.AccountPickerScreen.setCapsLockState", enabled);
996 void SigninScreenHandler::Observe(int type,
997 const content::NotificationSource& source,
998 const content::NotificationDetails& details) {
1000 case chrome::NOTIFICATION_AUTH_NEEDED: {
1001 has_pending_auth_ui_ = true;
1004 case chrome::NOTIFICATION_AUTH_SUPPLIED:
1005 has_pending_auth_ui_ = false;
1006 if (IsSigninScreenHiddenByError()) {
1007 // Hide error screen and reload auth extension.
1008 HideOfflineMessage(network_state_informer_->state(),
1009 ErrorScreenActor::ERROR_REASON_PROXY_AUTH_SUPPLIED);
1010 } else if (ui_state_ == UI_STATE_GAIA_SIGNIN) {
1011 // Reload auth extension as proxy credentials are supplied.
1015 case chrome::NOTIFICATION_AUTH_CANCELLED: {
1016 // Don't reload auth extension if proxy auth dialog was cancelled.
1017 has_pending_auth_ui_ = false;
1021 NOTREACHED() << "Unexpected notification " << type;
1025 void SigninScreenHandler::OnDnsCleared() {
1026 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1027 dns_clear_task_running_ = false;
1028 dns_cleared_ = true;
1029 ShowSigninScreenIfReady();
1032 // Update keyboard layout to least recently used by the user.
1033 void SigninScreenHandler::SetUserInputMethod(const std::string& username) {
1034 UserManager* user_manager = UserManager::Get();
1035 if (user_manager->IsUserLoggedIn()) {
1036 // We are on sign-in screen inside user session (adding new user to
1037 // the session or on lock screen), don't switch input methods in this case.
1038 // TODO(dpolukhin): adding user and sign-in should be consistent
1043 chromeos::input_method::InputMethodManager* const manager =
1044 chromeos::input_method::InputMethodManager::Get();
1046 const bool succeed = SetUserInputMethodImpl(username, manager);
1048 // This is also a case when LRU layout is set only for a few local users,
1049 // thus others need to be switched to default locale.
1050 // Otherwise they will end up using another user's locale to log in.
1052 DLOG(INFO) << "SetUserInputMethod('" << username
1053 << "'): failed to set user layout. Switching to default.";
1055 manager->SetInputMethodDefault();
1059 void SigninScreenHandler::ShowSigninScreenIfReady() {
1060 if (!dns_cleared_ || !cookies_cleared_ || !delegate_)
1063 std::string active_network_path = network_state_informer_->network_path();
1064 if (gaia_silent_load_ &&
1065 (network_state_informer_->state() != NetworkStateInformer::ONLINE ||
1066 gaia_silent_load_network_ != active_network_path)) {
1067 // Network has changed. Force Gaia reload.
1068 gaia_silent_load_ = false;
1069 // Gaia page will be realoded, so focus isn't stolen anymore.
1070 focus_stolen_ = false;
1073 // Note that LoadAuthExtension clears |email_|.
1075 delegate_->LoadSigninWallpaper();
1077 delegate_->LoadWallpaper(email_);
1079 // Set Least Recently Used input method for the user.
1080 if (!email_.empty())
1081 SetUserInputMethod(email_);
1083 LoadAuthExtension(!gaia_silent_load_, false, false);
1084 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
1086 if (gaia_silent_load_) {
1087 // The variable is assigned to false because silently loaded Gaia page was
1089 gaia_silent_load_ = false;
1091 HandleLoginWebuiReady();
1094 UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
1098 void SigninScreenHandler::UpdateAuthParams(DictionaryValue* params) {
1102 UpdateAuthParamsFromSettings(params, CrosSettings::Get());
1104 // Allow locally managed user creation only if:
1105 // 1. Enterprise managed device > is allowed by policy.
1106 // 2. Consumer device > owner exists.
1107 // 3. New users are allowed by owner.
1109 CrosSettings* cros_settings = CrosSettings::Get();
1110 bool allow_new_user = false;
1111 cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
1113 bool managed_users_allowed =
1114 UserManager::Get()->AreLocallyManagedUsersAllowed();
1115 bool managed_users_can_create = true;
1116 int message_id = -1;
1117 if (delegate_->GetUsers().size() == 0) {
1118 managed_users_can_create = false;
1119 message_id = IDS_CREATE_LOCALLY_MANAGED_USER_NO_MANAGER_TEXT;
1121 if (!allow_new_user) {
1122 managed_users_can_create = false;
1123 message_id = IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_RESTRICTED_TEXT;
1126 params->SetBoolean("managedUsersEnabled", managed_users_allowed);
1127 params->SetBoolean("managedUsersCanCreate", managed_users_can_create);
1128 if (!managed_users_can_create) {
1129 params->SetString("managedUsersRestrictionReason",
1130 l10n_util::GetStringUTF16(message_id));
1134 void SigninScreenHandler::LoadAuthExtension(
1135 bool force, bool silent_load, bool offline) {
1136 DictionaryValue params;
1138 params.SetBoolean("forceReload", force);
1139 params.SetBoolean("silentLoad", silent_load);
1140 params.SetBoolean("isLocal", offline);
1141 params.SetBoolean("passwordChanged",
1142 !email_.empty() && password_changed_for_.count(email_));
1144 params.SetBoolean("isShowUsers", delegate_->IsShowUsers());
1145 params.SetBoolean("useOffline", offline);
1146 params.SetString("email", email_);
1149 UpdateAuthParams(¶ms);
1152 const std::string app_locale = g_browser_process->GetApplicationLocale();
1153 if (!app_locale.empty())
1154 params.SetString("hl", app_locale);
1156 base::DictionaryValue *localized_strings = new base::DictionaryValue();
1157 localized_strings->SetString("stringEmail",
1158 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMAIL));
1159 localized_strings->SetString("stringPassword",
1160 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_PASSWORD));
1161 localized_strings->SetString("stringSignIn",
1162 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_SIGNIN));
1163 localized_strings->SetString("stringEmptyEmail",
1164 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMPTY_EMAIL));
1165 localized_strings->SetString("stringEmptyPassword",
1166 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_EMPTY_PASSWORD));
1167 localized_strings->SetString("stringError",
1168 l10n_util::GetStringUTF16(IDS_LOGIN_OFFLINE_ERROR));
1169 params.Set("localizedStrings", localized_strings);
1172 const GURL gaia_url =
1173 CommandLine::ForCurrentProcess()->HasSwitch(::switches::kGaiaUrl) ?
1174 GURL(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
1175 ::switches::kGaiaUrl)) :
1176 GaiaUrls::GetInstance()->gaia_url();
1177 params.SetString("gaiaUrl", gaia_url.spec());
1179 frame_state_ = FRAME_STATE_LOADING;
1180 CallJS("login.GaiaSigninScreen.loadAuthExtension", params);
1183 void SigninScreenHandler::UserSettingsChanged() {
1184 UpdateAuthExtension();
1185 UpdateAddButtonStatus();
1188 void SigninScreenHandler::UpdateAuthExtension() {
1189 DictionaryValue params;
1190 UpdateAuthParams(¶ms);
1191 CallJS("login.GaiaSigninScreen.updateAuthExtension", params);
1194 void SigninScreenHandler::UpdateAddButtonStatus() {
1195 CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus",
1196 AllWhitelistedUsersPresent());
1199 void SigninScreenHandler::HandleCompleteLogin(const std::string& typed_email,
1200 const std::string& password) {
1203 const std::string sanitized_email = gaia::SanitizeEmail(typed_email);
1204 delegate_->SetDisplayEmail(sanitized_email);
1205 delegate_->CompleteLogin(UserContext(sanitized_email,
1207 std::string())); // auth_code
1209 if (test_expects_complete_login_) {
1210 VLOG(2) << "Complete test login for " << typed_email
1211 << ", requested=" << test_user_;
1213 test_expects_complete_login_ = false;
1219 void SigninScreenHandler::HandleCompleteAuthentication(
1220 const std::string& email,
1221 const std::string& password,
1222 const std::string& auth_code) {
1225 const std::string sanitized_email = gaia::SanitizeEmail(email);
1226 delegate_->SetDisplayEmail(sanitized_email);
1227 delegate_->CompleteLogin(UserContext(sanitized_email, password, auth_code));
1230 void SigninScreenHandler::HandleAuthenticateUser(const std::string& username,
1231 const std::string& password) {
1234 delegate_->Login(UserContext(gaia::SanitizeEmail(username),
1236 std::string())); // auth_code
1239 void SigninScreenHandler::HandleLaunchDemoUser() {
1241 delegate_->LoginAsRetailModeUser();
1244 void SigninScreenHandler::HandleLaunchIncognito() {
1246 delegate_->LoginAsGuest();
1249 void SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen() {
1250 if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
1251 LOG(ERROR) << "Managed users not allowed.";
1254 scoped_ptr<DictionaryValue> params(new DictionaryValue());
1255 LoginDisplayHostImpl::default_host()->
1256 StartWizard(WizardController::kLocallyManagedUserCreationScreenName,
1260 void SigninScreenHandler::HandleLaunchPublicAccount(
1261 const std::string& username) {
1263 delegate_->LoginAsPublicAccount(username);
1266 void SigninScreenHandler::HandleOfflineLogin(const base::ListValue* args) {
1267 if (!delegate_ || delegate_->IsShowUsers()) {
1271 if (!args->GetString(0, &email_))
1273 // Load auth extension. Parameters are: force reload, do not load extension in
1274 // background, use offline version.
1275 LoadAuthExtension(true, false, true);
1276 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
1279 void SigninScreenHandler::HandleShutdownSystem() {
1280 ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
1283 void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) {
1285 delegate_->LoadWallpaper(email);
1288 void SigninScreenHandler::HandleRebootSystem() {
1289 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
1292 void SigninScreenHandler::HandleRemoveUser(const std::string& email) {
1295 delegate_->RemoveUser(email);
1296 UpdateAddButtonStatus();
1299 void SigninScreenHandler::HandleShowAddUser(const base::ListValue* args) {
1301 // |args| can be null if it's OOBE.
1303 args->GetString(0, &email_);
1304 is_account_picker_showing_first_time_ = false;
1306 if (gaia_silent_load_ && email_.empty()) {
1307 dns_cleared_ = true;
1308 cookies_cleared_ = true;
1309 ShowSigninScreenIfReady();
1311 StartClearingDnsCache();
1312 StartClearingCookies(base::Bind(
1313 &SigninScreenHandler::ShowSigninScreenIfReady,
1314 weak_factory_.GetWeakPtr()));
1318 void SigninScreenHandler::HandleToggleEnrollmentScreen() {
1320 delegate_->ShowEnterpriseEnrollmentScreen();
1323 void SigninScreenHandler::HandleToggleKioskEnableScreen() {
1325 !wait_for_auto_enrollment_check_ &&
1326 !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
1327 wait_for_auto_enrollment_check_ = true;
1329 LoginDisplayHostImpl::default_host()->GetAutoEnrollmentCheckResult(
1330 base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow,
1331 weak_factory_.GetWeakPtr()));
1335 void SigninScreenHandler::HandleToggleResetScreen() {
1337 !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
1338 delegate_->ShowResetScreen();
1342 void SigninScreenHandler::HandleToggleKioskAutolaunchScreen() {
1344 !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
1345 delegate_->ShowKioskAutolaunchScreen();
1349 void SigninScreenHandler::HandleLaunchHelpApp(double help_topic_id) {
1352 if (!help_app_.get())
1353 help_app_ = new HelpAppLauncher(GetNativeWindow());
1354 help_app_->ShowHelpTopic(
1355 static_cast<HelpAppLauncher::HelpTopic>(help_topic_id));
1358 void SigninScreenHandler::FillUserDictionary(User* user,
1360 DictionaryValue* user_dict) {
1361 const std::string& email = user->email();
1362 bool is_public_account =
1363 user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT;
1364 bool is_locally_managed_user =
1365 user->GetType() == User::USER_TYPE_LOCALLY_MANAGED;
1366 User::OAuthTokenStatus token_status = user->oauth_token_status();
1368 // If supervised user has unknown token status consider that as valid token.
1369 // It will be invalidated inside session in case it has been revoked.
1370 if (is_locally_managed_user &&
1371 token_status == User::OAUTH_TOKEN_STATUS_UNKNOWN) {
1372 token_status = User::OAUTH2_TOKEN_STATUS_VALID;
1375 user_dict->SetString(kKeyUsername, email);
1376 user_dict->SetString(kKeyEmailAddress, user->display_email());
1377 user_dict->SetString(kKeyDisplayName, user->GetDisplayName());
1378 user_dict->SetBoolean(kKeyPublicAccount, is_public_account);
1379 user_dict->SetBoolean(kKeyLocallyManagedUser, is_locally_managed_user);
1380 user_dict->SetInteger(kKeyOauthTokenStatus, token_status);
1381 user_dict->SetBoolean(kKeySignedIn, user->is_logged_in());
1382 user_dict->SetBoolean(kKeyIsOwner, is_owner);
1384 if (is_public_account) {
1385 policy::BrowserPolicyConnector* policy_connector =
1386 g_browser_process->browser_policy_connector();
1388 if (policy_connector->IsEnterpriseManaged()) {
1389 user_dict->SetString(kKeyEnterpriseDomain,
1390 policy_connector->GetEnterpriseDomain());
1395 void SigninScreenHandler::SendUserList(bool animated) {
1399 size_t max_non_owner_users = kMaxUsers - 1;
1400 size_t non_owner_count = 0;
1402 ListValue users_list;
1403 const UserList& users = delegate_->GetUsers();
1405 // TODO(nkostylev): Show optional intro dialog about multi-profiles feature
1406 // based on user preferences. http://crbug.com/230862
1408 // TODO(nkostylev): Move to a separate method in UserManager.
1409 // http://crbug.com/230852
1410 bool is_signin_to_add = LoginDisplayHostImpl::default_host() &&
1411 UserManager::Get()->IsUserLoggedIn();
1413 bool single_user = users.size() == 1;
1414 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
1415 const std::string& email = (*it)->email();
1418 chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
1419 bool is_owner = (email == owner);
1421 if (non_owner_count < max_non_owner_users || is_owner) {
1422 DictionaryValue* user_dict = new DictionaryValue();
1423 FillUserDictionary(*it, is_owner, user_dict);
1424 bool is_public_account =
1425 ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT);
1426 bool signed_in = (*it)->is_logged_in();
1427 // Single user check here is necessary because owner info might not be
1428 // available when running into login screen on first boot.
1429 // See http://crosbug.com/12723
1430 user_dict->SetBoolean(kKeyCanRemove,
1434 !is_public_account &&
1438 users_list.Append(user_dict);
1444 CallJS("login.AccountPickerScreen.loadUsers", users_list, animated,
1445 delegate_->IsShowGuest());
1448 void SigninScreenHandler::HandleAccountPickerReady() {
1449 LOG(INFO) << "Login WebUI >> AccountPickerReady";
1451 if (delegate_ && !ScreenLocker::default_screen_locker() &&
1452 !chromeos::IsMachineHWIDCorrect() &&
1454 delegate_->ShowWrongHWIDScreen();
1458 PrefService* prefs = g_browser_process->local_state();
1459 if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
1460 prefs->SetBoolean(prefs::kFactoryResetRequested, false);
1461 prefs->CommitPendingWrite();
1462 HandleToggleResetScreen();
1466 is_account_picker_showing_first_time_ = true;
1467 MaybePreloadAuthExtension();
1469 if (ScreenLocker::default_screen_locker())
1470 ScreenLocker::default_screen_locker()->delegate()->OnLockWebUIReady();
1473 delegate_->OnSigninScreenReady();
1476 void SigninScreenHandler::HandleWallpaperReady() {
1477 if (ScreenLocker::default_screen_locker()) {
1478 ScreenLocker::default_screen_locker()->delegate()->
1479 OnLockBackgroundDisplayed();
1483 void SigninScreenHandler::HandleLoginWebuiReady() {
1484 if (focus_stolen_) {
1485 // Set focus to the Gaia page.
1486 // TODO(altimofeev): temporary solution, until focus parameters are
1487 // implemented on the Gaia side.
1488 // Do this only once. Any subsequent call would relod GAIA frame.
1489 focus_stolen_ = false;
1490 const char code[] = "gWindowOnLoad();";
1491 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1492 rvh->ExecuteJavascriptInWebFrame(
1493 ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1494 ASCIIToUTF16(code));
1496 if (!gaia_silent_load_) {
1497 content::NotificationService::current()->Notify(
1498 chrome::NOTIFICATION_LOGIN_WEBUI_LOADED,
1499 content::NotificationService::AllSources(),
1500 content::NotificationService::NoDetails());
1502 focus_stolen_ = true;
1503 // Prevent focus stealing by the Gaia page.
1504 // TODO(altimofeev): temporary solution, until focus parameters are
1505 // implemented on the Gaia side.
1506 const char code[] = "var gWindowOnLoad = window.onload; "
1507 "window.onload=function() {};";
1508 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1509 rvh->ExecuteJavascriptInWebFrame(
1510 ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1511 ASCIIToUTF16(code));
1512 // As we could miss and window.onload could already be called, restore
1513 // focus to current pod (see crbug/175243).
1514 RefocusCurrentPod();
1516 HandleFrameLoadingCompleted(0);
1518 if (test_expects_complete_login_)
1519 SubmitLoginFormForTest();
1522 void SigninScreenHandler::HandleSignOutUser() {
1524 delegate_->Signout();
1527 void SigninScreenHandler::HandleNetworkErrorShown() {
1528 content::NotificationService::current()->Notify(
1529 chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
1530 content::NotificationService::AllSources(),
1531 content::NotificationService::NoDetails());
1534 void SigninScreenHandler::HandleCreateAccount() {
1536 delegate_->CreateAccount();
1539 void SigninScreenHandler::HandleOpenProxySettings() {
1540 LoginDisplayHostImpl::default_host()->OpenProxySettings();
1543 void SigninScreenHandler::HandleLoginVisible(const std::string& source) {
1544 LOG(WARNING) << "Login WebUI >> loginVisible, src: " << source << ", "
1545 << "webui_visible_: " << webui_visible_;
1546 if (!webui_visible_) {
1547 // There might be multiple messages from OOBE UI so send notifications after
1548 // the first one only.
1549 content::NotificationService::current()->Notify(
1550 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
1551 content::NotificationService::AllSources(),
1552 content::NotificationService::NoDetails());
1553 TRACE_EVENT_ASYNC_END0(
1554 "ui", "ShowLoginWebUI", LoginDisplayHostImpl::kShowLoginWebUIid);
1556 webui_visible_ = true;
1557 if (preferences_changed_delayed_)
1558 OnPreferencesChanged();
1561 void SigninScreenHandler::HandleCancelPasswordChangedFlow() {
1562 StartClearingCookies(base::Bind(
1563 &SigninScreenHandler::CancelPasswordChangedFlowInternal,
1564 weak_factory_.GetWeakPtr()));
1567 void SigninScreenHandler::HandleCancelUserAdding() {
1569 delegate_->CancelUserAdding();
1572 void SigninScreenHandler::HandleMigrateUserData(
1573 const std::string& old_password) {
1575 delegate_->MigrateUserData(old_password);
1578 void SigninScreenHandler::HandleResyncUserData() {
1580 delegate_->ResyncUserData();
1583 void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source,
1585 LOG(INFO) << "Login WebUI >> active: " << new_value << ", "
1586 << "source: " << source;
1588 if (!KioskAppManager::Get()->GetAutoLaunchApp().empty() &&
1589 KioskAppManager::Get()->IsAutoLaunchRequested()) {
1590 LOG(INFO) << "Showing auto-launch warning";
1591 // On slow devices, the wallpaper animation is not shown initially, so we
1592 // must explicitly load the wallpaper. This is also the case for the
1593 // account-picker and gaia-signin UI states.
1594 delegate_->LoadSigninWallpaper();
1595 HandleToggleKioskAutolaunchScreen();
1599 if (source == kSourceGaiaSignin) {
1600 ui_state_ = UI_STATE_GAIA_SIGNIN;
1601 } else if (source == kSourceAccountPicker) {
1602 ui_state_ = UI_STATE_ACCOUNT_PICKER;
1609 void SigninScreenHandler::HandleUnlockOnLoginSuccess() {
1610 DCHECK(UserManager::Get()->IsUserLoggedIn());
1611 if (ScreenLocker::default_screen_locker())
1612 ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess();
1615 void SigninScreenHandler::HandleFrameLoadingCompleted(int status) {
1616 const net::Error frame_error = static_cast<net::Error>(-status);
1617 if (frame_error == net::ERR_ABORTED) {
1618 LOG(WARNING) << "Ignore gaia frame error: " << frame_error;
1621 frame_error_ = frame_error;
1622 if (frame_error == net::OK) {
1623 LOG(INFO) << "Gaia frame is loaded";
1624 frame_state_ = FRAME_STATE_LOADED;
1626 LOG(WARNING) << "Gaia frame error: " << frame_error_;
1627 frame_state_ = FRAME_STATE_ERROR;
1630 if (network_state_informer_->state() != NetworkStateInformer::ONLINE)
1632 if (frame_state_ == FRAME_STATE_LOADED)
1633 UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
1634 else if (frame_state_ == FRAME_STATE_ERROR)
1635 UpdateState(ErrorScreenActor::ERROR_REASON_FRAME_ERROR);
1638 void SigninScreenHandler::HandleShowLoadingTimeoutError() {
1639 UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
1642 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
1643 offline_login_active_ = offline_login_active;
1646 void SigninScreenHandler::HandleFocusPod(const std::string& user_id) {
1647 SetUserInputMethod(user_id);
1650 void SigninScreenHandler::HandleLaunchKioskApp(const std::string& app_id) {
1651 delegate_->LoginAsKioskApp(app_id);
1654 void SigninScreenHandler::StartClearingDnsCache() {
1655 if (dns_clear_task_running_ || !g_browser_process->io_thread())
1658 dns_cleared_ = false;
1659 BrowserThread::PostTaskAndReply(
1660 BrowserThread::IO, FROM_HERE,
1661 base::Bind(&ClearDnsCache, g_browser_process->io_thread()),
1662 base::Bind(&SigninScreenHandler::OnDnsCleared,
1663 weak_factory_.GetWeakPtr()));
1664 dns_clear_task_running_ = true;
1667 void SigninScreenHandler::StartClearingCookies(
1668 const base::Closure& on_clear_callback) {
1669 cookies_cleared_ = false;
1670 ProfileHelper* profile_helper =
1671 g_browser_process->platform_part()->profile_helper();
1673 Profile::FromWebUI(web_ui()) == profile_helper->GetSigninProfile());
1674 profile_helper->ClearSigninProfile(base::Bind(
1675 &SigninScreenHandler::OnCookiesCleared,
1676 weak_factory_.GetWeakPtr(), on_clear_callback));
1679 void SigninScreenHandler::MaybePreloadAuthExtension() {
1680 // Fetching of the extension is not started before account picker page is
1681 // loaded because it can affect the loading speed. Also if cookies clearing
1682 // was initiated or |dns_clear_task_running_| then auth extension showing has
1683 // already been initiated and preloading is senseless.
1684 // Do not load the extension for the screen locker, see crosbug.com/25018.
1685 if (is_account_picker_showing_first_time_ &&
1686 !gaia_silent_load_ &&
1687 !ScreenLocker::default_screen_locker() &&
1688 !cookies_cleared_ &&
1689 !dns_clear_task_running_ &&
1690 network_state_informer_->state() == NetworkStateInformer::ONLINE) {
1691 gaia_silent_load_ = true;
1692 gaia_silent_load_network_ = network_state_informer_->network_path();
1693 LoadAuthExtension(true, true, false);
1697 bool SigninScreenHandler::AllWhitelistedUsersPresent() {
1698 CrosSettings* cros_settings = CrosSettings::Get();
1699 bool allow_new_user = false;
1700 cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
1703 UserManager* user_manager = UserManager::Get();
1704 const UserList& users = user_manager->GetUsers();
1705 if (!delegate_ || users.size() > kMaxUsers) {
1708 const base::ListValue* whitelist = NULL;
1709 if (!cros_settings->GetList(kAccountsPrefUsers, &whitelist) || !whitelist)
1711 for (size_t i = 0; i < whitelist->GetSize(); ++i) {
1712 std::string whitelisted_user;
1713 // NB: Wildcards in the whitelist are also detected as not present here.
1714 if (!whitelist->GetString(i, &whitelisted_user) ||
1715 !user_manager->IsKnownUser(whitelisted_user)) {
1722 void SigninScreenHandler::CancelPasswordChangedFlowInternal() {
1725 delegate_->CancelPasswordChangedFlow();
1729 OobeUI::Screen SigninScreenHandler::GetCurrentScreen() const {
1730 OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN;
1731 OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController());
1733 screen = oobe_ui->current_screen();
1737 bool SigninScreenHandler::IsGaiaVisible() const {
1738 return IsSigninScreen(GetCurrentScreen()) &&
1739 ui_state_ == UI_STATE_GAIA_SIGNIN;
1742 bool SigninScreenHandler::IsGaiaHiddenByError() const {
1743 return IsSigninScreenHiddenByError() &&
1744 ui_state_ == UI_STATE_GAIA_SIGNIN;
1747 bool SigninScreenHandler::IsSigninScreenHiddenByError() const {
1748 return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) &&
1749 (IsSigninScreen(error_screen_actor_->parent_screen()));
1752 bool SigninScreenHandler::IsGuestSigninAllowed() const {
1753 CrosSettings* cros_settings = CrosSettings::Get();
1757 cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
1761 bool SigninScreenHandler::IsOfflineLoginAllowed() const {
1762 CrosSettings* cros_settings = CrosSettings::Get();
1766 // Offline login is allowed only when user pods are hidden.
1768 cros_settings->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_pods);
1772 void SigninScreenHandler::SubmitLoginFormForTest() {
1773 VLOG(2) << "Submit login form for test, user=" << test_user_;
1776 code += "document.getElementById('Email').value = '" + test_user_ + "';";
1777 code += "document.getElementById('Passwd').value = '" + test_pass_ + "';";
1778 code += "document.getElementById('signIn').click();";
1780 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1781 rvh->ExecuteJavascriptInWebFrame(
1782 ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1783 ASCIIToUTF16(code));
1785 // Test properties are cleared in HandleCompleteLogin because the form
1786 // submission might fail and login will not be attempted after reloading
1787 // if they are cleared here.
1790 void SigninScreenHandler::ContinueKioskEnableFlow(bool should_auto_enroll) {
1791 wait_for_auto_enrollment_check_ = false;
1793 // Do not proceed with kiosk enable when auto enroll will be enforced.
1794 // TODO(xiyuan): Add an error UI feedkback so user knows what happens.
1795 if (should_auto_enroll) {
1796 LOG(WARNING) << "Kiosk enable flow aborted because auto enrollment is "
1797 "going to be enforced.";
1799 if (!kiosk_enable_flow_aborted_callback_for_test_.is_null())
1800 kiosk_enable_flow_aborted_callback_for_test_.Run();
1805 delegate_->ShowKioskEnableScreen();
1808 } // namespace chromeos