Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / webui / chromeos / login / signin_screen_handler.cc
blob9d76bc4cf0338fdf302630138d39ecea4b9f996b
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/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/prefs/pref_registry_simple.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/prefs/scoped_user_pref_update.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/browser_process_platform_part_chromeos.h"
23 #include "chrome/browser/browser_shutdown.h"
24 #include "chrome/browser/chrome_notification_types.h"
25 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
26 #include "chrome/browser/chromeos/boot_times_loader.h"
27 #include "chrome/browser/chromeos/input_method/input_method_util.h"
28 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
29 #include "chrome/browser/chromeos/login/hwid_checker.h"
30 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
31 #include "chrome/browser/chromeos/login/screen_locker.h"
32 #include "chrome/browser/chromeos/login/screens/core_oobe_actor.h"
33 #include "chrome/browser/chromeos/login/user.h"
34 #include "chrome/browser/chromeos/login/webui_login_display.h"
35 #include "chrome/browser/chromeos/login/wizard_controller.h"
36 #include "chrome/browser/chromeos/net/network_portal_detector.h"
37 #include "chrome/browser/chromeos/profiles/profile_helper.h"
38 #include "chrome/browser/chromeos/settings/cros_settings.h"
39 #include "chrome/browser/io_thread.h"
40 #include "chrome/browser/policy/browser_policy_connector.h"
41 #include "chrome/browser/profiles/profile.h"
42 #include "chrome/browser/ui/webui/chromeos/login/authenticated_user_email_retriever.h"
43 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
44 #include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
45 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
46 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
47 #include "chrome/common/chrome_switches.h"
48 #include "chrome/common/pref_names.h"
49 #include "chrome/common/url_constants.h"
50 #include "chromeos/chromeos_switches.h"
51 #include "chromeos/dbus/dbus_thread_manager.h"
52 #include "chromeos/dbus/power_manager_client.h"
53 #include "chromeos/ime/input_method_manager.h"
54 #include "chromeos/ime/xkeyboard.h"
55 #include "chromeos/network/network_state.h"
56 #include "chromeos/network/network_state_handler.h"
57 #include "content/public/browser/browser_thread.h"
58 #include "content/public/browser/render_view_host.h"
59 #include "content/public/browser/web_contents.h"
60 #include "google_apis/gaia/gaia_auth_util.h"
61 #include "grit/chromium_strings.h"
62 #include "grit/generated_resources.h"
63 #include "net/url_request/url_request_context_getter.h"
64 #include "third_party/cros_system_api/dbus/service_constants.h"
66 #if defined(USE_AURA)
67 #include "ash/shell.h"
68 #include "ash/wm/lock_state_controller.h"
69 #endif
71 using content::BrowserThread;
72 using content::RenderViewHost;
74 namespace {
76 // User dictionary keys.
77 const char kKeyUsername[] = "username";
78 const char kKeyDisplayName[] = "displayName";
79 const char kKeyEmailAddress[] = "emailAddress";
80 const char kKeyEnterpriseDomain[] = "enterpriseDomain";
81 const char kKeyPublicAccount[] = "publicAccount";
82 const char kKeyLocallyManagedUser[] = "locallyManagedUser";
83 const char kKeySignedIn[] = "signedIn";
84 const char kKeyCanRemove[] = "canRemove";
85 const char kKeyIsOwner[] = "isOwner";
86 const char kKeyOauthTokenStatus[] = "oauthTokenStatus";
88 // Max number of users to show.
89 const size_t kMaxUsers = 18;
91 // Timeout to delay first notification about offline state for a
92 // current network.
93 const int kOfflineTimeoutSec = 5;
95 // Timeout used to prevent infinite connecting to a flaky network.
96 const int kConnectingTimeoutSec = 60;
98 // Type of the login screen UI that is currently presented to user.
99 const char kSourceGaiaSignin[] = "gaia-signin";
100 const char kSourceAccountPicker[] = "account-picker";
102 // The Task posted to PostTaskAndReply in StartClearingDnsCache on the IO
103 // thread.
104 void ClearDnsCache(IOThread* io_thread) {
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
106 if (browser_shutdown::IsTryingToQuit())
107 return;
109 io_thread->ClearHostCache();
112 static bool Contains(const std::vector<std::string>& container,
113 const std::string& value) {
114 return std::find(container.begin(), container.end(), value) !=
115 container.end();
118 } // namespace
120 namespace chromeos {
122 namespace {
124 bool IsOnline(NetworkStateInformer::State state,
125 ErrorScreenActor::ErrorReason reason) {
126 return state == NetworkStateInformer::ONLINE &&
127 reason != ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED &&
128 reason != ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT;
131 bool IsBehindCaptivePortal(NetworkStateInformer::State state,
132 ErrorScreenActor::ErrorReason reason) {
133 return state == NetworkStateInformer::CAPTIVE_PORTAL ||
134 reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED;
137 bool IsProxyError(NetworkStateInformer::State state,
138 ErrorScreenActor::ErrorReason reason,
139 net::Error frame_error) {
140 return state == NetworkStateInformer::PROXY_AUTH_REQUIRED ||
141 reason == ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED ||
142 reason == ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED ||
143 (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
144 (frame_error == net::ERR_PROXY_CONNECTION_FAILED ||
145 frame_error == net::ERR_TUNNEL_CONNECTION_FAILED));
148 bool IsSigninScreen(const OobeUI::Screen screen) {
149 return screen == OobeUI::SCREEN_GAIA_SIGNIN ||
150 screen == OobeUI::SCREEN_ACCOUNT_PICKER;
153 bool IsSigninScreenError(ErrorScreen::ErrorState error_state) {
154 return error_state == ErrorScreen::ERROR_STATE_PORTAL ||
155 error_state == ErrorScreen::ERROR_STATE_OFFLINE ||
156 error_state == ErrorScreen::ERROR_STATE_PROXY ||
157 error_state == ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
160 // Returns network name by service path.
161 std::string GetNetworkName(const std::string& service_path) {
162 const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
163 GetNetworkState(service_path);
164 if (!network)
165 return std::string();
166 return network->name();
169 static bool SetUserInputMethodImpl(
170 const std::string& username,
171 chromeos::input_method::InputMethodManager* manager) {
172 PrefService* const local_state = g_browser_process->local_state();
174 const base::DictionaryValue* users_lru_input_methods =
175 local_state->GetDictionary(prefs::kUsersLRUInputMethod);
177 if (users_lru_input_methods == NULL) {
178 DLOG(WARNING) << "SetUserInputMethod('" << username
179 << "'): no kUsersLRUInputMethod";
180 return false;
183 std::string input_method;
185 if (!users_lru_input_methods->GetStringWithoutPathExpansion(username,
186 &input_method)) {
187 DVLOG(0) << "SetUserInputMethod('" << username
188 << "'): no input method for this user";
189 return false;
192 if (input_method.empty())
193 return false;
195 if (!manager->IsLoginKeyboard(input_method)) {
196 LOG(WARNING) << "SetUserInputMethod('" << username
197 << "'): stored user LRU input method '" << input_method
198 << "' is no longer Full Latin Keyboard Language"
199 << " (entry dropped). Use hardware default instead.";
201 DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
203 base::DictionaryValue* const users_lru_input_methods = updater.Get();
204 if (users_lru_input_methods != NULL) {
205 users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
207 return false;
210 if (!Contains(manager->GetActiveInputMethodIds(), input_method)) {
211 if (!manager->EnableInputMethod(input_method)) {
212 DLOG(ERROR) << "SigninScreenHandler::SetUserInputMethod('" << username
213 << "'): user input method '" << input_method
214 << "' is not enabled and enabling failed (ignored!).";
217 manager->ChangeInputMethod(input_method);
219 return true;
222 } // namespace
224 // LoginScreenContext implementation ------------------------------------------
226 LoginScreenContext::LoginScreenContext() {
227 Init();
230 LoginScreenContext::LoginScreenContext(const base::ListValue* args) {
231 Init();
233 if (!args || args->GetSize() == 0)
234 return;
235 std::string email;
236 if (args->GetString(0, &email))
237 email_ = email;
240 void LoginScreenContext::Init() {
241 oobe_ui_ = false;
244 // SigninScreenHandler implementation ------------------------------------------
246 SigninScreenHandler::SigninScreenHandler(
247 const scoped_refptr<NetworkStateInformer>& network_state_informer,
248 ErrorScreenActor* error_screen_actor,
249 CoreOobeActor* core_oobe_actor,
250 GaiaScreenHandler* gaia_screen_handler)
251 : ui_state_(UI_STATE_UNKNOWN),
252 delegate_(NULL),
253 native_window_delegate_(NULL),
254 show_on_init_(false),
255 oobe_ui_(false),
256 focus_stolen_(false),
257 gaia_silent_load_(false),
258 is_account_picker_showing_first_time_(false),
259 dns_cleared_(false),
260 dns_clear_task_running_(false),
261 cookies_cleared_(false),
262 network_state_informer_(network_state_informer),
263 test_expects_complete_login_(false),
264 weak_factory_(this),
265 webui_visible_(false),
266 preferences_changed_delayed_(false),
267 error_screen_actor_(error_screen_actor),
268 core_oobe_actor_(core_oobe_actor),
269 is_first_update_state_call_(true),
270 offline_login_active_(false),
271 last_network_state_(NetworkStateInformer::UNKNOWN),
272 has_pending_auth_ui_(false),
273 wait_for_auto_enrollment_check_(false),
274 gaia_screen_handler_(gaia_screen_handler) {
275 DCHECK(network_state_informer_.get());
276 DCHECK(error_screen_actor_);
277 DCHECK(core_oobe_actor_);
278 DCHECK(gaia_screen_handler_);
279 gaia_screen_handler_->SetSigninScreenHandler(this);
280 network_state_informer_->AddObserver(this);
281 allow_new_user_subscription_ = CrosSettings::Get()->AddSettingsObserver(
282 kAccountsPrefAllowNewUser,
283 base::Bind(&SigninScreenHandler::UserSettingsChanged,
284 base::Unretained(this)));
285 allow_guest_subscription_ = CrosSettings::Get()->AddSettingsObserver(
286 kAccountsPrefAllowGuest,
287 base::Bind(&SigninScreenHandler::UserSettingsChanged,
288 base::Unretained(this)));
290 registrar_.Add(this,
291 chrome::NOTIFICATION_AUTH_NEEDED,
292 content::NotificationService::AllSources());
293 registrar_.Add(this,
294 chrome::NOTIFICATION_AUTH_SUPPLIED,
295 content::NotificationService::AllSources());
296 registrar_.Add(this,
297 chrome::NOTIFICATION_AUTH_CANCELLED,
298 content::NotificationService::AllSources());
300 WallpaperManager::Get()->AddObserver(this);
303 SigninScreenHandler::~SigninScreenHandler() {
304 WallpaperManager::Get()->RemoveObserver(this);
305 weak_factory_.InvalidateWeakPtrs();
306 SystemKeyEventListener* key_event_listener =
307 SystemKeyEventListener::GetInstance();
308 if (key_event_listener)
309 key_event_listener->RemoveCapsLockObserver(this);
310 if (delegate_)
311 delegate_->SetWebUIHandler(NULL);
312 network_state_informer_->RemoveObserver(this);
315 void SigninScreenHandler::DeclareLocalizedValues(
316 LocalizedValuesBuilder* builder) {
317 builder->Add("passwordHint", IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT);
318 builder->Add("podMenuButtonAccessibleName",
319 IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME);
320 builder->Add("podMenuRemoveItemAccessibleName",
321 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME);
322 builder->Add("passwordFieldAccessibleName",
323 IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME);
324 builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER);
325 builder->Add("signinButton", IDS_LOGIN_BUTTON);
326 builder->Add("shutDown", IDS_SHUTDOWN_BUTTON);
327 builder->Add("addUser", IDS_ADD_USER_BUTTON);
328 builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON);
329 builder->Add("cancel", IDS_CANCEL);
330 builder->Add("signOutUser", IDS_SCREEN_LOCK_SIGN_OUT);
331 builder->Add("offlineLogin", IDS_OFFLINE_LOGIN_HTML);
332 builder->Add("ownerUserPattern", IDS_LOGIN_POD_OWNER_USER);
333 builder->Add("removeUser", IDS_LOGIN_POD_REMOVE_USER);
334 builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE);
335 builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT);
336 builder->Add("errorTpmFailureRebootButton",
337 IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON);
338 builder->Add(
339 "disabledAddUserTooltip",
340 g_browser_process->browser_policy_connector()->IsEnterpriseManaged() ?
341 IDS_DISABLED_ADD_USER_TOOLTIP_ENTERPRISE :
342 IDS_DISABLED_ADD_USER_TOOLTIP);
343 builder->Add("supervisedUserExpiredTokenWarning",
344 IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING);
345 builder->Add("signinBannerText", IDS_LOGIN_USER_ADDING_BANNER);
347 // Strings used by password changed dialog.
348 builder->Add("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE);
349 builder->Add("passwordChangedDesc", IDS_LOGIN_PASSWORD_CHANGED_DESC);
350 builder->AddF("passwordChangedMoreInfo",
351 IDS_LOGIN_PASSWORD_CHANGED_MORE_INFO,
352 IDS_SHORT_PRODUCT_OS_NAME);
354 builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT);
355 builder->Add("oldPasswordIncorrect",
356 IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD);
357 builder->Add("passwordChangedCantRemember",
358 IDS_LOGIN_PASSWORD_CHANGED_CANT_REMEMBER);
359 builder->Add("passwordChangedBackButton",
360 IDS_LOGIN_PASSWORD_CHANGED_BACK_BUTTON);
361 builder->Add("passwordChangedsOkButton", IDS_OK);
362 builder->Add("passwordChangedProceedAnyway",
363 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY);
364 builder->Add("proceedAnywayButton",
365 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON);
366 builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT);
367 builder->Add("publicAccountReminder",
368 IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER);
369 builder->Add("publicAccountEnter", IDS_LOGIN_PUBLIC_ACCOUNT_ENTER);
370 builder->Add("publicAccountEnterAccessibleName",
371 IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME);
372 builder->AddF("removeUserWarningText",
373 IDS_LOGIN_POD_USER_REMOVE_WARNING,
374 base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
375 builder->Add("removeUserWarningButtonTitle",
376 IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON);
378 builder->Add("samlNotice", IDS_LOGIN_SAML_NOTICE);
380 // Strings used by confirm password dialog.
381 builder->Add("confirmPasswordTitle", IDS_LOGIN_CONFIRM_PASSWORD_TITLE);
382 builder->Add("confirmPasswordHint", IDS_LOGIN_CONFIRM_PASSWORD_HINT);
383 builder->Add("confirmPasswordConfirmButton",
384 IDS_LOGIN_CONFIRM_PASSWORD_CONFIRM_BUTTON);
386 if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
387 builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE);
390 void SigninScreenHandler::Show(const LoginScreenContext& context) {
391 CHECK(delegate_);
393 // Just initialize internal fields from context and call ShowImpl().
394 oobe_ui_ = context.oobe_ui();
395 if (!context.email().empty())
396 email_ = context.email();
397 else
398 email_.clear();
399 ShowImpl();
402 void SigninScreenHandler::ShowRetailModeLoginSpinner() {
403 CallJS("showLoginSpinner");
406 void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) {
407 delegate_ = delegate;
408 if (delegate_)
409 delegate_->SetWebUIHandler(this);
412 void SigninScreenHandler::SetNativeWindowDelegate(
413 NativeWindowDelegate* native_window_delegate) {
414 native_window_delegate_ = native_window_delegate;
417 void SigninScreenHandler::OnNetworkReady() {
418 LOG(WARNING) << "OnNetworkReady() call.";
419 MaybePreloadAuthExtension();
422 void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
423 UpdateStateInternal(reason, false);
426 // SigninScreenHandler, private: -----------------------------------------------
428 void SigninScreenHandler::ShowImpl() {
429 if (!page_is_ready()) {
430 show_on_init_ = true;
431 return;
434 if (oobe_ui_) {
435 // Shows new user sign-in for OOBE.
436 OnShowAddUser(email_);
437 } else {
438 // Populates account picker. Animation is turned off for now until we
439 // figure out how to make it fast enough.
440 SendUserList(false);
442 // Reset Caps Lock state when login screen is shown.
443 input_method::InputMethodManager::Get()->GetXKeyboard()->
444 SetCapsLockEnabled(false);
446 base::DictionaryValue params;
447 params.SetBoolean("disableAddUser", AllWhitelistedUsersPresent());
448 UpdateUIState(UI_STATE_ACCOUNT_PICKER, &params);
452 void SigninScreenHandler::UpdateUIState(UIState ui_state,
453 base::DictionaryValue* params) {
454 switch (ui_state) {
455 case UI_STATE_GAIA_SIGNIN:
456 ui_state_ = UI_STATE_GAIA_SIGNIN;
457 ShowScreen(OobeUI::kScreenGaiaSignin, params);
458 break;
459 case UI_STATE_ACCOUNT_PICKER:
460 ui_state_ = UI_STATE_ACCOUNT_PICKER;
461 ShowScreen(OobeUI::kScreenAccountPicker, params);
462 break;
463 default:
464 NOTREACHED();
465 break;
469 // TODO (ygorshenin@): split this method into small parts.
470 // TODO (ygorshenin@): move this logic to GaiaScreenHandler.
471 void SigninScreenHandler::UpdateStateInternal(
472 ErrorScreenActor::ErrorReason reason,
473 bool force_update) {
474 // Do nothing once user has signed in or sign in is in progress.
475 // TODO(ygorshenin): We will end up here when processing network state
476 // notification but no ShowSigninScreen() was called so delegate_ will be
477 // NULL. Network state processing logic does not belong here.
478 if (delegate_ &&
479 (delegate_->IsUserSigninCompleted() || delegate_->IsSigninInProgress())) {
480 return;
483 NetworkStateInformer::State state = network_state_informer_->state();
484 const std::string network_path = network_state_informer_->network_path();
485 const std::string network_name = GetNetworkName(network_path);
487 // Skip "update" notification about OFFLINE state from
488 // NetworkStateInformer if previous notification already was
489 // delayed.
490 if ((state == NetworkStateInformer::OFFLINE || has_pending_auth_ui_) &&
491 !force_update && !update_state_closure_.IsCancelled()) {
492 return;
495 // TODO (ygorshenin@): switch log level to INFO once signin screen
496 // will be tested well.
497 LOG(WARNING) << "SigninScreenHandler::UpdateStateInternal(): "
498 << "state=" << NetworkStateInformer::StatusString(state) << ", "
499 << "network_name=" << network_name << ", "
500 << "reason=" << ErrorScreenActor::ErrorReasonString(reason)
501 << ", force_update=" << force_update;
502 update_state_closure_.Cancel();
504 if ((state == NetworkStateInformer::OFFLINE && !force_update) ||
505 has_pending_auth_ui_) {
506 update_state_closure_.Reset(
507 base::Bind(&SigninScreenHandler::UpdateStateInternal,
508 weak_factory_.GetWeakPtr(),
509 reason,
510 true));
511 base::MessageLoop::current()->PostDelayedTask(
512 FROM_HERE,
513 update_state_closure_.callback(),
514 base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
515 return;
518 // Don't show or hide error screen if we're in connecting state.
519 if (state == NetworkStateInformer::CONNECTING && !force_update) {
520 if (connecting_closure_.IsCancelled()) {
521 // First notification about CONNECTING state.
522 connecting_closure_.Reset(
523 base::Bind(&SigninScreenHandler::UpdateStateInternal,
524 weak_factory_.GetWeakPtr(),
525 reason,
526 true));
527 base::MessageLoop::current()->PostDelayedTask(
528 FROM_HERE,
529 connecting_closure_.callback(),
530 base::TimeDelta::FromSeconds(kConnectingTimeoutSec));
532 return;
534 connecting_closure_.Cancel();
536 const bool is_online = IsOnline(state, reason);
537 const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason);
538 const bool is_gaia_loading_timeout =
539 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
540 const bool is_gaia_error =
541 FrameError() != net::OK && FrameError() != net::ERR_NETWORK_CHANGED;
542 const bool is_gaia_signin = IsGaiaVisible() || IsGaiaHiddenByError();
543 const bool error_screen_should_overlay =
544 !offline_login_active_ && IsGaiaVisible();
545 const bool from_not_online_to_online_transition =
546 is_online && last_network_state_ != NetworkStateInformer::ONLINE;
547 last_network_state_ = state;
549 if (is_online || !is_behind_captive_portal)
550 error_screen_actor_->HideCaptivePortal();
552 // Hide offline message (if needed) and return if current screen is
553 // not a Gaia frame.
554 if (!is_gaia_signin) {
555 if (!IsSigninScreenHiddenByError())
556 HideOfflineMessage(state, reason);
557 return;
560 // Reload frame if network state is changed from {!ONLINE} -> ONLINE state.
561 if (reason == ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED &&
562 from_not_online_to_online_transition) {
563 // Schedules a immediate retry.
564 LOG(WARNING) << "Retry page load since network has been changed.";
565 ReloadGaiaScreen();
568 if (reason == ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED &&
569 error_screen_should_overlay) {
570 // Schedules a immediate retry.
571 LOG(WARNING) << "Retry page load since proxy settings has been changed.";
572 ReloadGaiaScreen();
575 if (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
576 !IsProxyError(state, reason, FrameError())) {
577 LOG(WARNING) << "Retry page load due to reason: "
578 << ErrorScreenActor::ErrorReasonString(reason);
579 ReloadGaiaScreen();
582 if ((!is_online || is_gaia_loading_timeout || is_gaia_error) &&
583 !offline_login_active_) {
584 SetupAndShowOfflineMessage(state, reason);
585 } else {
586 HideOfflineMessage(state, reason);
590 void SigninScreenHandler::SetupAndShowOfflineMessage(
591 NetworkStateInformer:: State state,
592 ErrorScreenActor::ErrorReason reason) {
593 const std::string network_path = network_state_informer_->network_path();
594 const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason);
595 const bool is_proxy_error = IsProxyError(state, reason, FrameError());
596 const bool is_gaia_loading_timeout =
597 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
599 if (is_proxy_error) {
600 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
601 std::string());
602 } else if (is_behind_captive_portal) {
603 // Do not bother a user with obsessive captive portal showing. This
604 // check makes captive portal being shown only once: either when error
605 // screen is shown for the first time or when switching from another
606 // error screen (offline, proxy).
607 if (IsGaiaVisible() ||
608 (error_screen_actor_->error_state() !=
609 ErrorScreen::ERROR_STATE_PORTAL)) {
610 error_screen_actor_->FixCaptivePortal();
612 const std::string network_name = GetNetworkName(network_path);
613 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
614 network_name);
615 } else if (is_gaia_loading_timeout) {
616 error_screen_actor_->SetErrorState(
617 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT, std::string());
618 } else {
619 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
620 std::string());
623 const bool guest_signin_allowed = IsGuestSigninAllowed() &&
624 IsSigninScreenError(error_screen_actor_->error_state());
625 error_screen_actor_->AllowGuestSignin(guest_signin_allowed);
627 const bool offline_login_allowed = IsOfflineLoginAllowed() &&
628 IsSigninScreenError(error_screen_actor_->error_state()) &&
629 error_screen_actor_->error_state() !=
630 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
631 error_screen_actor_->AllowOfflineLogin(offline_login_allowed);
633 if (GetCurrentScreen() != OobeUI::SCREEN_ERROR_MESSAGE) {
634 base::DictionaryValue params;
635 const std::string network_type = network_state_informer_->network_type();
636 params.SetString("lastNetworkType", network_type);
637 error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_SIGNIN);
638 error_screen_actor_->Show(OobeUI::SCREEN_GAIA_SIGNIN, &params);
642 void SigninScreenHandler::HideOfflineMessage(
643 NetworkStateInformer::State state,
644 ErrorScreenActor::ErrorReason reason) {
645 if (!IsSigninScreenHiddenByError())
646 return;
648 error_screen_actor_->Hide();
650 // Forces a reload for Gaia screen on hiding error message.
651 if (IsGaiaVisible() || IsGaiaHiddenByError())
652 ReloadGaiaScreen();
655 void SigninScreenHandler::ReloadGaiaScreen() {
656 gaia_screen_handler_->ReloadGaia();
659 void SigninScreenHandler::Initialize() {
660 // If delegate_ is NULL here (e.g. WebUIScreenLocker has been destroyed),
661 // don't do anything, just return.
662 if (!delegate_)
663 return;
665 // Register for Caps Lock state change notifications;
666 SystemKeyEventListener* key_event_listener =
667 SystemKeyEventListener::GetInstance();
668 if (key_event_listener)
669 key_event_listener->AddCapsLockObserver(this);
671 if (show_on_init_) {
672 show_on_init_ = false;
673 ShowImpl();
677 gfx::NativeWindow SigninScreenHandler::GetNativeWindow() {
678 if (native_window_delegate_)
679 return native_window_delegate_->GetNativeWindow();
680 return NULL;
683 void SigninScreenHandler::RegisterMessages() {
684 AddCallback("authenticateUser", &SigninScreenHandler::HandleAuthenticateUser);
685 AddCallback("completeLogin", &SigninScreenHandler::HandleCompleteLogin);
686 AddCallback("completeAuthentication",
687 &SigninScreenHandler::HandleCompleteAuthentication);
688 AddCallback("getUsers", &SigninScreenHandler::HandleGetUsers);
689 AddCallback("launchDemoUser", &SigninScreenHandler::HandleLaunchDemoUser);
690 AddCallback("launchIncognito", &SigninScreenHandler::HandleLaunchIncognito);
691 AddCallback("showLocallyManagedUserCreationScreen",
692 &SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen);
693 AddCallback("launchPublicAccount",
694 &SigninScreenHandler::HandleLaunchPublicAccount);
695 AddRawCallback("offlineLogin", &SigninScreenHandler::HandleOfflineLogin);
696 AddCallback("rebootSystem", &SigninScreenHandler::HandleRebootSystem);
697 AddRawCallback("showAddUser", &SigninScreenHandler::HandleShowAddUser);
698 AddCallback("shutdownSystem", &SigninScreenHandler::HandleShutdownSystem);
699 AddCallback("loadWallpaper", &SigninScreenHandler::HandleLoadWallpaper);
700 AddCallback("removeUser", &SigninScreenHandler::HandleRemoveUser);
701 AddCallback("toggleEnrollmentScreen",
702 &SigninScreenHandler::HandleToggleEnrollmentScreen);
703 AddCallback("toggleKioskEnableScreen",
704 &SigninScreenHandler::HandleToggleKioskEnableScreen);
705 AddCallback("toggleResetScreen",
706 &SigninScreenHandler::HandleToggleResetScreen);
707 AddCallback("launchHelpApp", &SigninScreenHandler::HandleLaunchHelpApp);
708 AddCallback("createAccount", &SigninScreenHandler::HandleCreateAccount);
709 AddCallback("accountPickerReady",
710 &SigninScreenHandler::HandleAccountPickerReady);
711 AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady);
712 AddCallback("loginWebuiReady", &SigninScreenHandler::HandleLoginWebuiReady);
713 AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser);
714 AddCallback("networkErrorShown",
715 &SigninScreenHandler::HandleNetworkErrorShown);
716 AddCallback("openProxySettings",
717 &SigninScreenHandler::HandleOpenProxySettings);
718 AddCallback("loginVisible", &SigninScreenHandler::HandleLoginVisible);
719 AddCallback("cancelPasswordChangedFlow",
720 &SigninScreenHandler::HandleCancelPasswordChangedFlow);
721 AddCallback("cancelUserAdding",
722 &SigninScreenHandler::HandleCancelUserAdding);
723 AddCallback("migrateUserData", &SigninScreenHandler::HandleMigrateUserData);
724 AddCallback("resyncUserData", &SigninScreenHandler::HandleResyncUserData);
725 AddCallback("loginUIStateChanged",
726 &SigninScreenHandler::HandleLoginUIStateChanged);
727 AddCallback("unlockOnLoginSuccess",
728 &SigninScreenHandler::HandleUnlockOnLoginSuccess);
729 AddCallback("showLoadingTimeoutError",
730 &SigninScreenHandler::HandleShowLoadingTimeoutError);
731 AddCallback("updateOfflineLogin",
732 &SigninScreenHandler::HandleUpdateOfflineLogin);
733 AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod);
734 AddCallback("customButtonClicked",
735 &SigninScreenHandler::HandleCustomButtonClicked);
736 AddCallback("retrieveAuthenticatedUserEmail",
737 &SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail);
739 // This message is sent by the kiosk app menu, but is handled here
740 // so we can tell the delegate to launch the app.
741 AddCallback("launchKioskApp", &SigninScreenHandler::HandleLaunchKioskApp);
744 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
745 registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
748 void SigninScreenHandler::HandleGetUsers() {
749 SendUserList(false);
752 void SigninScreenHandler::ClearAndEnablePassword() {
753 core_oobe_actor_->ResetSignInUI(false);
756 void SigninScreenHandler::ClearUserPodPassword() {
757 core_oobe_actor_->ClearUserPodPassword();
760 void SigninScreenHandler::RefocusCurrentPod() {
761 core_oobe_actor_->RefocusCurrentPod();
764 void SigninScreenHandler::OnLoginSuccess(const std::string& username) {
765 core_oobe_actor_->OnLoginSuccess(username);
768 void SigninScreenHandler::OnUserRemoved(const std::string& username) {
769 CallJS("login.AccountPickerScreen.removeUser", username);
772 void SigninScreenHandler::OnUserImageChanged(const User& user) {
773 if (page_is_ready())
774 CallJS("login.AccountPickerScreen.updateUserImage", user.email());
777 void SigninScreenHandler::OnPreferencesChanged() {
778 // Make sure that one of the login UI is fully functional now, otherwise
779 // preferences update would be picked up next time it will be shown.
780 if (!webui_visible_) {
781 LOG(WARNING) << "Login UI is not active - postponed prefs change.";
782 preferences_changed_delayed_ = true;
783 return;
786 if (delegate_ && !delegate_->IsShowUsers()) {
787 HandleShowAddUser(NULL);
788 } else {
789 SendUserList(false);
790 UpdateUIState(UI_STATE_ACCOUNT_PICKER, NULL);
792 preferences_changed_delayed_ = false;
795 void SigninScreenHandler::ResetSigninScreenHandlerDelegate() {
796 SetDelegate(NULL);
799 void SigninScreenHandler::ShowBannerMessage(const std::string& message) {
800 CallJS("login.AccountPickerScreen.showBannerMessage", message);
803 void SigninScreenHandler::ShowUserPodButton(
804 const std::string& username,
805 const std::string& iconURL,
806 const base::Closure& click_callback) {
807 user_pod_button_callback_map_[username] = click_callback;
808 CallJS("login.AccountPickerScreen.showUserPodButton", username, iconURL);
811 void SigninScreenHandler::ShowError(int login_attempts,
812 const std::string& error_text,
813 const std::string& help_link_text,
814 HelpAppLauncher::HelpTopic help_topic_id) {
815 core_oobe_actor_->ShowSignInError(login_attempts, error_text, help_link_text,
816 help_topic_id);
819 void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) {
820 switch (error_id) {
821 case LoginDisplay::TPM_ERROR:
822 core_oobe_actor_->ShowTpmError();
823 break;
824 default:
825 NOTREACHED() << "Unknown sign in error";
826 break;
830 void SigninScreenHandler::ShowSigninUI(const std::string& email) {
831 core_oobe_actor_->ShowSignInUI(email);
834 void SigninScreenHandler::ShowGaiaPasswordChanged(const std::string& username) {
835 email_ = username;
836 password_changed_for_.insert(email_);
837 core_oobe_actor_->ShowSignInUI(email_);
838 CallJS("login.AccountPickerScreen.updateUserGaiaNeeded", email_);
841 void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) {
842 core_oobe_actor_->ShowPasswordChangedScreen(show_password_error);
845 void SigninScreenHandler::ShowSigninScreenForCreds(
846 const std::string& username,
847 const std::string& password) {
848 VLOG(2) << "ShowSigninScreenForCreds for user " << username
849 << ", frame_state=" << FrameState();
851 test_user_ = username;
852 test_pass_ = password;
853 test_expects_complete_login_ = true;
855 // Submit login form for test if gaia is ready. If gaia is loading, login
856 // will be attempted in HandleLoginWebuiReady after gaia is ready. Otherwise,
857 // reload gaia then follow the loading case.
858 if (FrameState() == GaiaScreenHandler::FRAME_STATE_LOADED)
859 SubmitLoginFormForTest();
860 else if (FrameState() != GaiaScreenHandler::FRAME_STATE_LOADING)
861 HandleShowAddUser(NULL);
864 void SigninScreenHandler::OnCookiesCleared(base::Closure on_clear_callback) {
865 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
866 cookies_cleared_ = true;
867 on_clear_callback.Run();
870 void SigninScreenHandler::OnCapsLockChange(bool enabled) {
871 if (page_is_ready())
872 CallJS("login.AccountPickerScreen.setCapsLockState", enabled);
875 void SigninScreenHandler::Observe(int type,
876 const content::NotificationSource& source,
877 const content::NotificationDetails& details) {
878 switch (type) {
879 case chrome::NOTIFICATION_AUTH_NEEDED: {
880 has_pending_auth_ui_ = true;
881 break;
883 case chrome::NOTIFICATION_AUTH_SUPPLIED:
884 has_pending_auth_ui_ = false;
885 if (IsSigninScreenHiddenByError()) {
886 // Hide error screen and reload auth extension.
887 HideOfflineMessage(network_state_informer_->state(),
888 ErrorScreenActor::ERROR_REASON_PROXY_AUTH_SUPPLIED);
889 } else if (ui_state_ == UI_STATE_GAIA_SIGNIN) {
890 // Reload auth extension as proxy credentials are supplied.
891 ReloadGaiaScreen();
893 break;
894 case chrome::NOTIFICATION_AUTH_CANCELLED: {
895 // Don't reload auth extension if proxy auth dialog was cancelled.
896 has_pending_auth_ui_ = false;
897 break;
899 default:
900 NOTREACHED() << "Unexpected notification " << type;
904 void SigninScreenHandler::OnDnsCleared() {
905 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
906 dns_clear_task_running_ = false;
907 dns_cleared_ = true;
908 ShowSigninScreenIfReady();
911 // Update keyboard layout to least recently used by the user.
912 void SigninScreenHandler::SetUserInputMethod(const std::string& username) {
913 UserManager* user_manager = UserManager::Get();
914 if (user_manager->IsUserLoggedIn()) {
915 // We are on sign-in screen inside user session (adding new user to
916 // the session or on lock screen), don't switch input methods in this case.
917 // TODO(dpolukhin): adding user and sign-in should be consistent
918 // crbug.com/292774
919 return;
922 chromeos::input_method::InputMethodManager* const manager =
923 chromeos::input_method::InputMethodManager::Get();
925 const bool succeed = SetUserInputMethodImpl(username, manager);
927 // This is also a case when LRU layout is set only for a few local users,
928 // thus others need to be switched to default locale.
929 // Otherwise they will end up using another user's locale to log in.
930 if (!succeed) {
931 DVLOG(0) << "SetUserInputMethod('" << username
932 << "'): failed to set user layout. Switching to default.";
934 manager->SetInputMethodDefault();
938 void SigninScreenHandler::ShowSigninScreenIfReady() {
939 LOG(WARNING) << "ShowSigninScreenIfReady() call.";
941 if (!dns_cleared_ || !cookies_cleared_ || !delegate_)
942 return;
944 std::string active_network_path = network_state_informer_->network_path();
945 if (gaia_silent_load_ &&
946 (network_state_informer_->state() != NetworkStateInformer::ONLINE ||
947 gaia_silent_load_network_ != active_network_path)) {
948 // Network has changed. Force Gaia reload.
949 gaia_silent_load_ = false;
950 // Gaia page will be realoded, so focus isn't stolen anymore.
951 focus_stolen_ = false;
954 // Note that LoadAuthExtension clears |email_|.
955 if (email_.empty())
956 delegate_->LoadSigninWallpaper();
957 else
958 delegate_->LoadWallpaper(email_);
960 // Set Least Recently Used input method for the user.
961 if (!email_.empty())
962 SetUserInputMethod(email_);
964 LoadAuthExtension(!gaia_silent_load_, false, false);
965 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
967 if (gaia_silent_load_) {
968 // The variable is assigned to false because silently loaded Gaia page was
969 // used.
970 gaia_silent_load_ = false;
971 if (focus_stolen_)
972 HandleLoginWebuiReady();
975 UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
978 void SigninScreenHandler::LoadAuthExtension(
979 bool force, bool silent_load, bool offline) {
980 GaiaContext context;
981 context.force_reload = force;
982 context.is_local = offline;
983 context.password_changed =
984 !email_.empty() && password_changed_for_.count(email_);
985 if (delegate_)
986 context.show_users = delegate_->IsShowUsers();
987 context.use_offline = offline;
988 if (delegate_)
989 context.has_users = delegate_->GetUsers().size() != 0;
990 context.email = email_;
992 email_.clear();
994 DCHECK(gaia_screen_handler_);
995 gaia_screen_handler_->LoadGaia(context);
998 void SigninScreenHandler::UserSettingsChanged() {
999 DCHECK(gaia_screen_handler_);
1000 GaiaContext context;
1001 if (delegate_)
1002 context.has_users = delegate_->GetUsers().size() != 0;
1003 gaia_screen_handler_->UpdateGaia(context);
1004 UpdateAddButtonStatus();
1007 void SigninScreenHandler::UpdateAddButtonStatus() {
1008 CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus",
1009 AllWhitelistedUsersPresent());
1012 void SigninScreenHandler::HandleCompleteLogin(const std::string& typed_email,
1013 const std::string& password) {
1014 if (!delegate_)
1015 return;
1016 const std::string sanitized_email = gaia::SanitizeEmail(typed_email);
1017 delegate_->SetDisplayEmail(sanitized_email);
1018 delegate_->CompleteLogin(UserContext(sanitized_email,
1019 password,
1020 std::string())); // auth_code
1022 if (test_expects_complete_login_) {
1023 VLOG(2) << "Complete test login for " << typed_email
1024 << ", requested=" << test_user_;
1026 test_expects_complete_login_ = false;
1027 test_user_.clear();
1028 test_pass_.clear();
1032 void SigninScreenHandler::HandleCompleteAuthentication(
1033 const std::string& email,
1034 const std::string& password,
1035 const std::string& auth_code) {
1036 if (!delegate_)
1037 return;
1038 const std::string sanitized_email = gaia::SanitizeEmail(email);
1039 delegate_->SetDisplayEmail(sanitized_email);
1040 delegate_->CompleteLogin(UserContext(sanitized_email, password, auth_code));
1043 void SigninScreenHandler::HandleAuthenticateUser(const std::string& username,
1044 const std::string& password) {
1045 if (!delegate_)
1046 return;
1047 delegate_->Login(UserContext(gaia::SanitizeEmail(username),
1048 password,
1049 std::string())); // auth_code
1052 void SigninScreenHandler::HandleLaunchDemoUser() {
1053 if (delegate_)
1054 delegate_->LoginAsRetailModeUser();
1057 void SigninScreenHandler::HandleLaunchIncognito() {
1058 if (delegate_)
1059 delegate_->LoginAsGuest();
1062 void SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen() {
1063 if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
1064 LOG(ERROR) << "Managed users not allowed.";
1065 return;
1067 scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue());
1068 LoginDisplayHostImpl::default_host()->
1069 StartWizard(WizardController::kLocallyManagedUserCreationScreenName,
1070 params.Pass());
1073 void SigninScreenHandler::HandleLaunchPublicAccount(
1074 const std::string& username) {
1075 if (delegate_)
1076 delegate_->LoginAsPublicAccount(username);
1079 void SigninScreenHandler::HandleOfflineLogin(const base::ListValue* args) {
1080 if (!delegate_ || delegate_->IsShowUsers()) {
1081 NOTREACHED();
1082 return;
1084 if (!args->GetString(0, &email_))
1085 email_.clear();
1086 // Load auth extension. Parameters are: force reload, do not load extension in
1087 // background, use offline version.
1088 LoadAuthExtension(true, false, true);
1089 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
1092 void SigninScreenHandler::HandleShutdownSystem() {
1093 ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
1096 void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) {
1097 if (delegate_)
1098 delegate_->LoadWallpaper(email);
1101 void SigninScreenHandler::OnWallpaperAnimationFinished(
1102 const std::string& email) {
1103 CallJS("login.AccountPickerScreen.onWallpaperLoaded", email);
1106 void SigninScreenHandler::HandleRebootSystem() {
1107 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
1110 void SigninScreenHandler::HandleRemoveUser(const std::string& email) {
1111 if (!delegate_)
1112 return;
1113 delegate_->RemoveUser(email);
1114 UpdateAddButtonStatus();
1117 void SigninScreenHandler::HandleShowAddUser(const base::ListValue* args) {
1118 TRACE_EVENT_ASYNC_STEP_INTO0("ui",
1119 "ShowLoginWebUI",
1120 LoginDisplayHostImpl::kShowLoginWebUIid,
1121 "ShowAddUser");
1122 std::string email;
1123 // |args| can be null if it's OOBE.
1124 if (args)
1125 args->GetString(0, &email);
1126 OnShowAddUser(email);
1129 void SigninScreenHandler::HandleToggleEnrollmentScreen() {
1130 if (delegate_)
1131 delegate_->ShowEnterpriseEnrollmentScreen();
1134 void SigninScreenHandler::HandleToggleKioskEnableScreen() {
1135 if (delegate_ &&
1136 !wait_for_auto_enrollment_check_ &&
1137 !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
1138 wait_for_auto_enrollment_check_ = true;
1140 LoginDisplayHostImpl::default_host()->GetAutoEnrollmentCheckResult(
1141 base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow,
1142 weak_factory_.GetWeakPtr()));
1146 void SigninScreenHandler::HandleToggleResetScreen() {
1147 if (delegate_ &&
1148 !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
1149 delegate_->ShowResetScreen();
1153 void SigninScreenHandler::HandleToggleKioskAutolaunchScreen() {
1154 if (delegate_ &&
1155 !g_browser_process->browser_policy_connector()->IsEnterpriseManaged()) {
1156 delegate_->ShowKioskAutolaunchScreen();
1160 void SigninScreenHandler::HandleLaunchHelpApp(double help_topic_id) {
1161 if (!delegate_)
1162 return;
1163 if (!help_app_.get())
1164 help_app_ = new HelpAppLauncher(GetNativeWindow());
1165 help_app_->ShowHelpTopic(
1166 static_cast<HelpAppLauncher::HelpTopic>(help_topic_id));
1169 void SigninScreenHandler::FillUserDictionary(User* user,
1170 bool is_owner,
1171 base::DictionaryValue* user_dict) {
1172 const std::string& email = user->email();
1173 bool is_public_account =
1174 user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT;
1175 bool is_locally_managed_user =
1176 user->GetType() == User::USER_TYPE_LOCALLY_MANAGED;
1177 User::OAuthTokenStatus token_status = user->oauth_token_status();
1179 // If supervised user has unknown token status consider that as valid token.
1180 // It will be invalidated inside session in case it has been revoked.
1181 if (is_locally_managed_user &&
1182 token_status == User::OAUTH_TOKEN_STATUS_UNKNOWN) {
1183 token_status = User::OAUTH2_TOKEN_STATUS_VALID;
1186 user_dict->SetString(kKeyUsername, email);
1187 user_dict->SetString(kKeyEmailAddress, user->display_email());
1188 user_dict->SetString(kKeyDisplayName, user->GetDisplayName());
1189 user_dict->SetBoolean(kKeyPublicAccount, is_public_account);
1190 user_dict->SetBoolean(kKeyLocallyManagedUser, is_locally_managed_user);
1191 user_dict->SetInteger(kKeyOauthTokenStatus, token_status);
1192 user_dict->SetBoolean(kKeySignedIn, user->is_logged_in());
1193 user_dict->SetBoolean(kKeyIsOwner, is_owner);
1195 if (is_public_account) {
1196 policy::BrowserPolicyConnector* policy_connector =
1197 g_browser_process->browser_policy_connector();
1199 if (policy_connector->IsEnterpriseManaged()) {
1200 user_dict->SetString(kKeyEnterpriseDomain,
1201 policy_connector->GetEnterpriseDomain());
1206 void SigninScreenHandler::SendUserList(bool animated) {
1207 if (!delegate_)
1208 return;
1209 TRACE_EVENT_ASYNC_STEP_INTO0("ui",
1210 "ShowLoginWebUI",
1211 LoginDisplayHostImpl::kShowLoginWebUIid,
1212 "SendUserList");
1213 BootTimesLoader::Get()->RecordCurrentStats("login-send-user-list");
1215 size_t max_non_owner_users = kMaxUsers - 1;
1216 size_t non_owner_count = 0;
1218 base::ListValue users_list;
1219 const UserList& users = delegate_->GetUsers();
1221 // TODO(nkostylev): Show optional intro dialog about multi-profiles feature
1222 // based on user preferences. http://crbug.com/230862
1224 // TODO(nkostylev): Move to a separate method in UserManager.
1225 // http://crbug.com/230852
1226 bool is_signin_to_add = LoginDisplayHostImpl::default_host() &&
1227 UserManager::Get()->IsUserLoggedIn();
1229 bool single_user = users.size() == 1;
1230 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
1231 const std::string& email = (*it)->email();
1233 std::string owner;
1234 chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
1235 bool is_owner = (email == owner);
1237 if (non_owner_count < max_non_owner_users || is_owner) {
1238 base::DictionaryValue* user_dict = new base::DictionaryValue();
1239 FillUserDictionary(*it, is_owner, user_dict);
1240 bool is_public_account =
1241 ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT);
1242 bool signed_in = (*it)->is_logged_in();
1243 // Single user check here is necessary because owner info might not be
1244 // available when running into login screen on first boot.
1245 // See http://crosbug.com/12723
1246 user_dict->SetBoolean(kKeyCanRemove,
1247 !single_user &&
1248 !email.empty() &&
1249 !is_owner &&
1250 !is_public_account &&
1251 !signed_in &&
1252 !is_signin_to_add);
1254 users_list.Append(user_dict);
1255 if (!is_owner)
1256 ++non_owner_count;
1260 CallJS("login.AccountPickerScreen.loadUsers", users_list, animated,
1261 delegate_->IsShowGuest());
1264 void SigninScreenHandler::HandleAccountPickerReady() {
1265 VLOG(0) << "Login WebUI >> AccountPickerReady";
1267 if (delegate_ && !ScreenLocker::default_screen_locker() &&
1268 !chromeos::IsMachineHWIDCorrect() &&
1269 !oobe_ui_) {
1270 delegate_->ShowWrongHWIDScreen();
1271 return;
1274 PrefService* prefs = g_browser_process->local_state();
1275 if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
1276 prefs->SetBoolean(prefs::kFactoryResetRequested, false);
1277 prefs->CommitPendingWrite();
1278 HandleToggleResetScreen();
1279 return;
1282 is_account_picker_showing_first_time_ = true;
1283 MaybePreloadAuthExtension();
1285 if (ScreenLocker::default_screen_locker())
1286 ScreenLocker::default_screen_locker()->delegate()->OnLockWebUIReady();
1288 if (delegate_)
1289 delegate_->OnSigninScreenReady();
1292 void SigninScreenHandler::HandleWallpaperReady() {
1293 if (ScreenLocker::default_screen_locker()) {
1294 ScreenLocker::default_screen_locker()->delegate()->
1295 OnLockBackgroundDisplayed();
1299 void SigninScreenHandler::HandleLoginWebuiReady() {
1300 if (focus_stolen_) {
1301 // Set focus to the Gaia page.
1302 // TODO(altimofeev): temporary solution, until focus parameters are
1303 // implemented on the Gaia side.
1304 // Do this only once. Any subsequent call would relod GAIA frame.
1305 focus_stolen_ = false;
1306 const char code[] = "gWindowOnLoad();";
1307 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1308 rvh->ExecuteJavascriptInWebFrame(
1309 base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1310 base::ASCIIToUTF16(code));
1312 if (!gaia_silent_load_) {
1313 content::NotificationService::current()->Notify(
1314 chrome::NOTIFICATION_LOGIN_WEBUI_LOADED,
1315 content::NotificationService::AllSources(),
1316 content::NotificationService::NoDetails());
1317 } else {
1318 focus_stolen_ = true;
1319 // Prevent focus stealing by the Gaia page.
1320 // TODO(altimofeev): temporary solution, until focus parameters are
1321 // implemented on the Gaia side.
1322 const char code[] = "var gWindowOnLoad = window.onload; "
1323 "window.onload=function() {};";
1324 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1325 rvh->ExecuteJavascriptInWebFrame(
1326 base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1327 base::ASCIIToUTF16(code));
1328 // As we could miss and window.onload could already be called, restore
1329 // focus to current pod (see crbug/175243).
1330 RefocusCurrentPod();
1332 DCHECK(gaia_screen_handler_);
1333 gaia_screen_handler_->HandleFrameLoadingCompleted(0);
1335 if (test_expects_complete_login_)
1336 SubmitLoginFormForTest();
1339 void SigninScreenHandler::HandleSignOutUser() {
1340 if (delegate_)
1341 delegate_->Signout();
1344 void SigninScreenHandler::HandleNetworkErrorShown() {
1345 content::NotificationService::current()->Notify(
1346 chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
1347 content::NotificationService::AllSources(),
1348 content::NotificationService::NoDetails());
1351 void SigninScreenHandler::HandleCreateAccount() {
1352 if (delegate_)
1353 delegate_->CreateAccount();
1356 void SigninScreenHandler::HandleOpenProxySettings() {
1357 LoginDisplayHostImpl::default_host()->OpenProxySettings();
1360 void SigninScreenHandler::HandleLoginVisible(const std::string& source) {
1361 LOG(WARNING) << "Login WebUI >> loginVisible, src: " << source << ", "
1362 << "webui_visible_: " << webui_visible_;
1363 if (!webui_visible_) {
1364 // There might be multiple messages from OOBE UI so send notifications after
1365 // the first one only.
1366 content::NotificationService::current()->Notify(
1367 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
1368 content::NotificationService::AllSources(),
1369 content::NotificationService::NoDetails());
1370 TRACE_EVENT_ASYNC_END0(
1371 "ui", "ShowLoginWebUI", LoginDisplayHostImpl::kShowLoginWebUIid);
1373 webui_visible_ = true;
1374 if (preferences_changed_delayed_)
1375 OnPreferencesChanged();
1378 void SigninScreenHandler::HandleCancelPasswordChangedFlow() {
1379 StartClearingCookies(base::Bind(
1380 &SigninScreenHandler::CancelPasswordChangedFlowInternal,
1381 weak_factory_.GetWeakPtr()));
1384 void SigninScreenHandler::HandleCancelUserAdding() {
1385 if (delegate_)
1386 delegate_->CancelUserAdding();
1389 void SigninScreenHandler::HandleMigrateUserData(
1390 const std::string& old_password) {
1391 if (delegate_)
1392 delegate_->MigrateUserData(old_password);
1395 void SigninScreenHandler::HandleResyncUserData() {
1396 if (delegate_)
1397 delegate_->ResyncUserData();
1400 void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source,
1401 bool new_value) {
1402 VLOG(0) << "Login WebUI >> active: " << new_value << ", "
1403 << "source: " << source;
1405 if (!KioskAppManager::Get()->GetAutoLaunchApp().empty() &&
1406 KioskAppManager::Get()->IsAutoLaunchRequested()) {
1407 VLOG(0) << "Showing auto-launch warning";
1408 // On slow devices, the wallpaper animation is not shown initially, so we
1409 // must explicitly load the wallpaper. This is also the case for the
1410 // account-picker and gaia-signin UI states.
1411 delegate_->LoadSigninWallpaper();
1412 HandleToggleKioskAutolaunchScreen();
1413 return;
1416 if (source == kSourceGaiaSignin) {
1417 ui_state_ = UI_STATE_GAIA_SIGNIN;
1418 } else if (source == kSourceAccountPicker) {
1419 ui_state_ = UI_STATE_ACCOUNT_PICKER;
1420 } else {
1421 NOTREACHED();
1422 return;
1426 void SigninScreenHandler::HandleUnlockOnLoginSuccess() {
1427 DCHECK(UserManager::Get()->IsUserLoggedIn());
1428 if (ScreenLocker::default_screen_locker())
1429 ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess();
1432 void SigninScreenHandler::HandleShowLoadingTimeoutError() {
1433 UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
1436 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
1437 offline_login_active_ = offline_login_active;
1440 void SigninScreenHandler::HandleFocusPod(const std::string& user_id) {
1441 SetUserInputMethod(user_id);
1444 void SigninScreenHandler::HandleCustomButtonClicked(
1445 const std::string& username) {
1446 if (user_pod_button_callback_map_.find(username)
1447 == user_pod_button_callback_map_.end()) {
1448 LOG(WARNING) << "User pod custom button clicked but no callback found";
1449 return;
1451 user_pod_button_callback_map_[username].Run();
1454 void SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail(
1455 double attempt_token) {
1456 email_retriever_.reset(new AuthenticatedUserEmailRetriever(
1457 base::Bind(&SigninScreenHandler::CallJS<double, std::string>,
1458 base::Unretained(this),
1459 "login.GaiaSigninScreen.setAuthenticatedUserEmail",
1460 attempt_token),
1461 Profile::FromWebUI(web_ui())->GetRequestContext()));
1464 void SigninScreenHandler::HandleLaunchKioskApp(const std::string& app_id) {
1465 delegate_->LoginAsKioskApp(app_id);
1468 void SigninScreenHandler::StartClearingDnsCache() {
1469 if (dns_clear_task_running_ || !g_browser_process->io_thread())
1470 return;
1472 dns_cleared_ = false;
1473 BrowserThread::PostTaskAndReply(
1474 BrowserThread::IO, FROM_HERE,
1475 base::Bind(&ClearDnsCache, g_browser_process->io_thread()),
1476 base::Bind(&SigninScreenHandler::OnDnsCleared,
1477 weak_factory_.GetWeakPtr()));
1478 dns_clear_task_running_ = true;
1481 void SigninScreenHandler::StartClearingCookies(
1482 const base::Closure& on_clear_callback) {
1483 cookies_cleared_ = false;
1484 ProfileHelper* profile_helper =
1485 g_browser_process->platform_part()->profile_helper();
1486 LOG_ASSERT(
1487 Profile::FromWebUI(web_ui()) == profile_helper->GetSigninProfile());
1488 profile_helper->ClearSigninProfile(base::Bind(
1489 &SigninScreenHandler::OnCookiesCleared,
1490 weak_factory_.GetWeakPtr(), on_clear_callback));
1493 void SigninScreenHandler::MaybePreloadAuthExtension() {
1494 LOG(WARNING) << "MaybePreloadAuthExtension() call.";
1496 // Fetching of the extension is not started before account picker page is
1497 // loaded because it can affect the loading speed. Also if cookies clearing
1498 // was initiated or |dns_clear_task_running_| then auth extension showing has
1499 // already been initiated and preloading is senseless.
1500 // Do not load the extension for the screen locker, see crosbug.com/25018.
1501 if (is_account_picker_showing_first_time_ &&
1502 !gaia_silent_load_ &&
1503 !ScreenLocker::default_screen_locker() &&
1504 !cookies_cleared_ &&
1505 !dns_clear_task_running_ &&
1506 network_state_informer_->state() == NetworkStateInformer::ONLINE) {
1507 gaia_silent_load_ = true;
1508 gaia_silent_load_network_ = network_state_informer_->network_path();
1509 LoadAuthExtension(true, true, false);
1513 bool SigninScreenHandler::AllWhitelistedUsersPresent() {
1514 CrosSettings* cros_settings = CrosSettings::Get();
1515 bool allow_new_user = false;
1516 cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
1517 if (allow_new_user)
1518 return false;
1519 UserManager* user_manager = UserManager::Get();
1520 const UserList& users = user_manager->GetUsers();
1521 if (!delegate_ || users.size() > kMaxUsers) {
1522 return false;
1524 const base::ListValue* whitelist = NULL;
1525 if (!cros_settings->GetList(kAccountsPrefUsers, &whitelist) || !whitelist)
1526 return false;
1527 for (size_t i = 0; i < whitelist->GetSize(); ++i) {
1528 std::string whitelisted_user;
1529 // NB: Wildcards in the whitelist are also detected as not present here.
1530 if (!whitelist->GetString(i, &whitelisted_user) ||
1531 !user_manager->IsKnownUser(whitelisted_user)) {
1532 return false;
1535 return true;
1538 void SigninScreenHandler::CancelPasswordChangedFlowInternal() {
1539 if (delegate_) {
1540 ShowImpl();
1541 delegate_->CancelPasswordChangedFlow();
1545 OobeUI::Screen SigninScreenHandler::GetCurrentScreen() const {
1546 OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN;
1547 OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController());
1548 if (oobe_ui)
1549 screen = oobe_ui->current_screen();
1550 return screen;
1553 bool SigninScreenHandler::IsGaiaVisible() const {
1554 return IsSigninScreen(GetCurrentScreen()) &&
1555 ui_state_ == UI_STATE_GAIA_SIGNIN;
1558 bool SigninScreenHandler::IsGaiaHiddenByError() const {
1559 return IsSigninScreenHiddenByError() &&
1560 ui_state_ == UI_STATE_GAIA_SIGNIN;
1563 bool SigninScreenHandler::IsSigninScreenHiddenByError() const {
1564 return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) &&
1565 (IsSigninScreen(error_screen_actor_->parent_screen()));
1568 bool SigninScreenHandler::IsGuestSigninAllowed() const {
1569 CrosSettings* cros_settings = CrosSettings::Get();
1570 if (!cros_settings)
1571 return false;
1572 bool allow_guest;
1573 cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
1574 return allow_guest;
1577 bool SigninScreenHandler::IsOfflineLoginAllowed() const {
1578 CrosSettings* cros_settings = CrosSettings::Get();
1579 if (!cros_settings)
1580 return false;
1582 // Offline login is allowed only when user pods are hidden.
1583 bool show_pods;
1584 cros_settings->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_pods);
1585 return !show_pods;
1588 void SigninScreenHandler::SubmitLoginFormForTest() {
1589 VLOG(2) << "Submit login form for test, user=" << test_user_;
1591 std::string code;
1592 code += "document.getElementById('Email').value = '" + test_user_ + "';";
1593 code += "document.getElementById('Passwd').value = '" + test_pass_ + "';";
1594 code += "document.getElementById('signIn').click();";
1596 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1597 rvh->ExecuteJavascriptInWebFrame(
1598 base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1599 base::ASCIIToUTF16(code));
1601 // Test properties are cleared in HandleCompleteLogin because the form
1602 // submission might fail and login will not be attempted after reloading
1603 // if they are cleared here.
1606 void SigninScreenHandler::ContinueKioskEnableFlow(bool should_auto_enroll) {
1607 wait_for_auto_enrollment_check_ = false;
1609 // Do not proceed with kiosk enable when auto enroll will be enforced.
1610 // TODO(xiyuan): Add an error UI feedkback so user knows what happens.
1611 if (should_auto_enroll) {
1612 LOG(WARNING) << "Kiosk enable flow aborted because auto enrollment is "
1613 "going to be enforced.";
1615 if (!kiosk_enable_flow_aborted_callback_for_test_.is_null())
1616 kiosk_enable_flow_aborted_callback_for_test_.Run();
1617 return;
1620 if (delegate_)
1621 delegate_->ShowKioskEnableScreen();
1624 void SigninScreenHandler::OnShowAddUser(const std::string& email) {
1625 email_ = email;
1626 is_account_picker_showing_first_time_ = false;
1628 if (gaia_silent_load_ && email_.empty()) {
1629 dns_cleared_ = true;
1630 cookies_cleared_ = true;
1631 ShowSigninScreenIfReady();
1632 } else {
1633 StartClearingDnsCache();
1634 StartClearingCookies(base::Bind(
1635 &SigninScreenHandler::ShowSigninScreenIfReady,
1636 weak_factory_.GetWeakPtr()));
1640 GaiaScreenHandler::FrameState SigninScreenHandler::FrameState() const {
1641 DCHECK(gaia_screen_handler_);
1642 return gaia_screen_handler_->frame_state();
1645 net::Error SigninScreenHandler::FrameError() const {
1646 DCHECK(gaia_screen_handler_);
1647 return gaia_screen_handler_->frame_error();
1650 } // namespace chromeos