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 /** 6 * @fileoverview Out of the box experience flow (OOBE). 7 * This is the main code for the OOBE WebUI implementation. 8 */ 9 10 <include src="login_common.js"> 11 <include src="oobe_screen_eula.js"> 12 <include src="oobe_screen_network.js"> 13 <include src="oobe_screen_hid_detection.js"> 14 <include src="oobe_screen_update.js"> 15 <include src="oobe_screen_controller_pairing.js"> 16 <include src="oobe_screen_host_pairing.js"> 17 <include src="oobe_screen_auto_enrollment_check.js"> 18 19 cr.define('cr.ui.Oobe', function() { 20 return { 21 /** 22 * Setups given "select" element using the list and adds callback. 23 * Creates option groups if needed. 24 * @param {!Element} select Select object to be updated. 25 * @param {!Object} list List of the options to be added. 26 * Elements with optionGroupName are considered option group. 27 * @param {string} callback Callback name which should be send to Chrome or 28 * an empty string if the event listener shouldn't be added. 29 */ 30 setupSelect: function(select, list, callback) { 31 select.innerHTML = ''; 32 var optgroup = select; 33 for (var i = 0; i < list.length; ++i) { 34 var item = list[i]; 35 if (item.optionGroupName) { 36 optgroup = document.createElement('optgroup'); 37 optgroup.label = item.optionGroupName; 38 select.appendChild(optgroup); 39 } else { 40 var option = 41 new Option(item.title, item.value, item.selected, item.selected); 42 optgroup.appendChild(option); 43 } 44 } 45 if (callback) { 46 var sendCallback = function() { 47 chrome.send(callback, [select.options[select.selectedIndex].value]); 48 }; 49 select.addEventListener('blur', sendCallback); 50 select.addEventListener('click', sendCallback); 51 select.addEventListener('keyup', function(event) { 52 var keycodeInterested = [ 53 9, // Tab 54 13, // Enter 55 27, // Escape 56 ]; 57 if (keycodeInterested.indexOf(event.keyCode) >= 0) 58 sendCallback(); 59 }); 60 } 61 }, 62 63 /** 64 * Initializes the OOBE flow. This will cause all C++ handlers to 65 * be invoked to do final setup. 66 */ 67 initialize: function() { 68 cr.ui.login.DisplayManager.initialize(); 69 login.HIDDetectionScreen.register(); 70 login.WrongHWIDScreen.register(); 71 login.NetworkScreen.register(); 72 login.EulaScreen.register(); 73 login.UpdateScreen.register(); 74 login.AutoEnrollmentCheckScreen.register(); 75 login.ResetScreen.register(); 76 login.AutolaunchScreen.register(); 77 login.KioskEnableScreen.register(); 78 login.AccountPickerScreen.register(); 79 login.GaiaSigninScreen.register(); 80 login.UserImageScreen.register(/* lazyInit= */ false); 81 login.ErrorMessageScreen.register(); 82 login.TPMErrorMessageScreen.register(); 83 login.PasswordChangedScreen.register(); 84 login.SupervisedUserCreationScreen.register(); 85 login.TermsOfServiceScreen.register(); 86 login.AppLaunchSplashScreen.register(); 87 login.ConfirmPasswordScreen.register(); 88 login.FatalErrorScreen.register(); 89 login.ControllerPairingScreen.register(); 90 login.HostPairingScreen.register(); 91 92 cr.ui.Bubble.decorate($('bubble')); 93 login.HeaderBar.decorate($('login-header-bar')); 94 95 Oobe.initializeA11yMenu(); 96 97 chrome.send('screenStateInitialize'); 98 }, 99 100 /** 101 * Initializes OOBE accessibility menu. 102 */ 103 initializeA11yMenu: function() { 104 cr.ui.Bubble.decorate($('accessibility-menu')); 105 $('connect-accessibility-link').addEventListener( 106 'click', Oobe.handleAccessibilityLinkClick); 107 $('eula-accessibility-link').addEventListener( 108 'click', Oobe.handleAccessibilityLinkClick); 109 $('update-accessibility-link').addEventListener( 110 'click', Oobe.handleAccessibilityLinkClick); 111 // Same behaviour on hitting spacebar. See crbug.com/342991. 112 function reactOnSpace(event) { 113 if (event.keyCode == 32) 114 Oobe.handleAccessibilityLinkClick(event); 115 } 116 $('connect-accessibility-link').addEventListener( 117 'keyup', reactOnSpace); 118 $('eula-accessibility-link').addEventListener( 119 'keyup', reactOnSpace); 120 $('update-accessibility-link').addEventListener( 121 'keyup', reactOnSpace); 122 123 $('high-contrast').addEventListener('click', 124 Oobe.handleHighContrastClick); 125 $('large-cursor').addEventListener('click', 126 Oobe.handleLargeCursorClick); 127 $('spoken-feedback').addEventListener('click', 128 Oobe.handleSpokenFeedbackClick); 129 $('screen-magnifier').addEventListener('click', 130 Oobe.handleScreenMagnifierClick); 131 $('virtual-keyboard').addEventListener('click', 132 Oobe.handleVirtualKeyboardClick); 133 134 // A11y menu should be accessible i.e. disable autohide on any 135 // keydown or click inside menu. 136 $('accessibility-menu').hideOnKeyPress = false; 137 $('accessibility-menu').hideOnSelfClick = false; 138 }, 139 140 /** 141 * Accessibility link handler. 142 */ 143 handleAccessibilityLinkClick: function(e) { 144 /** @const */ var BUBBLE_OFFSET = 5; 145 /** @const */ var BUBBLE_PADDING = 10; 146 $('accessibility-menu').showForElement(e.target, 147 cr.ui.Bubble.Attachment.BOTTOM, 148 BUBBLE_OFFSET, BUBBLE_PADDING); 149 150 var maxHeight = cr.ui.LoginUITools.getMaxHeightBeforeShelfOverlapping( 151 $('accessibility-menu')); 152 if (maxHeight < $('accessibility-menu').offsetHeight) { 153 $('accessibility-menu').showForElement(e.target, 154 cr.ui.Bubble.Attachment.TOP, 155 BUBBLE_OFFSET, BUBBLE_PADDING); 156 } 157 158 $('accessibility-menu').firstBubbleElement = $('spoken-feedback'); 159 $('accessibility-menu').lastBubbleElement = $('close-accessibility-menu'); 160 if (Oobe.getInstance().currentScreen && 161 Oobe.getInstance().currentScreen.defaultControl) { 162 $('accessibility-menu').elementToFocusOnHide = 163 Oobe.getInstance().currentScreen.defaultControl; 164 } else { 165 // Update screen falls into this category. Since it doesn't have any 166 // controls other than a11y link we don't want that link to receive 167 // focus when screen is shown i.e. defaultControl is not defined. 168 // Focus a11y link instead. 169 $('accessibility-menu').elementToFocusOnHide = e.target; 170 } 171 e.stopPropagation(); 172 }, 173 174 /** 175 * Spoken feedback checkbox handler. 176 */ 177 handleSpokenFeedbackClick: function(e) { 178 chrome.send('enableSpokenFeedback', [$('spoken-feedback').checked]); 179 e.stopPropagation(); 180 }, 181 182 /** 183 * Large cursor checkbox handler. 184 */ 185 handleLargeCursorClick: function(e) { 186 chrome.send('enableLargeCursor', [$('large-cursor').checked]); 187 e.stopPropagation(); 188 }, 189 190 /** 191 * High contrast mode checkbox handler. 192 */ 193 handleHighContrastClick: function(e) { 194 chrome.send('enableHighContrast', [$('high-contrast').checked]); 195 e.stopPropagation(); 196 }, 197 198 /** 199 * Screen magnifier checkbox handler. 200 */ 201 handleScreenMagnifierClick: function(e) { 202 chrome.send('enableScreenMagnifier', [$('screen-magnifier').checked]); 203 e.stopPropagation(); 204 }, 205 206 /** 207 * On-screen keyboard checkbox handler. 208 */ 209 handleVirtualKeyboardClick: function(e) { 210 chrome.send('enableVirtualKeyboard', [$('virtual-keyboard').checked]); 211 e.stopPropagation(); 212 }, 213 214 /** 215 * Sets usage statistics checkbox. 216 * @param {boolean} checked Is the checkbox checked? 217 */ 218 setUsageStats: function(checked) { 219 $('usage-stats').checked = checked; 220 }, 221 222 /** 223 * Set OEM EULA URL. 224 * @param {text} oemEulaUrl OEM EULA URL. 225 */ 226 setOemEulaUrl: function(oemEulaUrl) { 227 if (oemEulaUrl) { 228 $('oem-eula-frame').src = oemEulaUrl; 229 $('eulas').classList.remove('one-column'); 230 } else { 231 $('eulas').classList.add('one-column'); 232 } 233 }, 234 235 /** 236 * Sets TPM password. 237 * @param {text} password TPM password to be shown. 238 */ 239 setTpmPassword: function(password) { 240 $('tpm-busy').hidden = true; 241 242 if (password.length) { 243 $('tpm-password').textContent = password; 244 $('tpm-password').hidden = false; 245 } else { 246 $('tpm-desc').hidden = true; 247 $('tpm-desc-powerwash').hidden = false; 248 } 249 }, 250 251 /** 252 * Refreshes a11y menu state. 253 * @param {!Object} data New dictionary with a11y features state. 254 */ 255 refreshA11yInfo: function(data) { 256 $('high-contrast').checked = data.highContrastEnabled; 257 $('spoken-feedback').checked = data.spokenFeedbackEnabled; 258 $('screen-magnifier').checked = data.screenMagnifierEnabled; 259 $('large-cursor').checked = data.largeCursorEnabled; 260 $('virtual-keyboard').checked = data.virtualKeyboardEnabled; 261 }, 262 263 /** 264 * Reloads content of the page (localized strings, options of the select 265 * controls). 266 * @param {!Object} data New dictionary with i18n values. 267 */ 268 reloadContent: function(data) { 269 // Reload global local strings, process DOM tree again. 270 loadTimeData.overrideValues(data); 271 i18nTemplate.process(document, loadTimeData); 272 273 // Update language and input method menu lists. 274 Oobe.setupSelect($('language-select'), data.languageList, ''); 275 Oobe.setupSelect($('keyboard-select'), data.inputMethodsList, ''); 276 Oobe.setupSelect($('timezone-select'), data.timezoneList, ''); 277 278 // Update localized content of the screens. 279 Oobe.updateLocalizedContent(); 280 }, 281 282 /** 283 * Updates localized content of the screens. 284 * Should be executed on language change. 285 */ 286 updateLocalizedContent: function() { 287 // Buttons, headers and links. 288 Oobe.getInstance().updateLocalizedContent_(); 289 } 290 }; 291 }); 292