Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / resources / options / content_settings.js
blobf6236752535606bffd6c1f695a6f9ee82bd2f3e8
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.
5 cr.exportPath('options');
7 /**
8  * @typedef {{appId: string,
9  *            appName: (string|undefined),
10  *            embeddingOrigin: (string|undefined),
11  *            origin: string,
12  *            setting: string,
13  *            source: string,
14  *            video: (string|undefined)}}
15  */
16 options.Exception;
18 cr.define('options', function() {
19   /** @const */ var Page = cr.ui.pageManager.Page;
20   /** @const */ var PageManager = cr.ui.pageManager.PageManager;
22   // Lookup table to generate the i18n strings.
23   /** @const */ var permissionsLookup = {
24     'cookies': 'cookies',
25     'images': 'images',
26     'javascript': 'javascript',
27     'location': 'location',
28     'media-stream-camera': 'mediaStreamCamera',
29     'media-stream-mic': 'mediaStreamMic',
30     'multiple-automatic-downloads': 'multipleAutomaticDownloads',
31     'notifications': 'notifications',
32     'plugins': 'plugins',
33     'popups': 'popups',
34   };
36   //////////////////////////////////////////////////////////////////////////////
37   // ContentSettings class:
39   /**
40    * Encapsulated handling of content settings page.
41    * @constructor
42    * @extends {cr.ui.pageManager.Page}
43    */
44   function ContentSettings() {
45     this.activeNavTab = null;
46     Page.call(this, 'content',
47               loadTimeData.getString('contentSettingsPageTabTitle'),
48               'content-settings-page');
49   }
51   cr.addSingletonGetter(ContentSettings);
53   ContentSettings.prototype = {
54     __proto__: Page.prototype,
56     /** @override */
57     initializePage: function() {
58       Page.prototype.initializePage.call(this);
60       var exceptionsButtons =
61           this.pageDiv.querySelectorAll('.exceptions-list-button');
62       for (var i = 0; i < exceptionsButtons.length; i++) {
63         exceptionsButtons[i].onclick = function(event) {
64           var hash = event.currentTarget.getAttribute('contentType');
65           PageManager.showPageByName('contentExceptions', true,
66                                      {hash: '#' + hash});
67         };
68       }
70       var manageHandlersButton = $('manage-handlers-button');
71       if (manageHandlersButton) {
72         manageHandlersButton.onclick = function(event) {
73           PageManager.showPageByName('handlers');
74         };
75       }
77       if (cr.isChromeOS) {
78         // Disable some controls for Guest in Chrome OS.
79         UIAccountTweaks.applyGuestSessionVisibility(document);
81         // Disable some controls for Public session in Chrome OS.
82         UIAccountTweaks.applyPublicSessionVisibility(document);
83       }
85       // Cookies filter page ---------------------------------------------------
86       $('show-cookies-button').onclick = function(event) {
87         chrome.send('coreOptionsUserMetricsAction', ['Options_ShowCookies']);
88         PageManager.showPageByName('cookies');
89       };
91       $('content-settings-overlay-confirm').onclick =
92           PageManager.closeOverlay.bind(PageManager);
94       $('media-pepper-flash-default-mic').hidden = true;
95       $('media-pepper-flash-default-camera').hidden = true;
96       $('media-pepper-flash-exceptions-mic').hidden = true;
97       $('media-pepper-flash-exceptions-camera').hidden = true;
99       $('media-select-mic').addEventListener('change',
100           ContentSettings.setDefaultMicrophone_);
101       $('media-select-camera').addEventListener('change',
102           ContentSettings.setDefaultCamera_);
103     },
104   };
106   ContentSettings.updateHandlersEnabledRadios = function(enabled) {
107     var selector = '#content-settings-page input[type=radio][value=' +
108         (enabled ? 'allow' : 'block') + '].handler-radio';
109     document.querySelector(selector).checked = true;
110   };
112   /**
113    * Sets the values for all the content settings radios and labels.
114    * @param {Object<{managedBy: string, value: string}>} dict A mapping from
115    *     radio groups to the checked value for that group.
116    */
117   ContentSettings.setContentFilterSettingsValue = function(dict) {
118     for (var group in dict) {
119       var settingLabel = $(group + '-default-string');
120       if (settingLabel) {
121         var value = dict[group].value;
122         var valueId =
123             permissionsLookup[group] + value[0].toUpperCase() + value.slice(1);
124         settingLabel.textContent = loadTimeData.getString(valueId);
125       }
127       var managedBy = dict[group].managedBy;
128       var controlledBy = managedBy == 'policy' || managedBy == 'extension' ?
129           managedBy : null;
130       document.querySelector('input[type=radio][name=' + group + '][value=' +
131                              dict[group].value + ']').checked = true;
132       var radios = document.querySelectorAll('input[type=radio][name=' +
133                                              group + ']');
134       for (var i = 0, len = radios.length; i < len; i++) {
135         radios[i].disabled = (managedBy != 'default');
136         radios[i].controlledBy = controlledBy;
137       }
138       var indicators = document.querySelectorAll(
139           'span.controlled-setting-indicator[content-setting=' + group + ']');
140       if (indicators.length == 0)
141         continue;
142       // Create a synthetic pref change event decorated as
143       // CoreOptionsHandler::CreateValueForPref() does.
144       var event = new Event(group);
145       event.value = {
146         value: dict[group].value,
147         controlledBy: controlledBy,
148       };
149       for (var i = 0; i < indicators.length; i++) {
150         indicators[i].handlePrefChange(event);
151       }
152     }
153   };
155   /**
156    * Initializes an exceptions list.
157    * @param {string} type The content type that we are setting exceptions for.
158    * @param {Array<options.Exception>} exceptions An array of pairs, where the
159    *     first element of each pair is the filter string, and the second is the
160    *     setting (allow/block).
161    */
162   ContentSettings.setExceptions = function(type, exceptions) {
163     this.getExceptionsList(type, 'normal').setExceptions(exceptions);
164   };
166   ContentSettings.setHandlers = function(handlers) {
167     $('handlers-list').setHandlers(handlers);
168   };
170   ContentSettings.setIgnoredHandlers = function(ignoredHandlers) {
171     $('ignored-handlers-list').setHandlers(ignoredHandlers);
172   };
174   ContentSettings.setOTRExceptions = function(type, otrExceptions) {
175     var exceptionsList = this.getExceptionsList(type, 'otr');
176     // Settings for Guest hides many sections, so check for null first.
177     if (exceptionsList) {
178       exceptionsList.parentNode.hidden = false;
179       exceptionsList.setExceptions(otrExceptions);
180     }
181   };
183   /**
184    * @param {string} type The type of exceptions (e.g. "location") to get.
185    * @param {string} mode The mode of the desired exceptions list (e.g. otr).
186    * @return {?options.contentSettings.ExceptionsList} The corresponding
187    *     exceptions list or null.
188    */
189   ContentSettings.getExceptionsList = function(type, mode) {
190     var exceptionsList = document.querySelector(
191         'div[contentType=' + type + '] list[mode=' + mode + ']');
192     return !exceptionsList ? null :
193         assertInstanceof(exceptionsList,
194                          options.contentSettings.ExceptionsList);
195   };
197   /**
198    * The browser's response to a request to check the validity of a given URL
199    * pattern.
200    * @param {string} type The content type.
201    * @param {string} mode The browser mode.
202    * @param {string} pattern The pattern.
203    * @param {boolean} valid Whether said pattern is valid in the context of
204    *     a content exception setting.
205    */
206   ContentSettings.patternValidityCheckComplete =
207       function(type, mode, pattern, valid) {
208     this.getExceptionsList(type, mode).patternValidityCheckComplete(pattern,
209                                                                     valid);
210   };
212   /**
213    * Shows/hides the link to the Pepper Flash camera or microphone,
214    * default or exceptions settings.
215    * Please note that whether the link is actually showed or not is also
216    * affected by the style class pepper-flash-settings.
217    * @param {string} linkType Can be 'default' or 'exceptions'.
218    * @param {string} contentType Can be 'mic' or 'camera'.
219    * @param {boolean} show Whether to show (or hide) the link.
220    */
221   ContentSettings.showMediaPepperFlashLink =
222       function(linkType, contentType, show) {
223     assert(['default', 'exceptions'].indexOf(linkType) >= 0);
224     assert(['mic', 'camera'].indexOf(contentType) >= 0);
225     $('media-pepper-flash-' + linkType + '-' + contentType).hidden = !show;
226   };
228   /**
229    * Updates the microphone/camera devices menu with the given entries.
230    * @param {string} type The device type.
231    * @param {Array} devices List of available devices.
232    * @param {string} defaultdevice The unique id of the current default device.
233    */
234   ContentSettings.updateDevicesMenu = function(type, devices, defaultdevice) {
235     var deviceSelect = '';
236     if (type == 'mic') {
237       deviceSelect = $('media-select-mic');
238     } else if (type == 'camera') {
239       deviceSelect = $('media-select-camera');
240     } else {
241       console.error('Unknown device type for <device select> UI element: ' +
242                     type);
243       return;
244     }
246     deviceSelect.textContent = '';
248     var deviceCount = devices.length;
249     var defaultIndex = -1;
250     for (var i = 0; i < deviceCount; i++) {
251       var device = devices[i];
252       var option = new Option(device.name, device.id);
253       if (option.value == defaultdevice)
254         defaultIndex = i;
255       deviceSelect.appendChild(option);
256     }
257     if (defaultIndex >= 0)
258       deviceSelect.selectedIndex = defaultIndex;
259   };
261   /**
262    * Sets the visibility of the microphone/camera devices menu.
263    * @param {string} type The content settings type name of this device.
264    * @param {boolean} show Whether to show the menu.
265    */
266   ContentSettings.setDevicesMenuVisibility = function(type, show) {
267     assert(type == 'media-stream-mic' || type == 'media-stream-camera');
268     var deviceSelect = $(type == 'media-stream-mic' ? 'media-select-mic' :
269                                                       'media-select-camera');
270     deviceSelect.hidden = !show;
271   };
273   /**
274    * Enables/disables the protected content exceptions button.
275    * @param {boolean} enable Whether to enable the button.
276    */
277   ContentSettings.enableProtectedContentExceptions = function(enable) {
278     var exceptionsButton = $('protected-content-exceptions');
279     if (exceptionsButton)
280       exceptionsButton.disabled = !enable;
281   };
283   /**
284    * Set the default microphone device based on the popup selection.
285    * @private
286    */
287   ContentSettings.setDefaultMicrophone_ = function() {
288     var deviceSelect = $('media-select-mic');
289     chrome.send('setDefaultCaptureDevice', ['mic', deviceSelect.value]);
290   };
292   /**
293    * Set the default camera device based on the popup selection.
294    * @private
295    */
296   ContentSettings.setDefaultCamera_ = function() {
297     var deviceSelect = $('media-select-camera');
298     chrome.send('setDefaultCaptureDevice', ['camera', deviceSelect.value]);
299   };
301   // Export
302   return {
303     ContentSettings: ContentSettings
304   };