browser/devtools/framework/toolbox-options.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial