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

     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/. */
     5 "use strict";
     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");
    12 exports.OptionsPanel = OptionsPanel;
    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 });
    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;
    39   const EventEmitter = require("devtools/toolkit/event-emitter");
    40   EventEmitter.decorate(this);
    41 }
    43 OptionsPanel.prototype = {
    45   get target() {
    46     return this.toolbox.target;
    47   },
    49   open: function() {
    50     let targetPromise;
    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     }
    59     return targetPromise.then(() => {
    60       this.setupToolsList();
    61       this.setupToolbarButtonsList();
    62       this.populatePreferences();
    64       this._disableJSClicked = this._disableJSClicked.bind(this);
    65       this._disableCacheClicked = this._disableCacheClicked.bind(this);
    67       let disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
    68       disableJSNode.addEventListener("click", this._disableJSClicked, false);
    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   },
    82   setupToolbarButtonsList: function() {
    83     let enabledToolbarButtonsBox = this.panelDoc.getElementById("enabled-toolbox-buttons-box");
    84     enabledToolbarButtonsBox.textContent = "";
    86     let toggleableButtons = this.toolbox.toolboxButtons;
    87     let setToolboxButtonsVisibility =
    88       this.toolbox.setToolboxButtonsVisibility.bind(this.toolbox);
    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     };
    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     };
   105     for (let tool of toggleableButtons) {
   106       enabledToolbarButtonsBox.appendChild(createCommandCheckbox(tool));
   107     }
   108   },
   110   getBoolPref: function(key) {
   111     try {
   112       return Services.prefs.getBoolPref(key);
   113     }
   114     catch (ex) {
   115       return true;
   116     }
   117   },
   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;
   125     defaultToolsBox.textContent = "";
   126     additionalToolsBox.textContent = "";
   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     };
   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     };
   158     // Populating the default tools lists
   159     let toggleableTools = gDevTools.getDefaultTools().filter(tool => {
   160       return tool.visibilityswitch;
   161     });
   163     for (let tool of toggleableTools) {
   164       defaultToolsBox.appendChild(createToolCheckbox(tool));
   165     }
   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     }
   174     if (!atleastOneAddon) {
   175       additionalToolsBox.style.display = "none";
   176       additionalToolsBox.previousSibling.style.display = "none";
   177     }
   179     if (!atleastOneToolNotSupported) {
   180       toolsNotSupportedLabel.style.display = "none";
   181     }
   183     this.panelWin.focus();
   184   },
   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     }
   242     this.target.client.attachTab(this.target.activeTab._actor, (response) => {
   243       this._origJavascriptEnabled = response.javascriptEnabled;
   244       this._origCacheEnabled = response.cacheEnabled;
   246       this._populateDisableJSCheckbox();
   247       this._populateDisableCacheCheckbox();
   248     });
   249   },
   251   _populateDisableJSCheckbox: function() {
   252     let cbx = this.panelDoc.getElementById("devtools-disable-javascript");
   253     cbx.checked = !this._origJavascriptEnabled;
   254   },
   256   _populateDisableCacheCheckbox: function() {
   257     let cbx = this.panelDoc.getElementById("devtools-disable-cache");
   258     cbx.checked = !this._origCacheEnabled;
   259   },
   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;
   274     let options = {
   275       "javascriptEnabled": !checked
   276     };
   278     this.target.activeTab.reconfigure(options);
   279   },
   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;
   290     let options = {
   291       "cacheEnabled": !checked
   292     };
   294     this.target.activeTab.reconfigure(options);
   295   },
   297   destroy: function() {
   298     if (this.destroyPromise) {
   299       return this.destroyPromise;
   300     }
   302     let deferred = promise.defer();
   304     this.destroyPromise = deferred.promise;
   306     let disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
   307     disableJSNode.removeEventListener("click", this._disableJSClicked, false);
   309     let disableCacheNode = this.panelDoc.getElementById("devtools-disable-cache");
   310     disableCacheNode.removeEventListener("click", this._disableCacheClicked, false);
   312     this.panelWin = this.panelDoc = null;
   313     this._disableJSClicked = this._disableCacheClicked = null;
   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);
   326     return deferred.promise;
   327   }
   328 };

mercurial