1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h" 6 7#include "ash/magnifier/magnifier_constants.h" 8#include "ash/shell.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/values.h" 11#include "chrome/browser/browser_process.h" 12#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" 13#include "chrome/browser/chromeos/accessibility/magnification_manager.h" 14#include "chrome/browser/chromeos/login/helper.h" 15#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" 16#include "chrome/browser/chromeos/login/wizard_controller.h" 17#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 18#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" 19#include "chrome/browser/chromeos/system/input_device_settings.h" 20#include "chrome/browser/lifetime/application_lifetime.h" 21#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 22#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" 23#include "chrome/common/chrome_constants.h" 24#include "chrome/common/chrome_version_info.h" 25#include "chrome/grit/chromium_strings.h" 26#include "chrome/grit/generated_resources.h" 27#include "chromeos/chromeos_constants.h" 28#include "grit/components_strings.h" 29#include "ui/gfx/display.h" 30#include "ui/gfx/screen.h" 31#include "ui/gfx/size.h" 32#include "ui/keyboard/keyboard_controller.h" 33 34namespace { 35 36const char kJsScreenPath[] = "cr.ui.Oobe"; 37 38// JS API callbacks names. 39const char kJsApiEnableHighContrast[] = "enableHighContrast"; 40const char kJsApiEnableVirtualKeyboard[] = "enableVirtualKeyboard"; 41const char kJsApiEnableScreenMagnifier[] = "enableScreenMagnifier"; 42const char kJsApiEnableLargeCursor[] = "enableLargeCursor"; 43const char kJsApiEnableSpokenFeedback[] = "enableSpokenFeedback"; 44const char kJsApiScreenStateInitialize[] = "screenStateInitialize"; 45const char kJsApiSkipUpdateEnrollAfterEula[] = "skipUpdateEnrollAfterEula"; 46const char kJsApiScreenAssetsLoaded[] = "screenAssetsLoaded"; 47const char kJsApiHeaderBarVisible[] = "headerBarVisible"; 48 49} // namespace 50 51namespace chromeos { 52 53// Note that show_oobe_ui_ defaults to false because WizardController assumes 54// OOBE UI is not visible by default. 55CoreOobeHandler::CoreOobeHandler(OobeUI* oobe_ui) 56 : BaseScreenHandler(kJsScreenPath), 57 oobe_ui_(oobe_ui), 58 show_oobe_ui_(false), 59 version_info_updater_(this), 60 delegate_(NULL) { 61 AccessibilityManager* accessibility_manager = AccessibilityManager::Get(); 62 CHECK(accessibility_manager); 63 accessibility_subscription_ = accessibility_manager->RegisterCallback( 64 base::Bind(&CoreOobeHandler::OnAccessibilityStatusChanged, 65 base::Unretained(this))); 66} 67 68CoreOobeHandler::~CoreOobeHandler() { 69} 70 71void CoreOobeHandler::SetDelegate(Delegate* delegate) { 72 delegate_ = delegate; 73} 74 75void CoreOobeHandler::DeclareLocalizedValues(LocalizedValuesBuilder* builder) { 76 builder->Add("title", IDS_SHORT_PRODUCT_NAME); 77 builder->Add("productName", IDS_SHORT_PRODUCT_NAME); 78 builder->Add("learnMore", IDS_LEARN_MORE); 79 80 // OOBE accessibility options menu strings shown on each screen. 81 builder->Add("accessibilityLink", IDS_OOBE_ACCESSIBILITY_LINK); 82 builder->Add("spokenFeedbackOption", IDS_OOBE_SPOKEN_FEEDBACK_OPTION); 83 builder->Add("largeCursorOption", IDS_OOBE_LARGE_CURSOR_OPTION); 84 builder->Add("highContrastOption", IDS_OOBE_HIGH_CONTRAST_MODE_OPTION); 85 builder->Add("screenMagnifierOption", IDS_OOBE_SCREEN_MAGNIFIER_OPTION); 86 builder->Add("virtualKeyboardOption", IDS_OOBE_VIRTUAL_KEYBOARD_OPTION); 87 builder->Add("closeAccessibilityMenu", IDS_OOBE_CLOSE_ACCESSIBILITY_MENU); 88 89 // Strings for the device requisition prompt. 90 builder->Add("deviceRequisitionPromptCancel", 91 IDS_ENTERPRISE_DEVICE_REQUISITION_PROMPT_CANCEL); 92 builder->Add("deviceRequisitionPromptOk", 93 IDS_ENTERPRISE_DEVICE_REQUISITION_PROMPT_OK); 94 builder->Add("deviceRequisitionPromptText", 95 IDS_ENTERPRISE_DEVICE_REQUISITION_PROMPT_TEXT); 96 builder->Add("deviceRequisitionRemoraPromptCancel", 97 IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); 98 builder->Add("deviceRequisitionRemoraPromptOk", 99 IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL); 100 builder->Add("deviceRequisitionRemoraPromptText", 101 IDS_ENTERPRISE_DEVICE_REQUISITION_REMORA_PROMPT_TEXT); 102 builder->Add("deviceRequisitionSharkPromptText", 103 IDS_ENTERPRISE_DEVICE_REQUISITION_SHARK_PROMPT_TEXT); 104} 105 106void CoreOobeHandler::Initialize() { 107 UpdateA11yState(); 108 UpdateOobeUIVisibility(); 109#if defined(OFFICIAL_BUILD) 110 version_info_updater_.StartUpdate(true); 111#else 112 version_info_updater_.StartUpdate(false); 113#endif 114 UpdateDeviceRequisition(); 115 UpdateKeyboardState(); 116 UpdateClientAreaSize(); 117} 118 119void CoreOobeHandler::RegisterMessages() { 120 AddCallback(kJsApiScreenStateInitialize, 121 &CoreOobeHandler::HandleInitialized); 122 AddCallback(kJsApiSkipUpdateEnrollAfterEula, 123 &CoreOobeHandler::HandleSkipUpdateEnrollAfterEula); 124 AddCallback("updateCurrentScreen", 125 &CoreOobeHandler::HandleUpdateCurrentScreen); 126 AddCallback(kJsApiEnableHighContrast, 127 &CoreOobeHandler::HandleEnableHighContrast); 128 AddCallback(kJsApiEnableLargeCursor, 129 &CoreOobeHandler::HandleEnableLargeCursor); 130 AddCallback(kJsApiEnableVirtualKeyboard, 131 &CoreOobeHandler::HandleEnableVirtualKeyboard); 132 AddCallback(kJsApiEnableScreenMagnifier, 133 &CoreOobeHandler::HandleEnableScreenMagnifier); 134 AddCallback(kJsApiEnableSpokenFeedback, 135 &CoreOobeHandler::HandleEnableSpokenFeedback); 136 AddCallback("setDeviceRequisition", 137 &CoreOobeHandler::HandleSetDeviceRequisition); 138 AddCallback(kJsApiScreenAssetsLoaded, 139 &CoreOobeHandler::HandleScreenAssetsLoaded); 140 AddRawCallback("skipToLoginForTesting", 141 &CoreOobeHandler::HandleSkipToLoginForTesting); 142 AddCallback("launchHelpApp", 143 &CoreOobeHandler::HandleLaunchHelpApp); 144 AddCallback("toggleResetScreen", &CoreOobeHandler::HandleToggleResetScreen); 145 AddCallback(kJsApiHeaderBarVisible, 146 &CoreOobeHandler::HandleHeaderBarVisible); 147} 148 149void CoreOobeHandler::ShowSignInError( 150 int login_attempts, 151 const std::string& error_text, 152 const std::string& help_link_text, 153 HelpAppLauncher::HelpTopic help_topic_id) { 154 LOG(ERROR) << "CoreOobeHandler::ShowSignInError: error_text=" << error_text; 155 CallJS("showSignInError", login_attempts, error_text, 156 help_link_text, static_cast<int>(help_topic_id)); 157} 158 159void CoreOobeHandler::ShowTpmError() { 160 CallJS("showTpmError"); 161} 162 163void CoreOobeHandler::ShowDeviceResetScreen() { 164 policy::BrowserPolicyConnectorChromeOS* connector = 165 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 166 if (!connector->IsEnterpriseManaged()) { 167 // Don't recreate WizardController if it already exists. 168 WizardController* wizard_controller = 169 WizardController::default_controller(); 170 if (wizard_controller && !wizard_controller->login_screen_started()) { 171 wizard_controller->AdvanceToScreen(WizardController::kResetScreenName); 172 } else { 173 scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue()); 174 DCHECK(LoginDisplayHostImpl::default_host()); 175 if (LoginDisplayHostImpl::default_host()) { 176 LoginDisplayHostImpl::default_host()->StartWizard( 177 WizardController::kResetScreenName, params.Pass()); 178 } 179 } 180 } 181} 182 183void CoreOobeHandler::ShowSignInUI(const std::string& email) { 184 CallJS("showSigninUI", email); 185} 186 187void CoreOobeHandler::ResetSignInUI(bool force_online) { 188 CallJS("resetSigninUI", force_online); 189} 190 191void CoreOobeHandler::ClearUserPodPassword() { 192 CallJS("clearUserPodPassword"); 193} 194 195void CoreOobeHandler::RefocusCurrentPod() { 196 CallJS("refocusCurrentPod"); 197} 198 199void CoreOobeHandler::ShowPasswordChangedScreen(bool show_password_error) { 200 CallJS("showPasswordChangedScreen", show_password_error); 201} 202 203void CoreOobeHandler::SetUsageStats(bool checked) { 204 CallJS("setUsageStats", checked); 205} 206 207void CoreOobeHandler::SetOemEulaUrl(const std::string& oem_eula_url) { 208 CallJS("setOemEulaUrl", oem_eula_url); 209} 210 211void CoreOobeHandler::SetTpmPassword(const std::string& tpm_password) { 212 CallJS("setTpmPassword", tpm_password); 213} 214 215void CoreOobeHandler::ClearErrors() { 216 CallJS("clearErrors"); 217} 218 219void CoreOobeHandler::ReloadContent(const base::DictionaryValue& dictionary) { 220 CallJS("reloadContent", dictionary); 221} 222 223void CoreOobeHandler::ShowControlBar(bool show) { 224 CallJS("showControlBar", show); 225} 226 227void CoreOobeHandler::SetKeyboardState(bool shown, const gfx::Rect& bounds) { 228 CallJS("setKeyboardState", shown, bounds.width(), bounds.height()); 229} 230 231void CoreOobeHandler::SetClientAreaSize(int width, int height) { 232 CallJS("setClientAreaSize", width, height); 233} 234 235void CoreOobeHandler::HandleInitialized() { 236 oobe_ui_->InitializeHandlers(); 237} 238 239void CoreOobeHandler::HandleSkipUpdateEnrollAfterEula() { 240 WizardController* controller = WizardController::default_controller(); 241 DCHECK(controller); 242 if (controller) 243 controller->SkipUpdateEnrollAfterEula(); 244} 245 246void CoreOobeHandler::HandleUpdateCurrentScreen(const std::string& screen) { 247 if (delegate_) 248 delegate_->OnCurrentScreenChanged(screen); 249} 250 251void CoreOobeHandler::HandleEnableHighContrast(bool enabled) { 252 AccessibilityManager::Get()->EnableHighContrast(enabled); 253} 254 255void CoreOobeHandler::HandleEnableLargeCursor(bool enabled) { 256 AccessibilityManager::Get()->EnableLargeCursor(enabled); 257} 258 259void CoreOobeHandler::HandleEnableVirtualKeyboard(bool enabled) { 260 AccessibilityManager::Get()->EnableVirtualKeyboard(enabled); 261} 262 263void CoreOobeHandler::HandleEnableScreenMagnifier(bool enabled) { 264 // TODO(nkostylev): Add support for partial screen magnifier. 265 DCHECK(MagnificationManager::Get()); 266 MagnificationManager::Get()->SetMagnifierEnabled(enabled); 267} 268 269void CoreOobeHandler::HandleEnableSpokenFeedback() { 270 // Checkbox is initialized on page init and updates when spoken feedback 271 // setting is changed so just toggle spoken feedback here. 272 AccessibilityManager::Get()->ToggleSpokenFeedback( 273 ash::A11Y_NOTIFICATION_NONE); 274} 275 276void CoreOobeHandler::HandleSetDeviceRequisition( 277 const std::string& requisition) { 278 policy::BrowserPolicyConnectorChromeOS* connector = 279 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 280 std::string initial_requisition = 281 connector->GetDeviceCloudPolicyManager()->GetDeviceRequisition(); 282 connector->GetDeviceCloudPolicyManager()->SetDeviceRequisition(requisition); 283 // Exit Chrome to force the restart as soon as a new requisition is set. 284 if (initial_requisition != 285 connector->GetDeviceCloudPolicyManager()->GetDeviceRequisition()) { 286 chrome::AttemptRestart(); 287 } 288} 289 290void CoreOobeHandler::HandleScreenAssetsLoaded( 291 const std::string& screen_async_load_id) { 292 oobe_ui_->OnScreenAssetsLoaded(screen_async_load_id); 293} 294 295void CoreOobeHandler::HandleSkipToLoginForTesting( 296 const base::ListValue* args) { 297 LoginScreenContext context(args); 298 if (WizardController::default_controller()) 299 WizardController::default_controller()->SkipToLoginForTesting(context); 300} 301 302void CoreOobeHandler::HandleToggleResetScreen() { ShowDeviceResetScreen(); } 303 304void CoreOobeHandler::ShowOobeUI(bool show) { 305 if (show == show_oobe_ui_) 306 return; 307 308 show_oobe_ui_ = show; 309 310 if (page_is_ready()) 311 UpdateOobeUIVisibility(); 312} 313 314void CoreOobeHandler::UpdateA11yState() { 315#if !defined(USE_ATHENA) 316 // TODO(dpolukhin): crbug.com/412891 317 DCHECK(MagnificationManager::Get()); 318 base::DictionaryValue a11y_info; 319 a11y_info.SetBoolean("highContrastEnabled", 320 AccessibilityManager::Get()->IsHighContrastEnabled()); 321 a11y_info.SetBoolean("largeCursorEnabled", 322 AccessibilityManager::Get()->IsLargeCursorEnabled()); 323 a11y_info.SetBoolean("spokenFeedbackEnabled", 324 AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); 325 a11y_info.SetBoolean("screenMagnifierEnabled", 326 MagnificationManager::Get()->IsMagnifierEnabled()); 327 a11y_info.SetBoolean("virtualKeyboardEnabled", 328 AccessibilityManager::Get()->IsVirtualKeyboardEnabled()); 329 CallJS("refreshA11yInfo", a11y_info); 330#endif 331} 332 333void CoreOobeHandler::UpdateOobeUIVisibility() { 334 // Don't show version label on the stable channel by default. 335 bool should_show_version = true; 336 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 337 if (channel == chrome::VersionInfo::CHANNEL_STABLE || 338 channel == chrome::VersionInfo::CHANNEL_BETA) { 339 should_show_version = false; 340 } 341 CallJS("showVersion", should_show_version); 342 CallJS("showOobeUI", show_oobe_ui_); 343 if (system::InputDeviceSettings::Get()->ForceKeyboardDrivenUINavigation()) 344 CallJS("enableKeyboardFlow", true); 345} 346 347void CoreOobeHandler::OnOSVersionLabelTextUpdated( 348 const std::string& os_version_label_text) { 349 UpdateLabel("version", os_version_label_text); 350} 351 352void CoreOobeHandler::OnEnterpriseInfoUpdated( 353 const std::string& message_text) { 354 CallJS("setEnterpriseInfo", message_text); 355} 356 357void CoreOobeHandler::UpdateLabel(const std::string& id, 358 const std::string& text) { 359 CallJS("setLabelText", id, text); 360} 361 362void CoreOobeHandler::UpdateDeviceRequisition() { 363 policy::BrowserPolicyConnectorChromeOS* connector = 364 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 365 CallJS("updateDeviceRequisition", 366 connector->GetDeviceCloudPolicyManager()->GetDeviceRequisition()); 367} 368 369void CoreOobeHandler::UpdateKeyboardState() { 370 if (!login::LoginScrollIntoViewEnabled()) 371 return; 372 373 keyboard::KeyboardController* keyboard_controller = 374 keyboard::KeyboardController::GetInstance(); 375 if (keyboard_controller) { 376 gfx::Rect bounds = keyboard_controller->current_keyboard_bounds(); 377 SetKeyboardState(!bounds.IsEmpty(), bounds); 378 } 379} 380 381void CoreOobeHandler::UpdateClientAreaSize() { 382 const gfx::Size& size = ash::Shell::GetScreen()->GetPrimaryDisplay().size(); 383 SetClientAreaSize(size.width(), size.height()); 384} 385 386void CoreOobeHandler::OnAccessibilityStatusChanged( 387 const AccessibilityStatusEventDetails& details) { 388 if (details.notification_type == ACCESSIBILITY_MANAGER_SHUTDOWN) 389 accessibility_subscription_.reset(); 390 else 391 UpdateA11yState(); 392} 393 394void CoreOobeHandler::HandleLaunchHelpApp(double help_topic_id) { 395 if (!help_app_.get()) 396 help_app_ = new HelpAppLauncher(GetNativeWindow()); 397 help_app_->ShowHelpTopic( 398 static_cast<HelpAppLauncher::HelpTopic>(help_topic_id)); 399} 400 401void CoreOobeHandler::HandleHeaderBarVisible() { 402 LoginDisplayHost* login_display_host = LoginDisplayHostImpl::default_host(); 403 if (login_display_host) 404 login_display_host->SetStatusAreaVisible(true); 405} 406 407void CoreOobeHandler::InitDemoModeDetection() { 408 demo_mode_detector_.InitDetection(); 409} 410 411void CoreOobeHandler::StopDemoModeDetection() { 412 demo_mode_detector_.StopDetection(); 413} 414 415} // namespace chromeos 416