browser/devtools/framework/toolbox-options.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:f580ba6b0aba
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 "use strict";
6
7 const {Cu, Cc, Ci} = require("chrome");
8 const Services = require("Services");
9 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
10 XPCOMUtils.defineLazyModuleGetter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
11
12 exports.OptionsPanel = OptionsPanel;
13
14 XPCOMUtils.defineLazyGetter(this, "l10n", function() {
15 let bundle = Services.strings.createBundle("chrome://browser/locale/devtools/toolbox.properties");
16 let l10n = function(aName, ...aArgs) {
17 try {
18 if (aArgs.length == 0) {
19 return bundle.GetStringFromName(aName);
20 } else {
21 return bundle.formatStringFromName(aName, aArgs, aArgs.length);
22 }
23 } catch (ex) {
24 Services.console.logStringMessage("Error reading '" + aName + "'");
25 }
26 };
27 return l10n;
28 });
29
30 /**
31 * Represents the Options Panel in the Toolbox.
32 */
33 function OptionsPanel(iframeWindow, toolbox) {
34 this.panelDoc = iframeWindow.document;
35 this.panelWin = iframeWindow;
36 this.toolbox = toolbox;
37 this.isReady = false;
38
39 const EventEmitter = require("devtools/toolkit/event-emitter");
40 EventEmitter.decorate(this);
41 }
42
43 OptionsPanel.prototype = {
44
45 get target() {
46 return this.toolbox.target;
47 },
48
49 open: function() {
50 let targetPromise;
51
52 // For local debugging we need to make the target remote.
53 if (!this.target.isRemote) {
54 targetPromise = this.target.makeRemote();
55 } else {
56 targetPromise = promise.resolve(this.target);
57 }
58
59 return targetPromise.then(() => {
60 this.setupToolsList();
61 this.setupToolbarButtonsList();
62 this.populatePreferences();
63
64 this._disableJSClicked = this._disableJSClicked.bind(this);
65 this._disableCacheClicked = this._disableCacheClicked.bind(this);
66
67 let disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
68 disableJSNode.addEventListener("click", this._disableJSClicked, false);
69
70 let disableCacheNode = this.panelDoc.getElementById("devtools-disable-cache");
71 disableCacheNode.addEventListener("click", this._disableCacheClicked, false);
72 }).then(() => {
73 this.isReady = true;
74 this.emit("ready");
75 return this;
76 }).then(null, function onError(aReason) {
77 Cu.reportError("OptionsPanel open failed. " +
78 aReason.error + ": " + aReason.message);
79 });
80 },
81
82 setupToolbarButtonsList: function() {
83 let enabledToolbarButtonsBox = this.panelDoc.getElementById("enabled-toolbox-buttons-box");
84 enabledToolbarButtonsBox.textContent = "";
85
86 let toggleableButtons = this.toolbox.toolboxButtons;
87 let setToolboxButtonsVisibility =
88 this.toolbox.setToolboxButtonsVisibility.bind(this.toolbox);
89
90 let onCheckboxClick = (checkbox) => {
91 let toolDefinition = toggleableButtons.filter(tool => tool.id === checkbox.id)[0];
92 Services.prefs.setBoolPref(toolDefinition.visibilityswitch, checkbox.checked);
93 setToolboxButtonsVisibility();
94 };
95
96 let createCommandCheckbox = tool => {
97 let checkbox = this.panelDoc.createElement("checkbox");
98 checkbox.setAttribute("id", tool.id);
99 checkbox.setAttribute("label", tool.label);
100 checkbox.setAttribute("checked", this.getBoolPref(tool.visibilityswitch));
101 checkbox.addEventListener("command", onCheckboxClick.bind(this, checkbox));
102 return checkbox;
103 };
104
105 for (let tool of toggleableButtons) {
106 enabledToolbarButtonsBox.appendChild(createCommandCheckbox(tool));
107 }
108 },
109
110 getBoolPref: function(key) {
111 try {
112 return Services.prefs.getBoolPref(key);
113 }
114 catch (ex) {
115 return true;
116 }
117 },
118
119 setupToolsList: function() {
120 let defaultToolsBox = this.panelDoc.getElementById("default-tools-box");
121 let additionalToolsBox = this.panelDoc.getElementById("additional-tools-box");
122 let toolsNotSupportedLabel = this.panelDoc.getElementById("tools-not-supported-label");
123 let atleastOneToolNotSupported = false;
124
125 defaultToolsBox.textContent = "";
126 additionalToolsBox.textContent = "";
127
128 let onCheckboxClick = function(id) {
129 let toolDefinition = gDevTools._tools.get(id);
130 // Set the kill switch pref boolean to true
131 Services.prefs.setBoolPref(toolDefinition.visibilityswitch, this.checked);
132 if (this.checked) {
133 gDevTools.emit("tool-registered", id);
134 }
135 else {
136 gDevTools.emit("tool-unregistered", toolDefinition);
137 }
138 };
139
140 let createToolCheckbox = tool => {
141 let checkbox = this.panelDoc.createElement("checkbox");
142 checkbox.setAttribute("id", tool.id);
143 checkbox.setAttribute("tooltiptext", tool.tooltip || "");
144 if (tool.isTargetSupported(this.target)) {
145 checkbox.setAttribute("label", tool.label);
146 }
147 else {
148 atleastOneToolNotSupported = true;
149 checkbox.setAttribute("label",
150 l10n("options.toolNotSupportedMarker", tool.label));
151 checkbox.setAttribute("unsupported", "");
152 }
153 checkbox.setAttribute("checked", this.getBoolPref(tool.visibilityswitch));
154 checkbox.addEventListener("command", onCheckboxClick.bind(checkbox, tool.id));
155 return checkbox;
156 };
157
158 // Populating the default tools lists
159 let toggleableTools = gDevTools.getDefaultTools().filter(tool => {
160 return tool.visibilityswitch;
161 });
162
163 for (let tool of toggleableTools) {
164 defaultToolsBox.appendChild(createToolCheckbox(tool));
165 }
166
167 // Populating the additional tools list that came from add-ons.
168 let atleastOneAddon = false;
169 for (let tool of gDevTools.getAdditionalTools()) {
170 atleastOneAddon = true;
171 additionalToolsBox.appendChild(createToolCheckbox(tool));
172 }
173
174 if (!atleastOneAddon) {
175 additionalToolsBox.style.display = "none";
176 additionalToolsBox.previousSibling.style.display = "none";
177 }
178
179 if (!atleastOneToolNotSupported) {
180 toolsNotSupportedLabel.style.display = "none";
181 }
182
183 this.panelWin.focus();
184 },
185
186 populatePreferences: function() {
187 let prefCheckboxes = this.panelDoc.querySelectorAll("checkbox[data-pref]");
188 for (let checkbox of prefCheckboxes) {
189 checkbox.checked = Services.prefs.getBoolPref(checkbox.getAttribute("data-pref"));
190 checkbox.addEventListener("command", function() {
191 let data = {
192 pref: this.getAttribute("data-pref"),
193 newValue: this.checked
194 };
195 data.oldValue = Services.prefs.getBoolPref(data.pref);
196 Services.prefs.setBoolPref(data.pref, data.newValue);
197 gDevTools.emit("pref-changed", data);
198 }.bind(checkbox));
199 }
200 let prefRadiogroups = this.panelDoc.querySelectorAll("radiogroup[data-pref]");
201 for (let radiogroup of prefRadiogroups) {
202 let selectedValue = Services.prefs.getCharPref(radiogroup.getAttribute("data-pref"));
203 for (let radio of radiogroup.childNodes) {
204 radiogroup.selectedIndex = -1;
205 if (radio.getAttribute("value") == selectedValue) {
206 radiogroup.selectedItem = radio;
207 break;
208 }
209 }
210 radiogroup.addEventListener("select", function() {
211 let data = {
212 pref: this.getAttribute("data-pref"),
213 newValue: this.selectedItem.getAttribute("value")
214 };
215 data.oldValue = Services.prefs.getCharPref(data.pref);
216 Services.prefs.setCharPref(data.pref, data.newValue);
217 gDevTools.emit("pref-changed", data);
218 }.bind(radiogroup));
219 }
220 let prefMenulists = this.panelDoc.querySelectorAll("menulist[data-pref]");
221 for (let menulist of prefMenulists) {
222 let pref = Services.prefs.getCharPref(menulist.getAttribute("data-pref"));
223 let menuitems = menulist.querySelectorAll("menuitem");
224 for (let menuitem of menuitems) {
225 let value = menuitem.getAttribute("value");
226 if (value === pref) {
227 menulist.selectedItem = menuitem;
228 break;
229 }
230 }
231 menulist.addEventListener("command", function() {
232 let data = {
233 pref: this.getAttribute("data-pref"),
234 newValue: this.value
235 };
236 data.oldValue = Services.prefs.getCharPref(data.pref);
237 Services.prefs.setCharPref(data.pref, data.newValue);
238 gDevTools.emit("pref-changed", data);
239 }.bind(menulist));
240 }
241
242 this.target.client.attachTab(this.target.activeTab._actor, (response) => {
243 this._origJavascriptEnabled = response.javascriptEnabled;
244 this._origCacheEnabled = response.cacheEnabled;
245
246 this._populateDisableJSCheckbox();
247 this._populateDisableCacheCheckbox();
248 });
249 },
250
251 _populateDisableJSCheckbox: function() {
252 let cbx = this.panelDoc.getElementById("devtools-disable-javascript");
253 cbx.checked = !this._origJavascriptEnabled;
254 },
255
256 _populateDisableCacheCheckbox: function() {
257 let cbx = this.panelDoc.getElementById("devtools-disable-cache");
258 cbx.checked = !this._origCacheEnabled;
259 },
260
261 /**
262 * Disables JavaScript for the currently loaded tab. We force a page refresh
263 * here because setting docShell.allowJavascript to true fails to block JS
264 * execution from event listeners added using addEventListener(), AJAX calls
265 * and timers. The page refresh prevents these things from being added in the
266 * first place.
267 *
268 * @param {Event} event
269 * The event sent by checking / unchecking the disable JS checkbox.
270 */
271 _disableJSClicked: function(event) {
272 let checked = event.target.checked;
273
274 let options = {
275 "javascriptEnabled": !checked
276 };
277
278 this.target.activeTab.reconfigure(options);
279 },
280
281 /**
282 * Disables the cache for the currently loaded tab.
283 *
284 * @param {Event} event
285 * The event sent by checking / unchecking the disable cache checkbox.
286 */
287 _disableCacheClicked: function(event) {
288 let checked = event.target.checked;
289
290 let options = {
291 "cacheEnabled": !checked
292 };
293
294 this.target.activeTab.reconfigure(options);
295 },
296
297 destroy: function() {
298 if (this.destroyPromise) {
299 return this.destroyPromise;
300 }
301
302 let deferred = promise.defer();
303
304 this.destroyPromise = deferred.promise;
305
306 let disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
307 disableJSNode.removeEventListener("click", this._disableJSClicked, false);
308
309 let disableCacheNode = this.panelDoc.getElementById("devtools-disable-cache");
310 disableCacheNode.removeEventListener("click", this._disableCacheClicked, false);
311
312 this.panelWin = this.panelDoc = null;
313 this._disableJSClicked = this._disableCacheClicked = null;
314
315 // If the cache or JavaScript is disabled we need to revert them to their
316 // original values.
317 let options = {
318 "cacheEnabled": this._origCacheEnabled,
319 "javascriptEnabled": this._origJavascriptEnabled
320 };
321 this.target.activeTab.reconfigure(options, () => {
322 this.toolbox = null;
323 deferred.resolve();
324 }, true);
325
326 return deferred.promise;
327 }
328 };

mercurial