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 cr.define('options', function() { 6 /** @const */ var Page = cr.ui.pageManager.Page; 7 /** @const */ var PageManager = cr.ui.pageManager.PageManager; 8 9 // Lookup table to generate the i18n strings. 10 /** @const */ var permissionsLookup = { 11 'location': 'location', 12 'notifications': 'notifications', 13 'media-stream': 'mediaStream', 14 'cookies': 'cookies', 15 'multiple-automatic-downloads': 'multipleAutomaticDownloads', 16 'images': 'images', 17 'plugins': 'plugins', 18 'popups': 'popups', 19 'javascript': 'javascript' 20 }; 21 22 ////////////////////////////////////////////////////////////////////////////// 23 // ContentSettings class: 24 25 /** 26 * Encapsulated handling of content settings page. 27 * @constructor 28 * @extends {cr.ui.pageManager.Page} 29 */ 30 function ContentSettings() { 31 this.activeNavTab = null; 32 Page.call(this, 'content', 33 loadTimeData.getString('contentSettingsPageTabTitle'), 34 'content-settings-page'); 35 } 36 37 cr.addSingletonGetter(ContentSettings); 38 39 ContentSettings.prototype = { 40 __proto__: Page.prototype, 41 42 /** @override */ 43 initializePage: function() { 44 Page.prototype.initializePage.call(this); 45 46 var exceptionsButtons = 47 this.pageDiv.querySelectorAll('.exceptions-list-button'); 48 for (var i = 0; i < exceptionsButtons.length; i++) { 49 exceptionsButtons[i].onclick = function(event) { 50 var hash = event.currentTarget.getAttribute('contentType'); 51 PageManager.showPageByName('contentExceptions', true, 52 {hash: '#' + hash}); 53 }; 54 } 55 56 var experimentalExceptionsButtons = 57 this.pageDiv.querySelectorAll('.website-settings-permission-button'); 58 for (var i = 0; i < experimentalExceptionsButtons.length; i++) { 59 experimentalExceptionsButtons[i].onclick = function(event) { 60 var hash = event.currentTarget.getAttribute('contentType'); 61 WebsiteSettingsManager.showWebsiteSettings(hash); 62 }; 63 } 64 65 var manageHandlersButton = $('manage-handlers-button'); 66 if (manageHandlersButton) { 67 manageHandlersButton.onclick = function(event) { 68 PageManager.showPageByName('handlers'); 69 }; 70 } 71 72 if (cr.isChromeOS) { 73 // Disable some controls for Guest in Chrome OS. 74 UIAccountTweaks.applyGuestSessionVisibility(document); 75 76 // Disable some controls for Public session in Chrome OS. 77 UIAccountTweaks.applyPublicSessionVisibility(document); 78 } 79 80 // Cookies filter page --------------------------------------------------- 81 $('show-cookies-button').onclick = function(event) { 82 chrome.send('coreOptionsUserMetricsAction', ['Options_ShowCookies']); 83 PageManager.showPageByName('cookies'); 84 }; 85 86 $('content-settings-overlay-confirm').onclick = 87 PageManager.closeOverlay.bind(PageManager); 88 89 $('media-pepper-flash-default').hidden = true; 90 $('media-pepper-flash-exceptions').hidden = true; 91 92 $('media-select-mic').addEventListener('change', 93 ContentSettings.setDefaultMicrophone_); 94 $('media-select-camera').addEventListener('change', 95 ContentSettings.setDefaultCamera_); 96 97 if (loadTimeData.getBoolean('websiteSettingsManagerEnabled')) { 98 var oldUI = 99 this.pageDiv.querySelectorAll('.replace-with-website-settings'); 100 for (var i = 0; i < oldUI.length; i++) { 101 oldUI[i].hidden = true; 102 } 103 104 var newUI = 105 this.pageDiv.querySelectorAll('.experimental-website-settings'); 106 for (var i = 0; i < newUI.length; i++) { 107 newUI[i].hidden = false; 108 } 109 } 110 }, 111 }; 112 113 ContentSettings.updateHandlersEnabledRadios = function(enabled) { 114 var selector = '#content-settings-page input[type=radio][value=' + 115 (enabled ? 'allow' : 'block') + '].handler-radio'; 116 document.querySelector(selector).checked = true; 117 }; 118 119 /** 120 * Sets the values for all the content settings radios and labels. 121 * @param {Object} dict A mapping from radio groups to the checked value for 122 * that group. 123 */ 124 ContentSettings.setContentFilterSettingsValue = function(dict) { 125 for (var group in dict) { 126 var settingLabel = $(group + '-default-string'); 127 if (settingLabel) { 128 var value = dict[group].value; 129 var valueId = 130 permissionsLookup[group] + value[0].toUpperCase() + value.slice(1); 131 settingLabel.textContent = loadTimeData.getString(valueId); 132 } 133 134 var managedBy = dict[group].managedBy; 135 var controlledBy = managedBy == 'policy' || managedBy == 'extension' ? 136 managedBy : null; 137 document.querySelector('input[type=radio][name=' + group + '][value=' + 138 dict[group].value + ']').checked = true; 139 var radios = document.querySelectorAll('input[type=radio][name=' + 140 group + ']'); 141 for (var i = 0, len = radios.length; i < len; i++) { 142 radios[i].disabled = (managedBy != 'default'); 143 radios[i].controlledBy = controlledBy; 144 } 145 var indicators = document.querySelectorAll( 146 'span.controlled-setting-indicator[content-setting=' + group + ']'); 147 if (indicators.length == 0) 148 continue; 149 // Create a synthetic pref change event decorated as 150 // CoreOptionsHandler::CreateValueForPref() does. 151 var event = new Event(group); 152 event.value = { 153 value: dict[group].value, 154 controlledBy: controlledBy, 155 }; 156 for (var i = 0; i < indicators.length; i++) { 157 indicators[i].handlePrefChange(event); 158 } 159 } 160 }; 161 162 /** 163 * Updates the labels and indicators for the Media settings. Those require 164 * special handling because they are backed by multiple prefs and can change 165 * their scope based on the managed state of the backing prefs. 166 * @param {{askText: string, blockText: string, cameraDisabled: boolean, 167 * micDisabled: boolean, showBubble: boolean, bubbleText: string}} 168 * mediaSettings A dictionary containing the following fields: 169 * askText The label for the ask radio button. 170 * blockText The label for the block radio button. 171 * cameraDisabled Whether to disable the camera dropdown. 172 * micDisabled Whether to disable the microphone dropdown. 173 * showBubble Wether to show the managed icon and bubble for the media 174 * label. 175 * bubbleText The text to use inside the bubble if it is shown. 176 */ 177 ContentSettings.updateMediaUI = function(mediaSettings) { 178 $('media-stream-ask-label').innerHTML = 179 loadTimeData.getString(mediaSettings.askText); 180 $('media-stream-block-label').innerHTML = 181 loadTimeData.getString(mediaSettings.blockText); 182 183 if (mediaSettings.micDisabled) 184 $('media-select-mic').disabled = true; 185 if (mediaSettings.cameraDisabled) 186 $('media-select-camera').disabled = true; 187 188 PageManager.hideBubble(); 189 // Create a synthetic pref change event decorated as 190 // CoreOptionsHandler::CreateValueForPref() does. 191 // TODO(arv): It was not clear what event type this should use? 192 var event = new Event('undefined'); 193 event.value = {}; 194 195 if (mediaSettings.showBubble) { 196 event.value = { controlledBy: 'policy' }; 197 $('media-indicator').setAttribute( 198 'textpolicy', loadTimeData.getString(mediaSettings.bubbleText)); 199 $('media-indicator').location = cr.ui.ArrowLocation.TOP_START; 200 } 201 202 $('media-indicator').handlePrefChange(event); 203 }; 204 205 /** 206 * Initializes an exceptions list. 207 * @param {string} type The content type that we are setting exceptions for. 208 * @param {Array} exceptions An array of pairs, where the first element of 209 * each pair is the filter string, and the second is the setting 210 * (allow/block). 211 */ 212 ContentSettings.setExceptions = function(type, exceptions) { 213 this.getExceptionsList(type, 'normal').setExceptions(exceptions); 214 }; 215 216 ContentSettings.setHandlers = function(handlers) { 217 $('handlers-list').setHandlers(handlers); 218 }; 219 220 ContentSettings.setIgnoredHandlers = function(ignoredHandlers) { 221 $('ignored-handlers-list').setHandlers(ignoredHandlers); 222 }; 223 224 ContentSettings.setOTRExceptions = function(type, otrExceptions) { 225 var exceptionsList = this.getExceptionsList(type, 'otr'); 226 // Settings for Guest hides many sections, so check for null first. 227 if (exceptionsList) { 228 exceptionsList.parentNode.hidden = false; 229 exceptionsList.setExceptions(otrExceptions); 230 } 231 }; 232 233 /** 234 * @param {string} type The type of exceptions (e.g. "location") to get. 235 * @param {string} mode The mode of the desired exceptions list (e.g. otr). 236 * @return {?options.contentSettings.ExceptionsList} The corresponding 237 * exceptions list or null. 238 */ 239 ContentSettings.getExceptionsList = function(type, mode) { 240 var exceptionsList = document.querySelector( 241 'div[contentType=' + type + '] list[mode=' + mode + ']'); 242 return !exceptionsList ? null : 243 assertInstanceof(exceptionsList, 244 options.contentSettings.ExceptionsList); 245 }; 246 247 /** 248 * The browser's response to a request to check the validity of a given URL 249 * pattern. 250 * @param {string} type The content type. 251 * @param {string} mode The browser mode. 252 * @param {string} pattern The pattern. 253 * @param {boolean} valid Whether said pattern is valid in the context of 254 * a content exception setting. 255 */ 256 ContentSettings.patternValidityCheckComplete = 257 function(type, mode, pattern, valid) { 258 this.getExceptionsList(type, mode).patternValidityCheckComplete(pattern, 259 valid); 260 }; 261 262 /** 263 * Shows/hides the link to the Pepper Flash camera and microphone default 264 * settings. 265 * Please note that whether the link is actually showed or not is also 266 * affected by the style class pepper-flash-settings. 267 */ 268 ContentSettings.showMediaPepperFlashDefaultLink = function(show) { 269 $('media-pepper-flash-default').hidden = !show; 270 }; 271 272 /** 273 * Shows/hides the link to the Pepper Flash camera and microphone 274 * site-specific settings. 275 * Please note that whether the link is actually showed or not is also 276 * affected by the style class pepper-flash-settings. 277 */ 278 ContentSettings.showMediaPepperFlashExceptionsLink = function(show) { 279 $('media-pepper-flash-exceptions').hidden = !show; 280 }; 281 282 /** 283 * Shows/hides the whole Web MIDI settings. 284 * @param {boolean} show Wether to show the whole Web MIDI settings. 285 */ 286 ContentSettings.showExperimentalWebMIDISettings = function(show) { 287 $('experimental-web-midi-settings').hidden = !show; 288 }; 289 290 /** 291 * Updates the microphone/camera devices menu with the given entries. 292 * @param {string} type The device type. 293 * @param {Array} devices List of available devices. 294 * @param {string} defaultdevice The unique id of the current default device. 295 */ 296 ContentSettings.updateDevicesMenu = function(type, devices, defaultdevice) { 297 var deviceSelect = ''; 298 if (type == 'mic') { 299 deviceSelect = $('media-select-mic'); 300 } else if (type == 'camera') { 301 deviceSelect = $('media-select-camera'); 302 } else { 303 console.error('Unknown device type for <device select> UI element: ' + 304 type); 305 return; 306 } 307 308 deviceSelect.textContent = ''; 309 310 var deviceCount = devices.length; 311 var defaultIndex = -1; 312 for (var i = 0; i < deviceCount; i++) { 313 var device = devices[i]; 314 var option = new Option(device.name, device.id); 315 if (option.value == defaultdevice) 316 defaultIndex = i; 317 deviceSelect.appendChild(option); 318 } 319 if (defaultIndex >= 0) 320 deviceSelect.selectedIndex = defaultIndex; 321 }; 322 323 /** 324 * Enables/disables the protected content exceptions button. 325 * @param {boolean} enable Whether to enable the button. 326 */ 327 ContentSettings.enableProtectedContentExceptions = function(enable) { 328 var exceptionsButton = $('protected-content-exceptions'); 329 if (exceptionsButton) 330 exceptionsButton.disabled = !enable; 331 }; 332 333 /** 334 * Set the default microphone device based on the popup selection. 335 * @private 336 */ 337 ContentSettings.setDefaultMicrophone_ = function() { 338 var deviceSelect = $('media-select-mic'); 339 chrome.send('setDefaultCaptureDevice', ['mic', deviceSelect.value]); 340 }; 341 342 /** 343 * Set the default camera device based on the popup selection. 344 * @private 345 */ 346 ContentSettings.setDefaultCamera_ = function() { 347 var deviceSelect = $('media-select-camera'); 348 chrome.send('setDefaultCaptureDevice', ['camera', deviceSelect.value]); 349 }; 350 351 // Export 352 return { 353 ContentSettings: ContentSettings 354 }; 355 356 }); 357