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 var Preferences = options.Preferences;
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.
13 * @extends {HTMLSpanElement}
15 var ControlledSettingIndicator = cr.ui.define('span');
17 ControlledSettingIndicator.prototype = {
18 __proto__: cr.ui.BubbleButton.prototype,
21 * Decorates the base element to show the proper icon.
23 decorate: function() {
24 cr.ui.BubbleButton.prototype.decorate.call(this);
25 this.classList.add('controlled-setting-indicator');
27 // If there is a pref, track its controlledBy and recommendedValue
28 // properties in order to be able to bring up the correct bubble.
30 Preferences.getInstance().addEventListener(
31 this.pref, this.handlePrefChange.bind(this));
32 this.resetHandler = this.clearAssociatedPref_;
37 * The given handler will be called when the user clicks on the 'reset to
38 * recommended value' link shown in the indicator bubble. The |this| object
39 * will be the indicator itself.
40 * @param {function()} handler The handler to be called.
42 set resetHandler(handler) {
43 this.resetHandler_ = handler;
47 * Clears the preference associated with this indicator.
50 clearAssociatedPref_: function() {
51 Preferences.clearPref(this.pref, !this.dialogPref);
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.
58 handlePrefChange: function(event) {
59 OptionsPage.hideBubble();
60 if (event.value.controlledBy) {
61 if (!this.value || String(event.value.value) == this.value) {
62 this.controlledBy = event.value.controlledBy;
63 if (event.value.extension) {
64 this.extensionId = event.value.extension.id;
65 this.extensionIcon = event.value.extension.icon;
66 this.extensionName = event.value.extension.name;
69 this.controlledBy = null;
71 } else if (event.value.recommendedValue != undefined) {
73 !this.value || String(event.value.recommendedValue) == this.value ?
74 'hasRecommendation' : null;
76 this.controlledBy = null;
81 * Open or close a bubble with further information about the pref.
84 toggleBubble_: function() {
85 if (this.showingBubble) {
86 OptionsPage.hideBubble();
90 // Construct the bubble text.
91 if (this.hasAttribute('plural')) {
92 var defaultStrings = {
93 'policy': loadTimeData.getString('controlledSettingsPolicy'),
94 'extension': loadTimeData.getString('controlledSettingsExtension'),
95 'extensionWithName': loadTimeData.getString(
96 'controlledSettingsExtensionWithName'),
99 defaultStrings.shared =
100 loadTimeData.getString('controlledSettingsShared');
103 var defaultStrings = {
104 'policy': loadTimeData.getString('controlledSettingPolicy'),
105 'extension': loadTimeData.getString('controlledSettingExtension'),
106 'extensionWithName': loadTimeData.getString(
107 'controlledSettingExtensionWithName'),
109 loadTimeData.getString('controlledSettingRecommended'),
111 loadTimeData.getString('controlledSettingHasRecommendation'),
114 defaultStrings.owner =
115 loadTimeData.getString('controlledSettingOwner');
116 defaultStrings.shared =
117 loadTimeData.getString('controlledSettingShared');
121 // No controller, no bubble.
122 if (!this.controlledBy || !(this.controlledBy in defaultStrings))
125 var text = defaultStrings[this.controlledBy];
126 if (this.controlledBy == 'extension' && this.extensionName)
127 text = defaultStrings.extensionWithName;
129 // Apply text overrides.
130 if (this.hasAttribute('text' + this.controlledBy))
131 text = this.getAttribute('text' + this.controlledBy);
133 // Create the DOM tree.
134 var content = document.createElement('div');
135 content.classList.add('controlled-setting-bubble-header');
136 content.textContent = text;
138 if (this.controlledBy == 'hasRecommendation' && this.resetHandler_ &&
140 var container = document.createElement('div');
141 var action = document.createElement('button');
142 action.classList.add('link-button');
143 action.classList.add('controlled-setting-bubble-action');
145 loadTimeData.getString('controlledSettingFollowRecommendation');
146 action.addEventListener('click', function(event) {
147 self.resetHandler_();
149 container.appendChild(action);
150 content.appendChild(container);
151 } else if (this.controlledBy == 'extension' && this.extensionName) {
152 var extensionContainer =
153 $('extension-controlled-settings-bubble-template').
155 // No need for an id anymore, and thus remove to avoid id collision.
156 extensionContainer.removeAttribute('id');
157 extensionContainer.hidden = false;
159 var extensionName = extensionContainer.querySelector(
160 '.controlled-setting-bubble-extension-name');
161 extensionName.textContent = this.extensionName;
162 extensionName.style.backgroundImage =
163 'url("' + this.extensionIcon + '")';
165 var manageLink = extensionContainer.querySelector(
166 '.controlled-setting-bubble-extension-manage-link');
167 var extensionId = this.extensionId;
168 manageLink.onclick = function() {
169 uber.invokeMethodOnWindow(
170 window.top, 'showPage', {pageId: 'extensions',
171 path: '?id=' + extensionId});
174 var disableButton = extensionContainer.querySelector(
175 '.controlled-setting-bubble-extension-disable-button');
176 disableButton.onclick = function() {
177 chrome.send('disableExtension', [extensionId]);
179 content.appendChild(extensionContainer);
182 OptionsPage.showBubble(content, this.image, this, this.location);
188 * The name of the associated preference.
191 cr.defineProperty(ControlledSettingIndicator, 'pref', cr.PropertyKind.ATTR);
194 * Whether this indicator is part of a dialog. If so, changes made to the
195 * associated preference take effect in the settings UI immediately but are
196 * only actually committed when the user confirms the dialog. If the user
197 * cancels the dialog instead, the changes are rolled back in the settings UI
198 * and never committed.
201 cr.defineProperty(ControlledSettingIndicator, 'dialogPref',
202 cr.PropertyKind.BOOL_ATTR);
205 * The value of the associated preference that the indicator represents. If
206 * this is not set, the indicator will be visible whenever any value is
207 * enforced or recommended. If it is set, the indicator will be visible only
208 * when the enforced or recommended value matches the value it represents.
209 * This allows multiple indicators to be created for a set of radio buttons,
210 * ensuring that only one of them is visible at a time.
212 cr.defineProperty(ControlledSettingIndicator, 'value',
213 cr.PropertyKind.ATTR);
216 * The status of the associated preference:
217 * - 'policy': A specific value is enfoced by policy.
218 * - 'extension': A specific value is enforced by an extension.
219 * - 'recommended': A value is recommended by policy. The user could
220 * override this recommendation but has not done so.
221 * - 'hasRecommendation': A value is recommended by policy. The user has
222 * overridden this recommendation.
223 * - 'owner': A value is controlled by the owner of the device
225 * - 'shared': A value belongs to the primary user but can be
226 * modified (Chrome OS only).
227 * - unset: The value is controlled by the user alone.
230 cr.defineProperty(ControlledSettingIndicator, 'controlledBy',
231 cr.PropertyKind.ATTR);
235 ControlledSettingIndicator: ControlledSettingIndicator