browser/devtools/framework/toolbox-options.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/devtools/framework/toolbox-options.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,328 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +"use strict";
     1.9 +
    1.10 +const {Cu, Cc, Ci} = require("chrome");
    1.11 +const Services = require("Services");
    1.12 +Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    1.13 +XPCOMUtils.defineLazyModuleGetter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
    1.14 +
    1.15 +exports.OptionsPanel = OptionsPanel;
    1.16 +
    1.17 +XPCOMUtils.defineLazyGetter(this, "l10n", function() {
    1.18 +  let bundle = Services.strings.createBundle("chrome://browser/locale/devtools/toolbox.properties");
    1.19 +  let l10n = function(aName, ...aArgs) {
    1.20 +    try {
    1.21 +      if (aArgs.length == 0) {
    1.22 +        return bundle.GetStringFromName(aName);
    1.23 +      } else {
    1.24 +        return bundle.formatStringFromName(aName, aArgs, aArgs.length);
    1.25 +      }
    1.26 +    } catch (ex) {
    1.27 +      Services.console.logStringMessage("Error reading '" + aName + "'");
    1.28 +    }
    1.29 +  };
    1.30 +  return l10n;
    1.31 +});
    1.32 +
    1.33 +/**
    1.34 + * Represents the Options Panel in the Toolbox.
    1.35 + */
    1.36 +function OptionsPanel(iframeWindow, toolbox) {
    1.37 +  this.panelDoc = iframeWindow.document;
    1.38 +  this.panelWin = iframeWindow;
    1.39 +  this.toolbox = toolbox;
    1.40 +  this.isReady = false;
    1.41 +
    1.42 +  const EventEmitter = require("devtools/toolkit/event-emitter");
    1.43 +  EventEmitter.decorate(this);
    1.44 +}
    1.45 +
    1.46 +OptionsPanel.prototype = {
    1.47 +
    1.48 +  get target() {
    1.49 +    return this.toolbox.target;
    1.50 +  },
    1.51 +
    1.52 +  open: function() {
    1.53 +    let targetPromise;
    1.54 +
    1.55 +    // For local debugging we need to make the target remote.
    1.56 +    if (!this.target.isRemote) {
    1.57 +      targetPromise = this.target.makeRemote();
    1.58 +    } else {
    1.59 +      targetPromise = promise.resolve(this.target);
    1.60 +    }
    1.61 +
    1.62 +    return targetPromise.then(() => {
    1.63 +      this.setupToolsList();
    1.64 +      this.setupToolbarButtonsList();
    1.65 +      this.populatePreferences();
    1.66 +
    1.67 +      this._disableJSClicked = this._disableJSClicked.bind(this);
    1.68 +      this._disableCacheClicked = this._disableCacheClicked.bind(this);
    1.69 +
    1.70 +      let disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
    1.71 +      disableJSNode.addEventListener("click", this._disableJSClicked, false);
    1.72 +
    1.73 +      let disableCacheNode = this.panelDoc.getElementById("devtools-disable-cache");
    1.74 +      disableCacheNode.addEventListener("click", this._disableCacheClicked, false);
    1.75 +    }).then(() => {
    1.76 +      this.isReady = true;
    1.77 +      this.emit("ready");
    1.78 +      return this;
    1.79 +    }).then(null, function onError(aReason) {
    1.80 +      Cu.reportError("OptionsPanel open failed. " +
    1.81 +                     aReason.error + ": " + aReason.message);
    1.82 +    });
    1.83 +  },
    1.84 +
    1.85 +  setupToolbarButtonsList: function() {
    1.86 +    let enabledToolbarButtonsBox = this.panelDoc.getElementById("enabled-toolbox-buttons-box");
    1.87 +    enabledToolbarButtonsBox.textContent = "";
    1.88 +
    1.89 +    let toggleableButtons = this.toolbox.toolboxButtons;
    1.90 +    let setToolboxButtonsVisibility =
    1.91 +      this.toolbox.setToolboxButtonsVisibility.bind(this.toolbox);
    1.92 +
    1.93 +    let onCheckboxClick = (checkbox) => {
    1.94 +      let toolDefinition = toggleableButtons.filter(tool => tool.id === checkbox.id)[0];
    1.95 +      Services.prefs.setBoolPref(toolDefinition.visibilityswitch, checkbox.checked);
    1.96 +      setToolboxButtonsVisibility();
    1.97 +    };
    1.98 +
    1.99 +    let createCommandCheckbox = tool => {
   1.100 +      let checkbox = this.panelDoc.createElement("checkbox");
   1.101 +      checkbox.setAttribute("id", tool.id);
   1.102 +      checkbox.setAttribute("label", tool.label);
   1.103 +      checkbox.setAttribute("checked", this.getBoolPref(tool.visibilityswitch));
   1.104 +      checkbox.addEventListener("command", onCheckboxClick.bind(this, checkbox));
   1.105 +      return checkbox;
   1.106 +    };
   1.107 +
   1.108 +    for (let tool of toggleableButtons) {
   1.109 +      enabledToolbarButtonsBox.appendChild(createCommandCheckbox(tool));
   1.110 +    }
   1.111 +  },
   1.112 +
   1.113 +  getBoolPref: function(key) {
   1.114 +    try {
   1.115 +      return Services.prefs.getBoolPref(key);
   1.116 +    }
   1.117 +    catch (ex) {
   1.118 +      return true;
   1.119 +    }
   1.120 +  },
   1.121 +
   1.122 +  setupToolsList: function() {
   1.123 +    let defaultToolsBox = this.panelDoc.getElementById("default-tools-box");
   1.124 +    let additionalToolsBox = this.panelDoc.getElementById("additional-tools-box");
   1.125 +    let toolsNotSupportedLabel = this.panelDoc.getElementById("tools-not-supported-label");
   1.126 +    let atleastOneToolNotSupported = false;
   1.127 +
   1.128 +    defaultToolsBox.textContent = "";
   1.129 +    additionalToolsBox.textContent = "";
   1.130 +
   1.131 +    let onCheckboxClick = function(id) {
   1.132 +      let toolDefinition = gDevTools._tools.get(id);
   1.133 +      // Set the kill switch pref boolean to true
   1.134 +      Services.prefs.setBoolPref(toolDefinition.visibilityswitch, this.checked);
   1.135 +      if (this.checked) {
   1.136 +        gDevTools.emit("tool-registered", id);
   1.137 +      }
   1.138 +      else {
   1.139 +        gDevTools.emit("tool-unregistered", toolDefinition);
   1.140 +      }
   1.141 +    };
   1.142 +
   1.143 +    let createToolCheckbox = tool => {
   1.144 +      let checkbox = this.panelDoc.createElement("checkbox");
   1.145 +      checkbox.setAttribute("id", tool.id);
   1.146 +      checkbox.setAttribute("tooltiptext", tool.tooltip || "");
   1.147 +      if (tool.isTargetSupported(this.target)) {
   1.148 +        checkbox.setAttribute("label", tool.label);
   1.149 +      }
   1.150 +      else {
   1.151 +        atleastOneToolNotSupported = true;
   1.152 +        checkbox.setAttribute("label",
   1.153 +                              l10n("options.toolNotSupportedMarker", tool.label));
   1.154 +        checkbox.setAttribute("unsupported", "");
   1.155 +      }
   1.156 +      checkbox.setAttribute("checked", this.getBoolPref(tool.visibilityswitch));
   1.157 +      checkbox.addEventListener("command", onCheckboxClick.bind(checkbox, tool.id));
   1.158 +      return checkbox;
   1.159 +    };
   1.160 +
   1.161 +    // Populating the default tools lists
   1.162 +    let toggleableTools = gDevTools.getDefaultTools().filter(tool => {
   1.163 +      return tool.visibilityswitch;
   1.164 +    });
   1.165 +
   1.166 +    for (let tool of toggleableTools) {
   1.167 +      defaultToolsBox.appendChild(createToolCheckbox(tool));
   1.168 +    }
   1.169 +
   1.170 +    // Populating the additional tools list that came from add-ons.
   1.171 +    let atleastOneAddon = false;
   1.172 +    for (let tool of gDevTools.getAdditionalTools()) {
   1.173 +      atleastOneAddon = true;
   1.174 +      additionalToolsBox.appendChild(createToolCheckbox(tool));
   1.175 +    }
   1.176 +
   1.177 +    if (!atleastOneAddon) {
   1.178 +      additionalToolsBox.style.display = "none";
   1.179 +      additionalToolsBox.previousSibling.style.display = "none";
   1.180 +    }
   1.181 +
   1.182 +    if (!atleastOneToolNotSupported) {
   1.183 +      toolsNotSupportedLabel.style.display = "none";
   1.184 +    }
   1.185 +
   1.186 +    this.panelWin.focus();
   1.187 +  },
   1.188 +
   1.189 +  populatePreferences: function() {
   1.190 +    let prefCheckboxes = this.panelDoc.querySelectorAll("checkbox[data-pref]");
   1.191 +    for (let checkbox of prefCheckboxes) {
   1.192 +      checkbox.checked = Services.prefs.getBoolPref(checkbox.getAttribute("data-pref"));
   1.193 +      checkbox.addEventListener("command", function() {
   1.194 +        let data = {
   1.195 +          pref: this.getAttribute("data-pref"),
   1.196 +          newValue: this.checked
   1.197 +        };
   1.198 +        data.oldValue = Services.prefs.getBoolPref(data.pref);
   1.199 +        Services.prefs.setBoolPref(data.pref, data.newValue);
   1.200 +        gDevTools.emit("pref-changed", data);
   1.201 +      }.bind(checkbox));
   1.202 +    }
   1.203 +    let prefRadiogroups = this.panelDoc.querySelectorAll("radiogroup[data-pref]");
   1.204 +    for (let radiogroup of prefRadiogroups) {
   1.205 +      let selectedValue = Services.prefs.getCharPref(radiogroup.getAttribute("data-pref"));
   1.206 +      for (let radio of radiogroup.childNodes) {
   1.207 +        radiogroup.selectedIndex = -1;
   1.208 +        if (radio.getAttribute("value") == selectedValue) {
   1.209 +          radiogroup.selectedItem = radio;
   1.210 +          break;
   1.211 +        }
   1.212 +      }
   1.213 +      radiogroup.addEventListener("select", function() {
   1.214 +        let data = {
   1.215 +          pref: this.getAttribute("data-pref"),
   1.216 +          newValue: this.selectedItem.getAttribute("value")
   1.217 +        };
   1.218 +        data.oldValue = Services.prefs.getCharPref(data.pref);
   1.219 +        Services.prefs.setCharPref(data.pref, data.newValue);
   1.220 +        gDevTools.emit("pref-changed", data);
   1.221 +      }.bind(radiogroup));
   1.222 +    }
   1.223 +    let prefMenulists = this.panelDoc.querySelectorAll("menulist[data-pref]");
   1.224 +    for (let menulist of prefMenulists) {
   1.225 +      let pref = Services.prefs.getCharPref(menulist.getAttribute("data-pref"));
   1.226 +      let menuitems = menulist.querySelectorAll("menuitem");
   1.227 +      for (let menuitem of menuitems) {
   1.228 +        let value = menuitem.getAttribute("value");
   1.229 +        if (value === pref) {
   1.230 +          menulist.selectedItem = menuitem;
   1.231 +          break;
   1.232 +        }
   1.233 +      }
   1.234 +      menulist.addEventListener("command", function() {
   1.235 +        let data = {
   1.236 +          pref: this.getAttribute("data-pref"),
   1.237 +          newValue: this.value
   1.238 +        };
   1.239 +        data.oldValue = Services.prefs.getCharPref(data.pref);
   1.240 +        Services.prefs.setCharPref(data.pref, data.newValue);
   1.241 +        gDevTools.emit("pref-changed", data);
   1.242 +      }.bind(menulist));
   1.243 +    }
   1.244 +
   1.245 +    this.target.client.attachTab(this.target.activeTab._actor, (response) => {
   1.246 +      this._origJavascriptEnabled = response.javascriptEnabled;
   1.247 +      this._origCacheEnabled = response.cacheEnabled;
   1.248 +
   1.249 +      this._populateDisableJSCheckbox();
   1.250 +      this._populateDisableCacheCheckbox();
   1.251 +    });
   1.252 +  },
   1.253 +
   1.254 +  _populateDisableJSCheckbox: function() {
   1.255 +    let cbx = this.panelDoc.getElementById("devtools-disable-javascript");
   1.256 +    cbx.checked = !this._origJavascriptEnabled;
   1.257 +  },
   1.258 +
   1.259 +  _populateDisableCacheCheckbox: function() {
   1.260 +    let cbx = this.panelDoc.getElementById("devtools-disable-cache");
   1.261 +    cbx.checked = !this._origCacheEnabled;
   1.262 +  },
   1.263 +
   1.264 +  /**
   1.265 +   * Disables JavaScript for the currently loaded tab. We force a page refresh
   1.266 +   * here because setting docShell.allowJavascript to true fails to block JS
   1.267 +   * execution from event listeners added using addEventListener(), AJAX calls
   1.268 +   * and timers. The page refresh prevents these things from being added in the
   1.269 +   * first place.
   1.270 +   *
   1.271 +   * @param {Event} event
   1.272 +   *        The event sent by checking / unchecking the disable JS checkbox.
   1.273 +   */
   1.274 +  _disableJSClicked: function(event) {
   1.275 +    let checked = event.target.checked;
   1.276 +
   1.277 +    let options = {
   1.278 +      "javascriptEnabled": !checked
   1.279 +    };
   1.280 +
   1.281 +    this.target.activeTab.reconfigure(options);
   1.282 +  },
   1.283 +
   1.284 +  /**
   1.285 +   * Disables the cache for the currently loaded tab.
   1.286 +   *
   1.287 +   * @param {Event} event
   1.288 +   *        The event sent by checking / unchecking the disable cache checkbox.
   1.289 +   */
   1.290 +  _disableCacheClicked: function(event) {
   1.291 +    let checked = event.target.checked;
   1.292 +
   1.293 +    let options = {
   1.294 +      "cacheEnabled": !checked
   1.295 +    };
   1.296 +
   1.297 +    this.target.activeTab.reconfigure(options);
   1.298 +  },
   1.299 +
   1.300 +  destroy: function() {
   1.301 +    if (this.destroyPromise) {
   1.302 +      return this.destroyPromise;
   1.303 +    }
   1.304 +
   1.305 +    let deferred = promise.defer();
   1.306 +
   1.307 +    this.destroyPromise = deferred.promise;
   1.308 +
   1.309 +    let disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
   1.310 +    disableJSNode.removeEventListener("click", this._disableJSClicked, false);
   1.311 +
   1.312 +    let disableCacheNode = this.panelDoc.getElementById("devtools-disable-cache");
   1.313 +    disableCacheNode.removeEventListener("click", this._disableCacheClicked, false);
   1.314 +
   1.315 +    this.panelWin = this.panelDoc = null;
   1.316 +    this._disableJSClicked = this._disableCacheClicked = null;
   1.317 +
   1.318 +    // If the cache or JavaScript is disabled we need to revert them to their
   1.319 +    // original values.
   1.320 +    let options = {
   1.321 +      "cacheEnabled": this._origCacheEnabled,
   1.322 +      "javascriptEnabled": this._origJavascriptEnabled
   1.323 +    };
   1.324 +    this.target.activeTab.reconfigure(options, () => {
   1.325 +      this.toolbox = null;
   1.326 +      deferred.resolve();
   1.327 +    }, true);
   1.328 +
   1.329 +    return deferred.promise;
   1.330 +  }
   1.331 +};

mercurial