cros: Update SAML flow.
[chromium-blink-merge.git] / chrome / browser / ui / webui / chromeos / login / signin_screen_handler.cc
blob7589dbf4e4d8f6064099ee33ffec0b72f61f6beb
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/wallpaper_manager.h"
35 #include "chrome/browser/chromeos/login/webui_login_display.h"
36 #include "chrome/browser/chromeos/login/wizard_controller.h"
37 #include "chrome/browser/chromeos/net/network_portal_detector.h"
38 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
39 #include "chrome/browser/chromeos/profiles/profile_helper.h"
40 #include "chrome/browser/chromeos/settings/cros_settings.h"
41 #include "chrome/browser/io_thread.h"
42 #include "chrome/browser/profiles/profile.h"
43 #include "chrome/browser/ui/webui/chromeos/login/authenticated_user_email_retriever.h"
44 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
45 #include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h"
46 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
47 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
48 #include "chrome/common/chrome_switches.h"
49 #include "chrome/common/pref_names.h"
50 #include "chrome/common/url_constants.h"
51 #include "chromeos/chromeos_switches.h"
52 #include "chromeos/dbus/dbus_thread_manager.h"
53 #include "chromeos/dbus/power_manager_client.h"
54 #include "chromeos/ime/input_method_manager.h"
55 #include "chromeos/ime/xkeyboard.h"
56 #include "chromeos/network/network_state.h"
57 #include "chromeos/network/network_state_handler.h"
58 #include "content/public/browser/browser_thread.h"
59 #include "content/public/browser/render_view_host.h"
60 #include "content/public/browser/web_contents.h"
61 #include "google_apis/gaia/gaia_auth_util.h"
62 #include "grit/chromium_strings.h"
63 #include "grit/generated_resources.h"
64 #include "net/url_request/url_request_context_getter.h"
65 #include "third_party/cros_system_api/dbus/service_constants.h"
67 #if defined(USE_AURA)
68 #include "ash/shell.h"
69 #include "ash/wm/lock_state_controller.h"
70 #endif
72 using content::BrowserThread;
73 using content::RenderViewHost;
75 namespace {
77 // User dictionary keys.
78 const char kKeyUsername[] = "username";
79 const char kKeyDisplayName[] = "displayName";
80 const char kKeyEmailAddress[] = "emailAddress";
81 const char kKeyEnterpriseDomain[] = "enterpriseDomain";
82 const char kKeyPublicAccount[] = "publicAccount";
83 const char kKeyLocallyManagedUser[] = "locallyManagedUser";
84 const char kKeySignedIn[] = "signedIn";
85 const char kKeyCanRemove[] = "canRemove";
86 const char kKeyIsOwner[] = "isOwner";
87 const char kKeyForceOnlineSignin[] = "forceOnlineSignin";
89 // Max number of users to show.
90 const size_t kMaxUsers = 18;
92 // Timeout to delay first notification about offline state for a
93 // current network.
94 const int kOfflineTimeoutSec = 5;
96 // Timeout used to prevent infinite connecting to a flaky network.
97 const int kConnectingTimeoutSec = 60;
99 // Type of the login screen UI that is currently presented to user.
100 const char kSourceGaiaSignin[] = "gaia-signin";
101 const char kSourceAccountPicker[] = "account-picker";
103 // The Task posted to PostTaskAndReply in StartClearingDnsCache on the IO
104 // thread.
105 void ClearDnsCache(IOThread* io_thread) {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
107 if (browser_shutdown::IsTryingToQuit())
108 return;
110 io_thread->ClearHostCache();
113 static bool Contains(const std::vector<std::string>& container,
114 const std::string& value) {
115 return std::find(container.begin(), container.end(), value) !=
116 container.end();
119 } // namespace
121 namespace chromeos {
123 namespace {
125 bool IsOnline(NetworkStateInformer::State state,
126 ErrorScreenActor::ErrorReason reason) {
127 return state == NetworkStateInformer::ONLINE &&
128 reason != ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED &&
129 reason != ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT;
132 bool IsBehindCaptivePortal(NetworkStateInformer::State state,
133 ErrorScreenActor::ErrorReason reason) {
134 return state == NetworkStateInformer::CAPTIVE_PORTAL ||
135 reason == ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED;
138 bool IsProxyError(NetworkStateInformer::State state,
139 ErrorScreenActor::ErrorReason reason,
140 net::Error frame_error) {
141 return state == NetworkStateInformer::PROXY_AUTH_REQUIRED ||
142 reason == ErrorScreenActor::ERROR_REASON_PROXY_AUTH_CANCELLED ||
143 reason == ErrorScreenActor::ERROR_REASON_PROXY_CONNECTION_FAILED ||
144 (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
145 (frame_error == net::ERR_PROXY_CONNECTION_FAILED ||
146 frame_error == net::ERR_TUNNEL_CONNECTION_FAILED));
149 bool IsSigninScreen(const OobeUI::Screen screen) {
150 return screen == OobeUI::SCREEN_GAIA_SIGNIN ||
151 screen == OobeUI::SCREEN_ACCOUNT_PICKER;
154 bool IsSigninScreenError(ErrorScreen::ErrorState error_state) {
155 return error_state == ErrorScreen::ERROR_STATE_PORTAL ||
156 error_state == ErrorScreen::ERROR_STATE_OFFLINE ||
157 error_state == ErrorScreen::ERROR_STATE_PROXY ||
158 error_state == ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
161 // Returns network name by service path.
162 std::string GetNetworkName(const std::string& service_path) {
163 const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
164 GetNetworkState(service_path);
165 if (!network)
166 return std::string();
167 return network->name();
170 static bool SetUserInputMethodImpl(
171 const std::string& username,
172 chromeos::input_method::InputMethodManager* manager) {
173 PrefService* const local_state = g_browser_process->local_state();
175 const base::DictionaryValue* users_lru_input_methods =
176 local_state->GetDictionary(prefs::kUsersLRUInputMethod);
178 if (users_lru_input_methods == NULL) {
179 DLOG(WARNING) << "SetUserInputMethod('" << username
180 << "'): no kUsersLRUInputMethod";
181 return false;
184 std::string input_method;
186 if (!users_lru_input_methods->GetStringWithoutPathExpansion(username,
187 &input_method)) {
188 DVLOG(0) << "SetUserInputMethod('" << username
189 << "'): no input method for this user";
190 return false;
193 if (input_method.empty())
194 return false;
196 if (!manager->IsLoginKeyboard(input_method)) {
197 LOG(WARNING) << "SetUserInputMethod('" << username
198 << "'): stored user LRU input method '" << input_method
199 << "' is no longer Full Latin Keyboard Language"
200 << " (entry dropped). Use hardware default instead.";
202 DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
204 base::DictionaryValue* const users_lru_input_methods = updater.Get();
205 if (users_lru_input_methods != NULL) {
206 users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
208 return false;
211 if (!Contains(manager->GetActiveInputMethodIds(), input_method)) {
212 if (!manager->EnableInputMethod(input_method)) {
213 DLOG(ERROR) << "SigninScreenHandler::SetUserInputMethod('" << username
214 << "'): user input method '" << input_method
215 << "' is not enabled and enabling failed (ignored!).";
218 manager->ChangeInputMethod(input_method);
220 return true;
223 } // namespace
225 // LoginScreenContext implementation ------------------------------------------
227 LoginScreenContext::LoginScreenContext() {
228 Init();
231 LoginScreenContext::LoginScreenContext(const base::ListValue* args) {
232 Init();
234 if (!args || args->GetSize() == 0)
235 return;
236 std::string email;
237 if (args->GetString(0, &email))
238 email_ = email;
241 void LoginScreenContext::Init() {
242 oobe_ui_ = false;
245 // SigninScreenHandler implementation ------------------------------------------
247 SigninScreenHandler::SigninScreenHandler(
248 const scoped_refptr<NetworkStateInformer>& network_state_informer,
249 ErrorScreenActor* error_screen_actor,
250 CoreOobeActor* core_oobe_actor,
251 GaiaScreenHandler* gaia_screen_handler)
252 : ui_state_(UI_STATE_UNKNOWN),
253 delegate_(NULL),
254 native_window_delegate_(NULL),
255 show_on_init_(false),
256 oobe_ui_(false),
257 focus_stolen_(false),
258 gaia_silent_load_(false),
259 is_account_picker_showing_first_time_(false),
260 dns_cleared_(false),
261 dns_clear_task_running_(false),
262 cookies_cleared_(false),
263 network_state_informer_(network_state_informer),
264 test_expects_complete_login_(false),
265 weak_factory_(this),
266 webui_visible_(false),
267 preferences_changed_delayed_(false),
268 error_screen_actor_(error_screen_actor),
269 core_oobe_actor_(core_oobe_actor),
270 is_first_update_state_call_(true),
271 offline_login_active_(false),
272 last_network_state_(NetworkStateInformer::UNKNOWN),
273 has_pending_auth_ui_(false),
274 wait_for_auto_enrollment_check_(false),
275 gaia_screen_handler_(gaia_screen_handler) {
276 DCHECK(network_state_informer_.get());
277 DCHECK(error_screen_actor_);
278 DCHECK(core_oobe_actor_);
279 DCHECK(gaia_screen_handler_);
280 gaia_screen_handler_->SetSigninScreenHandler(this);
281 network_state_informer_->AddObserver(this);
282 allow_new_user_subscription_ = CrosSettings::Get()->AddSettingsObserver(
283 kAccountsPrefAllowNewUser,
284 base::Bind(&SigninScreenHandler::UserSettingsChanged,
285 base::Unretained(this)));
286 allow_guest_subscription_ = CrosSettings::Get()->AddSettingsObserver(
287 kAccountsPrefAllowGuest,
288 base::Bind(&SigninScreenHandler::UserSettingsChanged,
289 base::Unretained(this)));
291 registrar_.Add(this,
292 chrome::NOTIFICATION_AUTH_NEEDED,
293 content::NotificationService::AllSources());
294 registrar_.Add(this,
295 chrome::NOTIFICATION_AUTH_SUPPLIED,
296 content::NotificationService::AllSources());
297 registrar_.Add(this,
298 chrome::NOTIFICATION_AUTH_CANCELLED,
299 content::NotificationService::AllSources());
302 SigninScreenHandler::~SigninScreenHandler() {
303 weak_factory_.InvalidateWeakPtrs();
304 SystemKeyEventListener* key_event_listener =
305 SystemKeyEventListener::GetInstance();
306 if (key_event_listener)
307 key_event_listener->RemoveCapsLockObserver(this);
308 if (delegate_)
309 delegate_->SetWebUIHandler(NULL);
310 network_state_informer_->RemoveObserver(this);
313 void SigninScreenHandler::DeclareLocalizedValues(
314 LocalizedValuesBuilder* builder) {
315 builder->Add("passwordHint", IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT);
316 builder->Add("podMenuButtonAccessibleName",
317 IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME);
318 builder->Add("podMenuRemoveItemAccessibleName",
319 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME);
320 builder->Add("passwordFieldAccessibleName",
321 IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME);
322 builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER);
323 builder->Add("signinButton", IDS_LOGIN_BUTTON);
324 builder->Add("shutDown", IDS_SHUTDOWN_BUTTON);
325 builder->Add("addUser", IDS_ADD_USER_BUTTON);
326 builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON);
327 builder->Add("cancel", IDS_CANCEL);
328 builder->Add("signOutUser", IDS_SCREEN_LOCK_SIGN_OUT);
329 builder->Add("offlineLogin", IDS_OFFLINE_LOGIN_HTML);
330 builder->Add("ownerUserPattern", IDS_LOGIN_POD_OWNER_USER);
331 builder->Add("removeUser", IDS_LOGIN_POD_REMOVE_USER);
332 builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE);
333 builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT);
334 builder->Add("errorTpmFailureRebootButton",
335 IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON);
337 policy::BrowserPolicyConnectorChromeOS* connector =
338 g_browser_process->platform_part()->browser_policy_connector_chromeos();
339 builder->Add("disabledAddUserTooltip",
340 connector->IsEnterpriseManaged()
341 ? IDS_DISABLED_ADD_USER_TOOLTIP_ENTERPRISE
342 : IDS_DISABLED_ADD_USER_TOOLTIP);
344 builder->Add("supervisedUserExpiredTokenWarning",
345 IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING);
346 builder->Add("signinBannerText", IDS_LOGIN_USER_ADDING_BANNER);
348 // Strings used by password changed dialog.
349 builder->Add("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE);
350 builder->Add("passwordChangedDesc", IDS_LOGIN_PASSWORD_CHANGED_DESC);
351 builder->AddF("passwordChangedMoreInfo",
352 IDS_LOGIN_PASSWORD_CHANGED_MORE_INFO,
353 IDS_SHORT_PRODUCT_OS_NAME);
355 builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT);
356 builder->Add("oldPasswordIncorrect",
357 IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD);
358 builder->Add("passwordChangedCantRemember",
359 IDS_LOGIN_PASSWORD_CHANGED_CANT_REMEMBER);
360 builder->Add("passwordChangedBackButton",
361 IDS_LOGIN_PASSWORD_CHANGED_BACK_BUTTON);
362 builder->Add("passwordChangedsOkButton", IDS_OK);
363 builder->Add("passwordChangedProceedAnyway",
364 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY);
365 builder->Add("proceedAnywayButton",
366 IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON);
367 builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT);
368 builder->Add("publicAccountReminder",
369 IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER);
370 builder->Add("publicAccountEnter", IDS_LOGIN_PUBLIC_ACCOUNT_ENTER);
371 builder->Add("publicAccountEnterAccessibleName",
372 IDS_LOGIN_PUBLIC_ACCOUNT_ENTER_ACCESSIBLE_NAME);
373 builder->AddF("removeUserWarningText",
374 IDS_LOGIN_POD_USER_REMOVE_WARNING,
375 base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
376 builder->Add("removeUserWarningButtonTitle",
377 IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON);
379 builder->Add("samlNotice", IDS_LOGIN_SAML_NOTICE);
381 builder->Add("confirmPasswordTitle", IDS_LOGIN_CONFIRM_PASSWORD_TITLE);
382 builder->Add("confirmPasswordLabel", IDS_LOGIN_CONFIRM_PASSWORD_LABEL);
383 builder->Add("confirmPasswordConfirmButton",
384 IDS_LOGIN_CONFIRM_PASSWORD_CONFIRM_BUTTON);
385 builder->Add("confirmPasswordText", IDS_LOGIN_CONFIRM_PASSWORD_TEXT);
386 builder->Add("confirmPasswordErrorText",
387 IDS_LOGIN_CONFIRM_PASSWORD_ERROR_TEXT);
389 if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
390 builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE);
393 void SigninScreenHandler::Show(const LoginScreenContext& context) {
394 CHECK(delegate_);
396 // Just initialize internal fields from context and call ShowImpl().
397 oobe_ui_ = context.oobe_ui();
398 if (!context.email().empty())
399 email_ = context.email();
400 else
401 email_.clear();
402 ShowImpl();
405 void SigninScreenHandler::ShowRetailModeLoginSpinner() {
406 CallJS("showLoginSpinner");
409 void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) {
410 delegate_ = delegate;
411 if (delegate_)
412 delegate_->SetWebUIHandler(this);
415 void SigninScreenHandler::SetNativeWindowDelegate(
416 NativeWindowDelegate* native_window_delegate) {
417 native_window_delegate_ = native_window_delegate;
420 void SigninScreenHandler::OnNetworkReady() {
421 LOG(WARNING) << "OnNetworkReady() call.";
422 MaybePreloadAuthExtension();
425 void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
426 UpdateStateInternal(reason, false);
429 // SigninScreenHandler, private: -----------------------------------------------
431 void SigninScreenHandler::ShowImpl() {
432 if (!page_is_ready()) {
433 show_on_init_ = true;
434 return;
437 if (oobe_ui_) {
438 // Shows new user sign-in for OOBE.
439 OnShowAddUser(email_);
440 } else {
441 // Populates account picker. Animation is turned off for now until we
442 // figure out how to make it fast enough.
443 SendUserList(false);
445 // Reset Caps Lock state when login screen is shown.
446 input_method::InputMethodManager::Get()->GetXKeyboard()->
447 SetCapsLockEnabled(false);
449 base::DictionaryValue params;
450 params.SetBoolean("disableAddUser", AllWhitelistedUsersPresent());
451 UpdateUIState(UI_STATE_ACCOUNT_PICKER, &params);
455 void SigninScreenHandler::UpdateUIState(UIState ui_state,
456 base::DictionaryValue* params) {
457 switch (ui_state) {
458 case UI_STATE_GAIA_SIGNIN:
459 ui_state_ = UI_STATE_GAIA_SIGNIN;
460 ShowScreen(OobeUI::kScreenGaiaSignin, params);
461 break;
462 case UI_STATE_ACCOUNT_PICKER:
463 ui_state_ = UI_STATE_ACCOUNT_PICKER;
464 ShowScreen(OobeUI::kScreenAccountPicker, params);
465 break;
466 default:
467 NOTREACHED();
468 break;
472 // TODO (ygorshenin@): split this method into small parts.
473 // TODO (ygorshenin@): move this logic to GaiaScreenHandler.
474 void SigninScreenHandler::UpdateStateInternal(
475 ErrorScreenActor::ErrorReason reason,
476 bool force_update) {
477 // Do nothing once user has signed in or sign in is in progress.
478 // TODO(ygorshenin): We will end up here when processing network state
479 // notification but no ShowSigninScreen() was called so delegate_ will be
480 // NULL. Network state processing logic does not belong here.
481 if (delegate_ &&
482 (delegate_->IsUserSigninCompleted() || delegate_->IsSigninInProgress())) {
483 return;
486 NetworkStateInformer::State state = network_state_informer_->state();
487 const std::string network_path = network_state_informer_->network_path();
488 const std::string network_name = GetNetworkName(network_path);
490 // Skip "update" notification about OFFLINE state from
491 // NetworkStateInformer if previous notification already was
492 // delayed.
493 if ((state == NetworkStateInformer::OFFLINE || has_pending_auth_ui_) &&
494 !force_update && !update_state_closure_.IsCancelled()) {
495 return;
498 // TODO (ygorshenin@): switch log level to INFO once signin screen
499 // will be tested well.
500 LOG(WARNING) << "SigninScreenHandler::UpdateStateInternal(): "
501 << "state=" << NetworkStateInformer::StatusString(state) << ", "
502 << "network_name=" << network_name << ", "
503 << "reason=" << ErrorScreenActor::ErrorReasonString(reason)
504 << ", force_update=" << force_update;
505 update_state_closure_.Cancel();
507 if ((state == NetworkStateInformer::OFFLINE && !force_update) ||
508 has_pending_auth_ui_) {
509 update_state_closure_.Reset(
510 base::Bind(&SigninScreenHandler::UpdateStateInternal,
511 weak_factory_.GetWeakPtr(),
512 reason,
513 true));
514 base::MessageLoop::current()->PostDelayedTask(
515 FROM_HERE,
516 update_state_closure_.callback(),
517 base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
518 return;
521 // Don't show or hide error screen if we're in connecting state.
522 if (state == NetworkStateInformer::CONNECTING && !force_update) {
523 if (connecting_closure_.IsCancelled()) {
524 // First notification about CONNECTING state.
525 connecting_closure_.Reset(
526 base::Bind(&SigninScreenHandler::UpdateStateInternal,
527 weak_factory_.GetWeakPtr(),
528 reason,
529 true));
530 base::MessageLoop::current()->PostDelayedTask(
531 FROM_HERE,
532 connecting_closure_.callback(),
533 base::TimeDelta::FromSeconds(kConnectingTimeoutSec));
535 return;
537 connecting_closure_.Cancel();
539 const bool is_online = IsOnline(state, reason);
540 const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason);
541 const bool is_gaia_loading_timeout =
542 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
543 const bool is_gaia_error =
544 FrameError() != net::OK && FrameError() != net::ERR_NETWORK_CHANGED;
545 const bool is_gaia_signin = IsGaiaVisible() || IsGaiaHiddenByError();
546 const bool error_screen_should_overlay =
547 !offline_login_active_ && IsGaiaVisible();
548 const bool from_not_online_to_online_transition =
549 is_online && last_network_state_ != NetworkStateInformer::ONLINE;
550 last_network_state_ = state;
552 if (is_online || !is_behind_captive_portal)
553 error_screen_actor_->HideCaptivePortal();
555 // Hide offline message (if needed) and return if current screen is
556 // not a Gaia frame.
557 if (!is_gaia_signin) {
558 if (!IsSigninScreenHiddenByError())
559 HideOfflineMessage(state, reason);
560 return;
563 // Reload frame if network state is changed from {!ONLINE} -> ONLINE state.
564 if (reason == ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED &&
565 from_not_online_to_online_transition) {
566 // Schedules a immediate retry.
567 LOG(WARNING) << "Retry page load since network has been changed.";
568 ReloadGaiaScreen();
571 if (reason == ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED &&
572 error_screen_should_overlay) {
573 // Schedules a immediate retry.
574 LOG(WARNING) << "Retry page load since proxy settings has been changed.";
575 ReloadGaiaScreen();
578 if (reason == ErrorScreenActor::ERROR_REASON_FRAME_ERROR &&
579 !IsProxyError(state, reason, FrameError())) {
580 LOG(WARNING) << "Retry page load due to reason: "
581 << ErrorScreenActor::ErrorReasonString(reason);
582 ReloadGaiaScreen();
585 if ((!is_online || is_gaia_loading_timeout || is_gaia_error) &&
586 !offline_login_active_) {
587 SetupAndShowOfflineMessage(state, reason);
588 } else {
589 HideOfflineMessage(state, reason);
593 void SigninScreenHandler::SetupAndShowOfflineMessage(
594 NetworkStateInformer:: State state,
595 ErrorScreenActor::ErrorReason reason) {
596 const std::string network_path = network_state_informer_->network_path();
597 const bool is_behind_captive_portal = IsBehindCaptivePortal(state, reason);
598 const bool is_proxy_error = IsProxyError(state, reason, FrameError());
599 const bool is_gaia_loading_timeout =
600 (reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
602 if (is_proxy_error) {
603 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
604 std::string());
605 } else if (is_behind_captive_portal) {
606 // Do not bother a user with obsessive captive portal showing. This
607 // check makes captive portal being shown only once: either when error
608 // screen is shown for the first time or when switching from another
609 // error screen (offline, proxy).
610 if (IsGaiaVisible() ||
611 (error_screen_actor_->error_state() !=
612 ErrorScreen::ERROR_STATE_PORTAL)) {
613 error_screen_actor_->FixCaptivePortal();
615 const std::string network_name = GetNetworkName(network_path);
616 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
617 network_name);
618 } else if (is_gaia_loading_timeout) {
619 error_screen_actor_->SetErrorState(
620 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT, std::string());
621 } else {
622 error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
623 std::string());
626 const bool guest_signin_allowed = IsGuestSigninAllowed() &&
627 IsSigninScreenError(error_screen_actor_->error_state());
628 error_screen_actor_->AllowGuestSignin(guest_signin_allowed);
630 const bool offline_login_allowed = IsOfflineLoginAllowed() &&
631 IsSigninScreenError(error_screen_actor_->error_state()) &&
632 error_screen_actor_->error_state() !=
633 ErrorScreen::ERROR_STATE_AUTH_EXT_TIMEOUT;
634 error_screen_actor_->AllowOfflineLogin(offline_login_allowed);
636 if (GetCurrentScreen() != OobeUI::SCREEN_ERROR_MESSAGE) {
637 base::DictionaryValue params;
638 const std::string network_type = network_state_informer_->network_type();
639 params.SetString("lastNetworkType", network_type);
640 error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_SIGNIN);
641 error_screen_actor_->Show(OobeUI::SCREEN_GAIA_SIGNIN, &params);
645 void SigninScreenHandler::HideOfflineMessage(
646 NetworkStateInformer::State state,
647 ErrorScreenActor::ErrorReason reason) {
648 if (!IsSigninScreenHiddenByError())
649 return;
651 error_screen_actor_->Hide();
653 // Forces a reload for Gaia screen on hiding error message.
654 if (IsGaiaVisible() || IsGaiaHiddenByError())
655 ReloadGaiaScreen();
658 void SigninScreenHandler::ReloadGaiaScreen() {
659 gaia_screen_handler_->ReloadGaia();
662 void SigninScreenHandler::Initialize() {
663 // If delegate_ is NULL here (e.g. WebUIScreenLocker has been destroyed),
664 // don't do anything, just return.
665 if (!delegate_)
666 return;
668 // Register for Caps Lock state change notifications;
669 SystemKeyEventListener* key_event_listener =
670 SystemKeyEventListener::GetInstance();
671 if (key_event_listener)
672 key_event_listener->AddCapsLockObserver(this);
674 if (show_on_init_) {
675 show_on_init_ = false;
676 ShowImpl();
680 gfx::NativeWindow SigninScreenHandler::GetNativeWindow() {
681 if (native_window_delegate_)
682 return native_window_delegate_->GetNativeWindow();
683 return NULL;
686 void SigninScreenHandler::RegisterMessages() {
687 AddCallback("authenticateUser", &SigninScreenHandler::HandleAuthenticateUser);
688 AddCallback("completeLogin", &SigninScreenHandler::HandleCompleteLogin);
689 AddCallback("completeAuthentication",
690 &SigninScreenHandler::HandleCompleteAuthentication);
691 AddCallback("getUsers", &SigninScreenHandler::HandleGetUsers);
692 AddCallback("launchDemoUser", &SigninScreenHandler::HandleLaunchDemoUser);
693 AddCallback("launchIncognito", &SigninScreenHandler::HandleLaunchIncognito);
694 AddCallback("showLocallyManagedUserCreationScreen",
695 &SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen);
696 AddCallback("launchPublicAccount",
697 &SigninScreenHandler::HandleLaunchPublicAccount);
698 AddRawCallback("offlineLogin", &SigninScreenHandler::HandleOfflineLogin);
699 AddCallback("rebootSystem", &SigninScreenHandler::HandleRebootSystem);
700 AddRawCallback("showAddUser", &SigninScreenHandler::HandleShowAddUser);
701 AddCallback("shutdownSystem", &SigninScreenHandler::HandleShutdownSystem);
702 AddCallback("loadWallpaper", &SigninScreenHandler::HandleLoadWallpaper);
703 AddCallback("removeUser", &SigninScreenHandler::HandleRemoveUser);
704 AddCallback("toggleEnrollmentScreen",
705 &SigninScreenHandler::HandleToggleEnrollmentScreen);
706 AddCallback("toggleKioskEnableScreen",
707 &SigninScreenHandler::HandleToggleKioskEnableScreen);
708 AddCallback("toggleResetScreen",
709 &SigninScreenHandler::HandleToggleResetScreen);
710 AddCallback("launchHelpApp", &SigninScreenHandler::HandleLaunchHelpApp);
711 AddCallback("createAccount", &SigninScreenHandler::HandleCreateAccount);
712 AddCallback("accountPickerReady",
713 &SigninScreenHandler::HandleAccountPickerReady);
714 AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady);
715 AddCallback("loginWebuiReady", &SigninScreenHandler::HandleLoginWebuiReady);
716 AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser);
717 AddCallback("networkErrorShown",
718 &SigninScreenHandler::HandleNetworkErrorShown);
719 AddCallback("openProxySettings",
720 &SigninScreenHandler::HandleOpenProxySettings);
721 AddCallback("loginVisible", &SigninScreenHandler::HandleLoginVisible);
722 AddCallback("cancelPasswordChangedFlow",
723 &SigninScreenHandler::HandleCancelPasswordChangedFlow);
724 AddCallback("cancelUserAdding",
725 &SigninScreenHandler::HandleCancelUserAdding);
726 AddCallback("migrateUserData", &SigninScreenHandler::HandleMigrateUserData);
727 AddCallback("resyncUserData", &SigninScreenHandler::HandleResyncUserData);
728 AddCallback("loginUIStateChanged",
729 &SigninScreenHandler::HandleLoginUIStateChanged);
730 AddCallback("unlockOnLoginSuccess",
731 &SigninScreenHandler::HandleUnlockOnLoginSuccess);
732 AddCallback("showLoadingTimeoutError",
733 &SigninScreenHandler::HandleShowLoadingTimeoutError);
734 AddCallback("updateOfflineLogin",
735 &SigninScreenHandler::HandleUpdateOfflineLogin);
736 AddCallback("focusPod", &SigninScreenHandler::HandleFocusPod);
737 AddCallback("customButtonClicked",
738 &SigninScreenHandler::HandleCustomButtonClicked);
739 AddCallback("retrieveAuthenticatedUserEmail",
740 &SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail);
742 // This message is sent by the kiosk app menu, but is handled here
743 // so we can tell the delegate to launch the app.
744 AddCallback("launchKioskApp", &SigninScreenHandler::HandleLaunchKioskApp);
747 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
748 registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
751 void SigninScreenHandler::HandleGetUsers() {
752 SendUserList(false);
755 void SigninScreenHandler::ClearAndEnablePassword() {
756 core_oobe_actor_->ResetSignInUI(false);
759 void SigninScreenHandler::ClearUserPodPassword() {
760 core_oobe_actor_->ClearUserPodPassword();
763 void SigninScreenHandler::RefocusCurrentPod() {
764 core_oobe_actor_->RefocusCurrentPod();
767 void SigninScreenHandler::OnLoginSuccess(const std::string& username) {
768 core_oobe_actor_->OnLoginSuccess(username);
771 void SigninScreenHandler::OnUserRemoved(const std::string& username) {
772 CallJS("login.AccountPickerScreen.removeUser", username);
775 void SigninScreenHandler::OnUserImageChanged(const User& user) {
776 if (page_is_ready())
777 CallJS("login.AccountPickerScreen.updateUserImage", user.email());
780 void SigninScreenHandler::OnPreferencesChanged() {
781 // Make sure that one of the login UI is fully functional now, otherwise
782 // preferences update would be picked up next time it will be shown.
783 if (!webui_visible_) {
784 LOG(WARNING) << "Login UI is not active - postponed prefs change.";
785 preferences_changed_delayed_ = true;
786 return;
789 if (delegate_ && !delegate_->IsShowUsers()) {
790 HandleShowAddUser(NULL);
791 } else {
792 SendUserList(false);
793 UpdateUIState(UI_STATE_ACCOUNT_PICKER, NULL);
795 preferences_changed_delayed_ = false;
798 void SigninScreenHandler::ResetSigninScreenHandlerDelegate() {
799 SetDelegate(NULL);
802 void SigninScreenHandler::ShowBannerMessage(const std::string& message) {
803 CallJS("login.AccountPickerScreen.showBannerMessage", message);
806 void SigninScreenHandler::ShowUserPodButton(
807 const std::string& username,
808 const std::string& iconURL,
809 const base::Closure& click_callback) {
810 user_pod_button_callback_map_[username] = click_callback;
811 CallJS("login.AccountPickerScreen.showUserPodButton", username, iconURL);
814 void SigninScreenHandler::ShowError(int login_attempts,
815 const std::string& error_text,
816 const std::string& help_link_text,
817 HelpAppLauncher::HelpTopic help_topic_id) {
818 core_oobe_actor_->ShowSignInError(login_attempts, error_text, help_link_text,
819 help_topic_id);
822 void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) {
823 switch (error_id) {
824 case LoginDisplay::TPM_ERROR:
825 core_oobe_actor_->ShowTpmError();
826 break;
827 default:
828 NOTREACHED() << "Unknown sign in error";
829 break;
833 void SigninScreenHandler::ShowSigninUI(const std::string& email) {
834 core_oobe_actor_->ShowSignInUI(email);
837 void SigninScreenHandler::ShowGaiaPasswordChanged(const std::string& username) {
838 email_ = username;
839 password_changed_for_.insert(email_);
840 core_oobe_actor_->ShowSignInUI(email_);
841 CallJS("login.AccountPickerScreen.forceOnlineSignin", email_);
844 void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) {
845 core_oobe_actor_->ShowPasswordChangedScreen(show_password_error);
848 void SigninScreenHandler::ShowSigninScreenForCreds(
849 const std::string& username,
850 const std::string& password) {
851 VLOG(2) << "ShowSigninScreenForCreds for user " << username
852 << ", frame_state=" << FrameState();
854 test_user_ = username;
855 test_pass_ = password;
856 test_expects_complete_login_ = true;
858 // Submit login form for test if gaia is ready. If gaia is loading, login
859 // will be attempted in HandleLoginWebuiReady after gaia is ready. Otherwise,
860 // reload gaia then follow the loading case.
861 if (FrameState() == GaiaScreenHandler::FRAME_STATE_LOADED)
862 SubmitLoginFormForTest();
863 else if (FrameState() != GaiaScreenHandler::FRAME_STATE_LOADING)
864 HandleShowAddUser(NULL);
867 void SigninScreenHandler::OnCookiesCleared(base::Closure on_clear_callback) {
868 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
869 cookies_cleared_ = true;
870 on_clear_callback.Run();
873 void SigninScreenHandler::OnCapsLockChange(bool enabled) {
874 if (page_is_ready())
875 CallJS("login.AccountPickerScreen.setCapsLockState", enabled);
878 void SigninScreenHandler::Observe(int type,
879 const content::NotificationSource& source,
880 const content::NotificationDetails& details) {
881 switch (type) {
882 case chrome::NOTIFICATION_AUTH_NEEDED: {
883 has_pending_auth_ui_ = true;
884 break;
886 case chrome::NOTIFICATION_AUTH_SUPPLIED:
887 has_pending_auth_ui_ = false;
888 if (IsSigninScreenHiddenByError()) {
889 // Hide error screen and reload auth extension.
890 HideOfflineMessage(network_state_informer_->state(),
891 ErrorScreenActor::ERROR_REASON_PROXY_AUTH_SUPPLIED);
892 } else if (ui_state_ == UI_STATE_GAIA_SIGNIN) {
893 // Reload auth extension as proxy credentials are supplied.
894 ReloadGaiaScreen();
896 break;
897 case chrome::NOTIFICATION_AUTH_CANCELLED: {
898 // Don't reload auth extension if proxy auth dialog was cancelled.
899 has_pending_auth_ui_ = false;
900 break;
902 default:
903 NOTREACHED() << "Unexpected notification " << type;
907 void SigninScreenHandler::OnDnsCleared() {
908 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
909 dns_clear_task_running_ = false;
910 dns_cleared_ = true;
911 ShowSigninScreenIfReady();
914 // Update keyboard layout to least recently used by the user.
915 void SigninScreenHandler::SetUserInputMethod(const std::string& username) {
916 UserManager* user_manager = UserManager::Get();
917 if (user_manager->IsUserLoggedIn()) {
918 // We are on sign-in screen inside user session (adding new user to
919 // the session or on lock screen), don't switch input methods in this case.
920 // TODO(dpolukhin): adding user and sign-in should be consistent
921 // crbug.com/292774
922 return;
925 chromeos::input_method::InputMethodManager* const manager =
926 chromeos::input_method::InputMethodManager::Get();
928 const bool succeed = SetUserInputMethodImpl(username, manager);
930 // This is also a case when LRU layout is set only for a few local users,
931 // thus others need to be switched to default locale.
932 // Otherwise they will end up using another user's locale to log in.
933 if (!succeed) {
934 DVLOG(0) << "SetUserInputMethod('" << username
935 << "'): failed to set user layout. Switching to default.";
937 manager->SetInputMethodDefault();
941 void SigninScreenHandler::ShowSigninScreenIfReady() {
942 LOG(WARNING) << "ShowSigninScreenIfReady() call.";
944 if (!dns_cleared_ || !cookies_cleared_ || !delegate_)
945 return;
947 std::string active_network_path = network_state_informer_->network_path();
948 if (gaia_silent_load_ &&
949 (network_state_informer_->state() != NetworkStateInformer::ONLINE ||
950 gaia_silent_load_network_ != active_network_path)) {
951 // Network has changed. Force Gaia reload.
952 gaia_silent_load_ = false;
953 // Gaia page will be realoded, so focus isn't stolen anymore.
954 focus_stolen_ = false;
957 // Note that LoadAuthExtension clears |email_|.
958 if (email_.empty())
959 delegate_->LoadSigninWallpaper();
960 else
961 delegate_->LoadWallpaper(email_);
963 // Set Least Recently Used input method for the user.
964 if (!email_.empty())
965 SetUserInputMethod(email_);
967 LoadAuthExtension(!gaia_silent_load_, false, false);
968 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
970 if (gaia_silent_load_) {
971 // The variable is assigned to false because silently loaded Gaia page was
972 // used.
973 gaia_silent_load_ = false;
974 if (focus_stolen_)
975 HandleLoginWebuiReady();
978 UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
981 void SigninScreenHandler::LoadAuthExtension(
982 bool force, bool silent_load, bool offline) {
983 GaiaContext context;
984 context.force_reload = force;
985 context.is_local = offline;
986 context.password_changed =
987 !email_.empty() && password_changed_for_.count(email_);
988 if (delegate_)
989 context.show_users = delegate_->IsShowUsers();
990 context.use_offline = offline;
991 if (delegate_)
992 context.has_users = delegate_->GetUsers().size() != 0;
993 context.email = email_;
995 email_.clear();
997 DCHECK(gaia_screen_handler_);
998 gaia_screen_handler_->LoadGaia(context);
1001 void SigninScreenHandler::UserSettingsChanged() {
1002 DCHECK(gaia_screen_handler_);
1003 GaiaContext context;
1004 if (delegate_)
1005 context.has_users = delegate_->GetUsers().size() != 0;
1006 gaia_screen_handler_->UpdateGaia(context);
1007 UpdateAddButtonStatus();
1010 void SigninScreenHandler::UpdateAddButtonStatus() {
1011 CallJS("cr.ui.login.DisplayManager.updateAddUserButtonStatus",
1012 AllWhitelistedUsersPresent());
1015 void SigninScreenHandler::HandleCompleteLogin(const std::string& typed_email,
1016 const std::string& password,
1017 bool using_saml) {
1018 if (!delegate_)
1019 return;
1021 const std::string sanitized_email = gaia::SanitizeEmail(typed_email);
1022 delegate_->SetDisplayEmail(sanitized_email);
1023 delegate_->CompleteLogin(UserContext(
1024 sanitized_email,
1025 password,
1026 std::string(), // auth_code
1027 std::string(), // username_hash
1028 true, // using_oauth
1029 using_saml ? UserContext::AUTH_FLOW_GAIA_WITH_SAML
1030 : UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML));
1032 if (test_expects_complete_login_) {
1033 VLOG(2) << "Complete test login for " << typed_email
1034 << ", requested=" << test_user_;
1036 test_expects_complete_login_ = false;
1037 test_user_.clear();
1038 test_pass_.clear();
1042 void SigninScreenHandler::HandleCompleteAuthentication(
1043 const std::string& email,
1044 const std::string& password,
1045 const std::string& auth_code) {
1046 if (!delegate_)
1047 return;
1048 const std::string sanitized_email = gaia::SanitizeEmail(email);
1049 delegate_->SetDisplayEmail(sanitized_email);
1050 delegate_->CompleteLogin(UserContext(sanitized_email, password, auth_code));
1053 void SigninScreenHandler::HandleAuthenticateUser(const std::string& username,
1054 const std::string& password) {
1055 if (!delegate_)
1056 return;
1057 delegate_->Login(UserContext(gaia::SanitizeEmail(username),
1058 password,
1059 std::string())); // auth_code
1062 void SigninScreenHandler::HandleLaunchDemoUser() {
1063 if (delegate_)
1064 delegate_->LoginAsRetailModeUser();
1067 void SigninScreenHandler::HandleLaunchIncognito() {
1068 if (delegate_)
1069 delegate_->LoginAsGuest();
1072 void SigninScreenHandler::HandleShowLocallyManagedUserCreationScreen() {
1073 if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
1074 LOG(ERROR) << "Managed users not allowed.";
1075 return;
1077 scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue());
1078 LoginDisplayHostImpl::default_host()->
1079 StartWizard(WizardController::kLocallyManagedUserCreationScreenName,
1080 params.Pass());
1083 void SigninScreenHandler::HandleLaunchPublicAccount(
1084 const std::string& username) {
1085 if (delegate_)
1086 delegate_->LoginAsPublicAccount(username);
1089 void SigninScreenHandler::HandleOfflineLogin(const base::ListValue* args) {
1090 if (!delegate_ || delegate_->IsShowUsers()) {
1091 NOTREACHED();
1092 return;
1094 if (!args->GetString(0, &email_))
1095 email_.clear();
1096 // Load auth extension. Parameters are: force reload, do not load extension in
1097 // background, use offline version.
1098 LoadAuthExtension(true, false, true);
1099 UpdateUIState(UI_STATE_GAIA_SIGNIN, NULL);
1102 void SigninScreenHandler::HandleShutdownSystem() {
1103 ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
1106 void SigninScreenHandler::HandleLoadWallpaper(const std::string& email) {
1107 if (delegate_)
1108 delegate_->LoadWallpaper(email);
1111 void SigninScreenHandler::HandleRebootSystem() {
1112 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
1115 void SigninScreenHandler::HandleRemoveUser(const std::string& email) {
1116 if (!delegate_)
1117 return;
1118 delegate_->RemoveUser(email);
1119 UpdateAddButtonStatus();
1122 void SigninScreenHandler::HandleShowAddUser(const base::ListValue* args) {
1123 TRACE_EVENT_ASYNC_STEP_INTO0("ui",
1124 "ShowLoginWebUI",
1125 LoginDisplayHostImpl::kShowLoginWebUIid,
1126 "ShowAddUser");
1127 std::string email;
1128 // |args| can be null if it's OOBE.
1129 if (args)
1130 args->GetString(0, &email);
1131 OnShowAddUser(email);
1134 void SigninScreenHandler::HandleToggleEnrollmentScreen() {
1135 if (delegate_)
1136 delegate_->ShowEnterpriseEnrollmentScreen();
1139 void SigninScreenHandler::HandleToggleKioskEnableScreen() {
1140 policy::BrowserPolicyConnectorChromeOS* connector =
1141 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1142 if (delegate_ &&
1143 !wait_for_auto_enrollment_check_ &&
1144 !connector->IsEnterpriseManaged()) {
1145 wait_for_auto_enrollment_check_ = true;
1147 LoginDisplayHostImpl::default_host()->GetAutoEnrollmentCheckResult(
1148 base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow,
1149 weak_factory_.GetWeakPtr()));
1153 void SigninScreenHandler::HandleToggleResetScreen() {
1154 policy::BrowserPolicyConnectorChromeOS* connector =
1155 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1156 if (delegate_ && !connector->IsEnterpriseManaged())
1157 delegate_->ShowResetScreen();
1160 void SigninScreenHandler::HandleToggleKioskAutolaunchScreen() {
1161 policy::BrowserPolicyConnectorChromeOS* connector =
1162 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1163 if (delegate_ && !connector->IsEnterpriseManaged())
1164 delegate_->ShowKioskAutolaunchScreen();
1167 void SigninScreenHandler::HandleLaunchHelpApp(double help_topic_id) {
1168 if (!delegate_)
1169 return;
1170 if (!help_app_.get())
1171 help_app_ = new HelpAppLauncher(GetNativeWindow());
1172 help_app_->ShowHelpTopic(
1173 static_cast<HelpAppLauncher::HelpTopic>(help_topic_id));
1176 void SigninScreenHandler::FillUserDictionary(User* user,
1177 bool is_owner,
1178 base::DictionaryValue* user_dict) {
1179 const std::string& email = user->email();
1180 const bool is_public_account =
1181 user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT;
1182 const bool is_locally_managed_user =
1183 user->GetType() == User::USER_TYPE_LOCALLY_MANAGED;
1184 const User::OAuthTokenStatus token_status = user->oauth_token_status();
1186 // Force online sign-in if at least one of the following is true:
1187 // * The flag to force online sign-in is set for the user.
1188 // * The user's oauth token is invalid.
1189 // * The user's oauth token status is unknown. This condition does not apply
1190 // to supervised users: A supervised user whose oauth token status is
1191 // unknown may still log in offline. The token will be invalidated inside
1192 // the session in case it has been revoked.
1193 const bool force_online_signin =
1194 user->force_online_signin() ||
1195 (token_status == User::OAUTH2_TOKEN_STATUS_INVALID) ||
1196 (!is_locally_managed_user &&
1197 token_status == User::OAUTH_TOKEN_STATUS_UNKNOWN);
1199 user_dict->SetString(kKeyUsername, email);
1200 user_dict->SetString(kKeyEmailAddress, user->display_email());
1201 user_dict->SetString(kKeyDisplayName, user->GetDisplayName());
1202 user_dict->SetBoolean(kKeyPublicAccount, is_public_account);
1203 user_dict->SetBoolean(kKeyLocallyManagedUser, is_locally_managed_user);
1204 user_dict->SetInteger(kKeyForceOnlineSignin, force_online_signin);
1205 user_dict->SetBoolean(kKeySignedIn, user->is_logged_in());
1206 user_dict->SetBoolean(kKeyIsOwner, is_owner);
1208 if (is_public_account) {
1209 policy::BrowserPolicyConnectorChromeOS* policy_connector =
1210 g_browser_process->platform_part()->browser_policy_connector_chromeos();
1212 if (policy_connector->IsEnterpriseManaged()) {
1213 user_dict->SetString(kKeyEnterpriseDomain,
1214 policy_connector->GetEnterpriseDomain());
1219 void SigninScreenHandler::SendUserList(bool animated) {
1220 if (!delegate_)
1221 return;
1222 TRACE_EVENT_ASYNC_STEP_INTO0("ui",
1223 "ShowLoginWebUI",
1224 LoginDisplayHostImpl::kShowLoginWebUIid,
1225 "SendUserList");
1226 BootTimesLoader::Get()->RecordCurrentStats("login-send-user-list");
1228 size_t max_non_owner_users = kMaxUsers - 1;
1229 size_t non_owner_count = 0;
1231 base::ListValue users_list;
1232 size_t first_non_public_account_index = 0;
1233 const UserList& users = delegate_->GetUsers();
1235 // TODO(nkostylev): Move to a separate method in UserManager.
1236 // http://crbug.com/230852
1237 bool is_signin_to_add = LoginDisplayHostImpl::default_host() &&
1238 UserManager::Get()->IsUserLoggedIn();
1240 bool single_user = users.size() == 1;
1241 std::string owner;
1242 chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
1243 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
1244 const std::string& email = (*it)->email();
1245 bool is_owner = (email == owner);
1247 if (non_owner_count < max_non_owner_users || is_owner) {
1248 base::DictionaryValue* user_dict = new base::DictionaryValue();
1249 FillUserDictionary(*it, is_owner, user_dict);
1250 bool is_public_account =
1251 ((*it)->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT);
1252 bool signed_in = (*it)->is_logged_in();
1253 // Single user check here is necessary because owner info might not be
1254 // available when running into login screen on first boot.
1255 // See http://crosbug.com/12723
1256 user_dict->SetBoolean(kKeyCanRemove,
1257 !single_user &&
1258 !email.empty() &&
1259 !is_owner &&
1260 !is_public_account &&
1261 !signed_in &&
1262 !is_signin_to_add);
1264 // public accounts come first in the list
1265 if (is_public_account)
1266 users_list.Insert(first_non_public_account_index++, user_dict);
1267 else
1268 users_list.Append(user_dict);
1269 if (!is_owner)
1270 ++non_owner_count;
1274 CallJS("login.AccountPickerScreen.loadUsers", users_list, animated,
1275 delegate_->IsShowGuest());
1278 void SigninScreenHandler::HandleAccountPickerReady() {
1279 VLOG(0) << "Login WebUI >> AccountPickerReady";
1281 if (delegate_ && !ScreenLocker::default_screen_locker() &&
1282 !chromeos::IsMachineHWIDCorrect() &&
1283 !oobe_ui_) {
1284 delegate_->ShowWrongHWIDScreen();
1285 return;
1288 PrefService* prefs = g_browser_process->local_state();
1289 if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
1290 prefs->SetBoolean(prefs::kFactoryResetRequested, false);
1291 prefs->CommitPendingWrite();
1292 HandleToggleResetScreen();
1293 return;
1296 is_account_picker_showing_first_time_ = true;
1297 MaybePreloadAuthExtension();
1299 if (ScreenLocker::default_screen_locker())
1300 ScreenLocker::default_screen_locker()->delegate()->OnLockWebUIReady();
1302 if (delegate_)
1303 delegate_->OnSigninScreenReady();
1306 void SigninScreenHandler::HandleWallpaperReady() {
1307 if (ScreenLocker::default_screen_locker()) {
1308 ScreenLocker::default_screen_locker()->delegate()->
1309 OnLockBackgroundDisplayed();
1313 void SigninScreenHandler::HandleLoginWebuiReady() {
1314 if (focus_stolen_) {
1315 // Set focus to the Gaia page.
1316 // TODO(altimofeev): temporary solution, until focus parameters are
1317 // implemented on the Gaia side.
1318 // Do this only once. Any subsequent call would relod GAIA frame.
1319 focus_stolen_ = false;
1320 const char code[] = "gWindowOnLoad();";
1321 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1322 rvh->ExecuteJavascriptInWebFrame(
1323 base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1324 base::ASCIIToUTF16(code));
1326 if (!gaia_silent_load_) {
1327 content::NotificationService::current()->Notify(
1328 chrome::NOTIFICATION_LOGIN_WEBUI_LOADED,
1329 content::NotificationService::AllSources(),
1330 content::NotificationService::NoDetails());
1331 } else {
1332 focus_stolen_ = true;
1333 // Prevent focus stealing by the Gaia page.
1334 // TODO(altimofeev): temporary solution, until focus parameters are
1335 // implemented on the Gaia side.
1336 const char code[] = "var gWindowOnLoad = window.onload; "
1337 "window.onload=function() {};";
1338 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1339 rvh->ExecuteJavascriptInWebFrame(
1340 base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1341 base::ASCIIToUTF16(code));
1342 // As we could miss and window.onload could already be called, restore
1343 // focus to current pod (see crbug/175243).
1344 RefocusCurrentPod();
1346 DCHECK(gaia_screen_handler_);
1347 gaia_screen_handler_->HandleFrameLoadingCompleted(0);
1349 if (test_expects_complete_login_)
1350 SubmitLoginFormForTest();
1353 void SigninScreenHandler::HandleSignOutUser() {
1354 if (delegate_)
1355 delegate_->Signout();
1358 void SigninScreenHandler::HandleNetworkErrorShown() {
1359 content::NotificationService::current()->Notify(
1360 chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
1361 content::NotificationService::AllSources(),
1362 content::NotificationService::NoDetails());
1365 void SigninScreenHandler::HandleCreateAccount() {
1366 if (delegate_)
1367 delegate_->CreateAccount();
1370 void SigninScreenHandler::HandleOpenProxySettings() {
1371 LoginDisplayHostImpl::default_host()->OpenProxySettings();
1374 void SigninScreenHandler::HandleLoginVisible(const std::string& source) {
1375 LOG(WARNING) << "Login WebUI >> loginVisible, src: " << source << ", "
1376 << "webui_visible_: " << webui_visible_;
1377 if (!webui_visible_) {
1378 // There might be multiple messages from OOBE UI so send notifications after
1379 // the first one only.
1380 content::NotificationService::current()->Notify(
1381 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
1382 content::NotificationService::AllSources(),
1383 content::NotificationService::NoDetails());
1384 TRACE_EVENT_ASYNC_END0(
1385 "ui", "ShowLoginWebUI", LoginDisplayHostImpl::kShowLoginWebUIid);
1387 webui_visible_ = true;
1388 if (preferences_changed_delayed_)
1389 OnPreferencesChanged();
1392 void SigninScreenHandler::HandleCancelPasswordChangedFlow() {
1393 StartClearingCookies(base::Bind(
1394 &SigninScreenHandler::CancelPasswordChangedFlowInternal,
1395 weak_factory_.GetWeakPtr()));
1398 void SigninScreenHandler::HandleCancelUserAdding() {
1399 if (delegate_)
1400 delegate_->CancelUserAdding();
1403 void SigninScreenHandler::HandleMigrateUserData(
1404 const std::string& old_password) {
1405 if (delegate_)
1406 delegate_->MigrateUserData(old_password);
1409 void SigninScreenHandler::HandleResyncUserData() {
1410 if (delegate_)
1411 delegate_->ResyncUserData();
1414 void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source,
1415 bool new_value) {
1416 VLOG(0) << "Login WebUI >> active: " << new_value << ", "
1417 << "source: " << source;
1419 if (!KioskAppManager::Get()->GetAutoLaunchApp().empty() &&
1420 KioskAppManager::Get()->IsAutoLaunchRequested()) {
1421 VLOG(0) << "Showing auto-launch warning";
1422 // On slow devices, the wallpaper animation is not shown initially, so we
1423 // must explicitly load the wallpaper. This is also the case for the
1424 // account-picker and gaia-signin UI states.
1425 delegate_->LoadSigninWallpaper();
1426 HandleToggleKioskAutolaunchScreen();
1427 return;
1430 if (source == kSourceGaiaSignin) {
1431 ui_state_ = UI_STATE_GAIA_SIGNIN;
1432 } else if (source == kSourceAccountPicker) {
1433 ui_state_ = UI_STATE_ACCOUNT_PICKER;
1434 } else {
1435 NOTREACHED();
1436 return;
1440 void SigninScreenHandler::HandleUnlockOnLoginSuccess() {
1441 DCHECK(UserManager::Get()->IsUserLoggedIn());
1442 if (ScreenLocker::default_screen_locker())
1443 ScreenLocker::default_screen_locker()->UnlockOnLoginSuccess();
1446 void SigninScreenHandler::HandleShowLoadingTimeoutError() {
1447 UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
1450 void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
1451 offline_login_active_ = offline_login_active;
1454 void SigninScreenHandler::HandleFocusPod(const std::string& user_id) {
1455 SetUserInputMethod(user_id);
1456 WallpaperManager::Get()->SetUserWallpaperDelayed(user_id);
1459 void SigninScreenHandler::HandleCustomButtonClicked(
1460 const std::string& username) {
1461 if (user_pod_button_callback_map_.find(username)
1462 == user_pod_button_callback_map_.end()) {
1463 LOG(WARNING) << "User pod custom button clicked but no callback found";
1464 return;
1466 user_pod_button_callback_map_[username].Run();
1469 void SigninScreenHandler::HandleRetrieveAuthenticatedUserEmail(
1470 double attempt_token) {
1471 email_retriever_.reset(new AuthenticatedUserEmailRetriever(
1472 base::Bind(&SigninScreenHandler::CallJS<double, std::string>,
1473 base::Unretained(this),
1474 "login.GaiaSigninScreen.setAuthenticatedUserEmail",
1475 attempt_token),
1476 Profile::FromWebUI(web_ui())->GetRequestContext()));
1479 void SigninScreenHandler::HandleLaunchKioskApp(const std::string& app_id) {
1480 delegate_->LoginAsKioskApp(app_id);
1483 void SigninScreenHandler::StartClearingDnsCache() {
1484 if (dns_clear_task_running_ || !g_browser_process->io_thread())
1485 return;
1487 dns_cleared_ = false;
1488 BrowserThread::PostTaskAndReply(
1489 BrowserThread::IO, FROM_HERE,
1490 base::Bind(&ClearDnsCache, g_browser_process->io_thread()),
1491 base::Bind(&SigninScreenHandler::OnDnsCleared,
1492 weak_factory_.GetWeakPtr()));
1493 dns_clear_task_running_ = true;
1496 void SigninScreenHandler::StartClearingCookies(
1497 const base::Closure& on_clear_callback) {
1498 cookies_cleared_ = false;
1499 ProfileHelper* profile_helper =
1500 g_browser_process->platform_part()->profile_helper();
1501 LOG_ASSERT(
1502 Profile::FromWebUI(web_ui()) == profile_helper->GetSigninProfile());
1503 profile_helper->ClearSigninProfile(base::Bind(
1504 &SigninScreenHandler::OnCookiesCleared,
1505 weak_factory_.GetWeakPtr(), on_clear_callback));
1508 void SigninScreenHandler::MaybePreloadAuthExtension() {
1509 LOG(WARNING) << "MaybePreloadAuthExtension() call.";
1511 // Fetching of the extension is not started before account picker page is
1512 // loaded because it can affect the loading speed. Also if cookies clearing
1513 // was initiated or |dns_clear_task_running_| then auth extension showing has
1514 // already been initiated and preloading is senseless.
1515 // Do not load the extension for the screen locker, see crosbug.com/25018.
1516 if (is_account_picker_showing_first_time_ &&
1517 !gaia_silent_load_ &&
1518 !ScreenLocker::default_screen_locker() &&
1519 !cookies_cleared_ &&
1520 !dns_clear_task_running_ &&
1521 network_state_informer_->state() == NetworkStateInformer::ONLINE) {
1522 gaia_silent_load_ = true;
1523 gaia_silent_load_network_ = network_state_informer_->network_path();
1524 LoadAuthExtension(true, true, false);
1528 bool SigninScreenHandler::AllWhitelistedUsersPresent() {
1529 CrosSettings* cros_settings = CrosSettings::Get();
1530 bool allow_new_user = false;
1531 cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
1532 if (allow_new_user)
1533 return false;
1534 UserManager* user_manager = UserManager::Get();
1535 const UserList& users = user_manager->GetUsers();
1536 if (!delegate_ || users.size() > kMaxUsers) {
1537 return false;
1539 const base::ListValue* whitelist = NULL;
1540 if (!cros_settings->GetList(kAccountsPrefUsers, &whitelist) || !whitelist)
1541 return false;
1542 for (size_t i = 0; i < whitelist->GetSize(); ++i) {
1543 std::string whitelisted_user;
1544 // NB: Wildcards in the whitelist are also detected as not present here.
1545 if (!whitelist->GetString(i, &whitelisted_user) ||
1546 !user_manager->IsKnownUser(whitelisted_user)) {
1547 return false;
1550 return true;
1553 void SigninScreenHandler::CancelPasswordChangedFlowInternal() {
1554 if (delegate_) {
1555 ShowImpl();
1556 delegate_->CancelPasswordChangedFlow();
1560 OobeUI::Screen SigninScreenHandler::GetCurrentScreen() const {
1561 OobeUI::Screen screen = OobeUI::SCREEN_UNKNOWN;
1562 OobeUI* oobe_ui = static_cast<OobeUI*>(web_ui()->GetController());
1563 if (oobe_ui)
1564 screen = oobe_ui->current_screen();
1565 return screen;
1568 bool SigninScreenHandler::IsGaiaVisible() const {
1569 return IsSigninScreen(GetCurrentScreen()) &&
1570 ui_state_ == UI_STATE_GAIA_SIGNIN;
1573 bool SigninScreenHandler::IsGaiaHiddenByError() const {
1574 return IsSigninScreenHiddenByError() &&
1575 ui_state_ == UI_STATE_GAIA_SIGNIN;
1578 bool SigninScreenHandler::IsSigninScreenHiddenByError() const {
1579 return (GetCurrentScreen() == OobeUI::SCREEN_ERROR_MESSAGE) &&
1580 (IsSigninScreen(error_screen_actor_->parent_screen()));
1583 bool SigninScreenHandler::IsGuestSigninAllowed() const {
1584 CrosSettings* cros_settings = CrosSettings::Get();
1585 if (!cros_settings)
1586 return false;
1587 bool allow_guest;
1588 cros_settings->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
1589 return allow_guest;
1592 bool SigninScreenHandler::IsOfflineLoginAllowed() const {
1593 CrosSettings* cros_settings = CrosSettings::Get();
1594 if (!cros_settings)
1595 return false;
1597 // Offline login is allowed only when user pods are hidden.
1598 bool show_pods;
1599 cros_settings->GetBoolean(kAccountsPrefShowUserNamesOnSignIn, &show_pods);
1600 return !show_pods;
1603 void SigninScreenHandler::SubmitLoginFormForTest() {
1604 VLOG(2) << "Submit login form for test, user=" << test_user_;
1606 std::string code;
1607 code += "document.getElementById('Email').value = '" + test_user_ + "';";
1608 code += "document.getElementById('Passwd').value = '" + test_pass_ + "';";
1609 code += "document.getElementById('signIn').click();";
1611 RenderViewHost* rvh = web_ui()->GetWebContents()->GetRenderViewHost();
1612 rvh->ExecuteJavascriptInWebFrame(
1613 base::ASCIIToUTF16("//iframe[@id='signin-frame']\n//iframe"),
1614 base::ASCIIToUTF16(code));
1616 // Test properties are cleared in HandleCompleteLogin because the form
1617 // submission might fail and login will not be attempted after reloading
1618 // if they are cleared here.
1621 void SigninScreenHandler::ContinueKioskEnableFlow(bool should_auto_enroll) {
1622 wait_for_auto_enrollment_check_ = false;
1624 // Do not proceed with kiosk enable when auto enroll will be enforced.
1625 // TODO(xiyuan): Add an error UI feedkback so user knows what happens.
1626 if (should_auto_enroll) {
1627 LOG(WARNING) << "Kiosk enable flow aborted because auto enrollment is "
1628 "going to be enforced.";
1630 if (!kiosk_enable_flow_aborted_callback_for_test_.is_null())
1631 kiosk_enable_flow_aborted_callback_for_test_.Run();
1632 return;
1635 if (delegate_)
1636 delegate_->ShowKioskEnableScreen();
1639 void SigninScreenHandler::OnShowAddUser(const std::string& email) {
1640 email_ = email;
1641 is_account_picker_showing_first_time_ = false;
1643 if (gaia_silent_load_ && email_.empty()) {
1644 dns_cleared_ = true;
1645 cookies_cleared_ = true;
1646 ShowSigninScreenIfReady();
1647 } else {
1648 StartClearingDnsCache();
1649 StartClearingCookies(base::Bind(
1650 &SigninScreenHandler::ShowSigninScreenIfReady,
1651 weak_factory_.GetWeakPtr()));
1655 GaiaScreenHandler::FrameState SigninScreenHandler::FrameState() const {
1656 DCHECK(gaia_screen_handler_);
1657 return gaia_screen_handler_->frame_state();
1660 net::Error SigninScreenHandler::FrameError() const {
1661 DCHECK(gaia_screen_handler_);
1662 return gaia_screen_handler_->frame_error();
1665 } // namespace chromeos