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