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