Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / resources / options / controlled_setting.js
blobfc5b960ab334c6c82e3bbaa261c310fc6bcb3824
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.define('options', function() {
6   /** @const */ var Preferences = options.Preferences;
8   /**
9    * A controlled setting indicator that can be placed on a setting as an
10    * indicator that the value is controlled by some external entity such as
11    * policy or an extension.
12    * @constructor
13    * @extends {cr.ui.ControlledIndicator}
14    */
15   var ControlledSettingIndicator = cr.ui.define('span');
17   ControlledSettingIndicator.prototype = {
18     __proto__: cr.ui.ControlledIndicator.prototype,
20     /**
21      * Decorates the base element to show the proper icon.
22      */
23     decorate: function() {
24       cr.ui.ControlledIndicator.prototype.decorate.call(this);
26       // If there is a pref, track its controlledBy and recommendedValue
27       // properties in order to be able to bring up the correct bubble.
28       if (this.pref) {
29         Preferences.getInstance().addEventListener(
30             this.pref, this.handlePrefChange.bind(this));
31         this.resetHandler = this.clearAssociatedPref_;
32       }
33     },
35     /**
36      * The given handler will be called when the user clicks on the 'reset to
37      * recommended value' link shown in the indicator bubble. The |this| object
38      * will be the indicator itself.
39      * @param {function()} handler The handler to be called.
40      */
41     set resetHandler(handler) {
42       this.resetHandler_ = handler;
43     },
45     /**
46      * Clears the preference associated with this indicator.
47      * @private
48      */
49     clearAssociatedPref_: function() {
50       Preferences.clearPref(this.pref, !this.dialogPref);
51     },
53     /**
54      * Handle changes to the associated pref by hiding any currently visible
55      * bubble and updating the controlledBy property.
56      * @param {Event} event Pref change event.
57      * @suppress {checkTypes}
58      * TODO(vitalyp): remove the suppression. |controlledBy| property is defined
59      * by cr.defineProperty(). Currently null can't be assigned to such
60      * properties due to implementation of ChromePass.java. See this discussion
61      * to change nulls to empty string below:
62      * https://chromiumcodereview.appspot.com/11066015/
63      */
64     handlePrefChange: function(event) {
65       PageManager.hideBubble();
66       if (event.value.controlledBy) {
67         if (!this.value || String(event.value.value) == this.value) {
68           this.controlledBy = event.value.controlledBy;
69           if (event.value.extension) {
70             this.extensionId = event.value.extension.id;
71             this.extensionIcon = event.value.extension.icon;
72             this.extensionName = event.value.extension.name;
73           }
74         } else {
75           this.controlledBy = null;
76         }
77       } else if (event.value.recommendedValue != undefined) {
78         this.controlledBy =
79             !this.value || String(event.value.recommendedValue) == this.value ?
80             'hasRecommendation' : null;
81       } else {
82         this.controlledBy = null;
83       }
84     },
86     /**
87      * Uses the page's PageManager to display an informational bubble.
88      * @override
89      */
90     showBubble: function(content) {
91       PageManager.showBubble(content, this.image, this, this.location);
92     },
94     /**
95      * Uses the page's PageManager to hide the currently visible bubble, if
96      * any.
97      * @override
98      */
99     hideBubble: function() {
100       PageManager.hideBubble();
101     },
103     /**
104      * Queries the |loadTimeData| singleton for the default bubble text strings.
105      * @override
106      */
107     getDefaultStrings: function() {
108       // Construct the bubble text.
109       if (this.hasAttribute('plural')) {
110         var defaultStrings = {
111           'policy': loadTimeData.getString('controlledSettingsPolicy'),
112           'extension': loadTimeData.getString('controlledSettingsExtension'),
113           'extensionWithName':
114               loadTimeData.getString('controlledSettingsExtensionWithName'),
115         };
116         if (cr.isChromeOS) {
117           defaultStrings.shared =
118               loadTimeData.getString('controlledSettingsShared');
119         }
120       } else {
121         var defaultStrings = {
122           'policy': loadTimeData.getString('controlledSettingPolicy'),
123           'extension': loadTimeData.getString('controlledSettingExtension'),
124           'extensionWithName':
125               loadTimeData.getString('controlledSettingExtensionWithName'),
126           'recommended': loadTimeData.getString('controlledSettingRecommended'),
127           'hasRecommendation':
128               loadTimeData.getString('controlledSettingHasRecommendation'),
129         };
130         if (cr.isChromeOS) {
131           defaultStrings.owner =
132               loadTimeData.getString('controlledSettingOwner');
133           defaultStrings.shared =
134               loadTimeData.getString('controlledSettingShared');
135         }
136       }
137       return defaultStrings;
138     },
140     /**
141      * Returns the DOM tree for a showing the message |text|.
142      * @param {string} text to be shown in the bubble.
143      * @override
144      */
145     createDomTree: function(text) {
146       var content = document.createElement('div');
147       content.classList.add('controlled-setting-bubble-header');
148       content.textContent = text;
150       if (this.controlledBy == 'hasRecommendation' && this.resetHandler_ &&
151           !this.readOnly) {
152         var container = document.createElement('div');
153         var action = new ActionLink;
154         action.classList.add('controlled-setting-bubble-action');
155         action.textContent =
156             loadTimeData.getString('controlledSettingFollowRecommendation');
157         action.addEventListener('click', this.resetHandler_.bind(this));
158         container.appendChild(action);
159         content.appendChild(container);
160       } else if (this.controlledBy == 'extension' && this.extensionName) {
161         var extensionContainer =
162             $('extension-controlled-settings-bubble-template').cloneNode(true);
163         // No need for an id anymore, and thus remove to avoid id collision.
164         extensionContainer.removeAttribute('id');
165         extensionContainer.hidden = false;
167         var extensionName = extensionContainer.querySelector(
168             '.controlled-setting-bubble-extension-name');
169         extensionName.textContent = this.extensionName;
170         extensionName.style.backgroundImage =
171             'url("' + this.extensionIcon + '")';
173         var manageLink = extensionContainer.querySelector(
174             '.controlled-setting-bubble-extension-manage-link');
175         var extensionId = this.extensionId;
176         manageLink.onclick = function() {
177           uber.invokeMethodOnWindow(
178               window.top, 'showPage',
179               {pageId: 'extensions', path: '?id=' + extensionId});
180         };
182         var disableButton = extensionContainer.querySelector(
183             '.controlled-setting-bubble-extension-disable-button');
184         disableButton.onclick =
185             function() { chrome.send('disableExtension', [extensionId]); };
186         content.appendChild(extensionContainer);
187       }
188       return content;
189     },
190   };
192   /**
193    * The name of the associated preference.
194    */
195   cr.defineProperty(ControlledSettingIndicator, 'pref', cr.PropertyKind.ATTR);
197   /**
198    * Whether this indicator is part of a dialog. If so, changes made to the
199    * associated preference take effect in the settings UI immediately but are
200    * only actually committed when the user confirms the dialog. If the user
201    * cancels the dialog instead, the changes are rolled back in the settings UI
202    * and never committed.
203    */
204   cr.defineProperty(ControlledSettingIndicator, 'dialogPref',
205                     cr.PropertyKind.BOOL_ATTR);
207   /**
208    * The value of the associated preference that the indicator represents. If
209    * this is not set, the indicator will be visible whenever any value is
210    * enforced or recommended. If it is set, the indicator will be visible only
211    * when the enforced or recommended value matches the value it represents.
212    * This allows multiple indicators to be created for a set of radio buttons,
213    * ensuring that only one of them is visible at a time.
214    */
215   cr.defineProperty(ControlledSettingIndicator, 'value',
216                     cr.PropertyKind.ATTR);
218   // Export.
219   return {
220     ControlledSettingIndicator: ControlledSettingIndicator
221   };