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 34 namespace { 35 36 const char kJsScreenPath[] = "cr.ui.Oobe"; 37 38 // JS API callbacks names. 39 const char kJsApiEnableHighContrast[] = "enableHighContrast"; 40 const char kJsApiEnableVirtualKeyboard[] = "enableVirtualKeyboard"; 41 const char kJsApiEnableScreenMagnifier[] = "enableScreenMagnifier"; 42 const char kJsApiEnableLargeCursor[] = "enableLargeCursor"; 43 const char kJsApiEnableSpokenFeedback[] = "enableSpokenFeedback"; 44 const char kJsApiScreenStateInitialize[] = "screenStateInitialize"; 45 const char kJsApiSkipUpdateEnrollAfterEula[] = "skipUpdateEnrollAfterEula"; 46 const char kJsApiScreenAssetsLoaded[] = "screenAssetsLoaded"; 47 const char kJsApiHeaderBarVisible[] = "headerBarVisible"; 48 49 } // namespace 50 51 namespace chromeos { 52 53 // Note that show_oobe_ui_ defaults to false because WizardController assumes 54 // OOBE UI is not visible by default. 55 CoreOobeHandler::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 68 CoreOobeHandler::~CoreOobeHandler() { 69 } 70 71 void CoreOobeHandler::SetDelegate(Delegate* delegate) { 72 delegate_ = delegate; 73 } 74 75 void 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 106 void 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 119 void 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 149 void 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 159 void CoreOobeHandler::ShowTpmError() { 160 CallJS("showTpmError"); 161 } 162 163 void 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 183 void CoreOobeHandler::ShowSignInUI(const std::string& email) { 184 CallJS("showSigninUI", email); 185 } 186 187 void CoreOobeHandler::ResetSignInUI(bool force_online) { 188 CallJS("resetSigninUI", force_online); 189 } 190 191 void CoreOobeHandler::ClearUserPodPassword() { 192 CallJS("clearUserPodPassword"); 193 } 194 195 void CoreOobeHandler::RefocusCurrentPod() { 196 CallJS("refocusCurrentPod"); 197 } 198 199 void CoreOobeHandler::ShowPasswordChangedScreen(bool show_password_error) { 200 CallJS("showPasswordChangedScreen", show_password_error); 201 } 202 203 void CoreOobeHandler::SetUsageStats(bool checked) { 204 CallJS("setUsageStats", checked); 205 } 206 207 void CoreOobeHandler::SetOemEulaUrl(const std::string& oem_eula_url) { 208 CallJS("setOemEulaUrl", oem_eula_url); 209 } 210 211 void CoreOobeHandler::SetTpmPassword(const std::string& tpm_password) { 212 CallJS("setTpmPassword", tpm_password); 213 } 214 215 void CoreOobeHandler::ClearErrors() { 216 CallJS("clearErrors"); 217 } 218 219 void CoreOobeHandler::ReloadContent(const base::DictionaryValue& dictionary) { 220 CallJS("reloadContent", dictionary); 221 } 222 223 void CoreOobeHandler::ShowControlBar(bool show) { 224 CallJS("showControlBar", show); 225 } 226 227 void CoreOobeHandler::SetKeyboardState(bool shown, const gfx::Rect& bounds) { 228 CallJS("setKeyboardState", shown, bounds.width(), bounds.height()); 229 } 230 231 void CoreOobeHandler::SetClientAreaSize(int width, int height) { 232 CallJS("setClientAreaSize", width, height); 233 } 234 235 void CoreOobeHandler::HandleInitialized() { 236 oobe_ui_->InitializeHandlers(); 237 } 238 239 void CoreOobeHandler::HandleSkipUpdateEnrollAfterEula() { 240 WizardController* controller = WizardController::default_controller(); 241 DCHECK(controller); 242 if (controller) 243 controller->SkipUpdateEnrollAfterEula(); 244 } 245 246 void CoreOobeHandler::HandleUpdateCurrentScreen(const std::string& screen) { 247 if (delegate_) 248 delegate_->OnCurrentScreenChanged(screen); 249 } 250 251 void CoreOobeHandler::HandleEnableHighContrast(bool enabled) { 252 AccessibilityManager::Get()->EnableHighContrast(enabled); 253 } 254 255 void CoreOobeHandler::HandleEnableLargeCursor(bool enabled) { 256 AccessibilityManager::Get()->EnableLargeCursor(enabled); 257 } 258 259 void CoreOobeHandler::HandleEnableVirtualKeyboard(bool enabled) { 260 AccessibilityManager::Get()->EnableVirtualKeyboard(enabled); 261 } 262 263 void CoreOobeHandler::HandleEnableScreenMagnifier(bool enabled) { 264 // TODO(nkostylev): Add support for partial screen magnifier. 265 DCHECK(MagnificationManager::Get()); 266 MagnificationManager::Get()->SetMagnifierEnabled(enabled); 267 } 268 269 void 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 276 void 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 290 void CoreOobeHandler::HandleScreenAssetsLoaded( 291 const std::string& screen_async_load_id) { 292 oobe_ui_->OnScreenAssetsLoaded(screen_async_load_id); 293 } 294 295 void CoreOobeHandler::HandleSkipToLoginForTesting( 296 const base::ListValue* args) { 297 LoginScreenContext context(args); 298 if (WizardController::default_controller()) 299 WizardController::default_controller()->SkipToLoginForTesting(context); 300 } 301 302 void CoreOobeHandler::HandleToggleResetScreen() { ShowDeviceResetScreen(); } 303 304 void 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 314 void 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 333 void 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 347 void CoreOobeHandler::OnOSVersionLabelTextUpdated( 348 const std::string& os_version_label_text) { 349 UpdateLabel("version", os_version_label_text); 350 } 351 352 void CoreOobeHandler::OnEnterpriseInfoUpdated( 353 const std::string& message_text) { 354 CallJS("setEnterpriseInfo", message_text); 355 } 356 357 void CoreOobeHandler::UpdateLabel(const std::string& id, 358 const std::string& text) { 359 CallJS("setLabelText", id, text); 360 } 361 362 void 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 369 void 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 381 void CoreOobeHandler::UpdateClientAreaSize() { 382 const gfx::Size& size = ash::Shell::GetScreen()->GetPrimaryDisplay().size(); 383 SetClientAreaSize(size.width(), size.height()); 384 } 385 386 void CoreOobeHandler::OnAccessibilityStatusChanged( 387 const AccessibilityStatusEventDetails& details) { 388 if (details.notification_type == ACCESSIBILITY_MANAGER_SHUTDOWN) 389 accessibility_subscription_.reset(); 390 else 391 UpdateA11yState(); 392 } 393 394 void 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 401 void CoreOobeHandler::HandleHeaderBarVisible() { 402 LoginDisplayHost* login_display_host = LoginDisplayHostImpl::default_host(); 403 if (login_display_host) 404 login_display_host->SetStatusAreaVisible(true); 405 } 406 407 void CoreOobeHandler::InitDemoModeDetection() { 408 demo_mode_detector_.InitDetection(); 409 } 410 411 void CoreOobeHandler::StopDemoModeDetection() { 412 demo_mode_detector_.StopDetection(); 413 } 414 415 } // namespace chromeos 416