Bug 864249 - Add option to toggle JavaScript to Toolbox Options panel r=jwalker

This commit is contained in:
Michael Ratcliffe 2013-05-31 16:52:06 +01:00
parent a0fef75b61
commit 78afee66a6
8 changed files with 280 additions and 10 deletions

View File

@ -24,6 +24,9 @@ MOCHITEST_BROWSER_FILES = \
browser_toolbox_window_shortcuts.js \
browser_toolbox_window_title_changes.js \
browser_toolbox_options.js \
browser_toolbox_options_disablejs.js \
browser_toolbox_options_disablejs.html \
browser_toolbox_options_disablejs_iframe.html \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,45 @@
<html>
<head>
<title>browser_toolbox_options_disablejs.html</title>
<meta charset="UTF-8">
<style>
div {
width: 260px;
height: 24px;
border: 1px solid #000;
margin-top: 10px;
}
iframe {
height: 90px;
border: 1px solid #000;
}
h1 {
font-size: 20px
}
</style>
<script type="application/javascript;version=1.8">
function log(msg) {
let output = document.getElementById("output");
output.innerHTML = msg;
}
</script>
</head>
<body>
<h1>Test in page</h1>
<input id="logJSEnabled"
type="button"
value="Log JS Enabled"
onclick="log('JavaScript Enabled')"/>
<input id="logJSDisabled"
type="button"
value="Log JS Disabled"
onclick="log('JavaScript Disabled')"/>
<br>
<div id="output">No output</div>
<h1>Test in iframe</h1>
<iframe src="browser_toolbox_options_disablejs_iframe.html"></iframe>
</body>
</html>

View File

@ -0,0 +1,128 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that disabling JavaScript for a tab works as it should.
const TEST_URI = "http://example.com/browser/browser/devtools/framework/" +
"test/browser_toolbox_options_disablejs.html";
let doc;
let toolbox;
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
doc = content.document;
gDevTools.showToolbox(target).then(testSelectTool);
}, true);
content.location = TEST_URI;
}
function testSelectTool(aToolbox) {
toolbox = aToolbox;
toolbox.once("options-selected", testJSEnabled);
toolbox.selectTool("options");
}
function testJSEnabled(event, tool, secondPass) {
ok(true, "Toolbox selected via selectTool method");
info("Testing that JS is enabled");
let logJSEnabled = doc.getElementById("logJSEnabled");
let output = doc.getElementById("output");
// We use executeSoon here because switching docSehll.allowJavascript to true
// takes a while to become live.
executeSoon(function() {
EventUtils.synthesizeMouseAtCenter(logJSEnabled, {}, doc.defaultView);
is(output.textContent, "JavaScript Enabled", 'Output is "JavaScript Enabled"');
testJSEnabledIframe(secondPass);
});
}
function testJSEnabledIframe(secondPass) {
info("Testing that JS is enabled in the iframe");
let iframe = doc.querySelector("iframe");
let iframeDoc = iframe.contentDocument;
let logJSEnabled = iframeDoc.getElementById("logJSEnabled");
let output = iframeDoc.getElementById("output");
EventUtils.synthesizeMouseAtCenter(logJSEnabled, {}, iframe.contentWindow);
is(output.textContent, "JavaScript Enabled",
'Output is "JavaScript Enabled" in iframe');
if (secondPass) {
finishUp();
} else {
toggleJS().then(testJSDisabled);
}
}
function toggleJS() {
let deferred = Promise.defer();
let panel = toolbox.getCurrentPanel();
let cbx = panel.panelDoc.getElementById("devtools-disable-javascript");
cbx.scrollIntoView();
if (cbx.checked) {
info("Clearing checkbox to re-enable JS");
} else {
info("Checking checkbox to disable JS");
}
// After uising scrollIntoView() we need to use executeSoon() to wait for the
// browser to scroll.
executeSoon(function() {
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
doc = content.document;
deferred.resolve();
}, true);
EventUtils.synthesizeMouseAtCenter(cbx, {}, panel.panelWin);
});
return deferred.promise;
}
function testJSDisabled() {
info("Testing that JS is disabled");
let logJSDisabled = doc.getElementById("logJSDisabled");
let output = doc.getElementById("output");
EventUtils.synthesizeMouseAtCenter(logJSDisabled, {}, doc.defaultView);
ok(output.textContent !== "JavaScript Disabled",
'output is not "JavaScript Disabled"');
testJSDisabledIframe();
}
function testJSDisabledIframe() {
info("Testing that JS is disabled in the iframe");
let iframe = doc.querySelector("iframe");
let iframeDoc = iframe.contentDocument;
let logJSDisabled = iframeDoc.getElementById("logJSDisabled");
let output = iframeDoc.getElementById("output");
EventUtils.synthesizeMouseAtCenter(logJSDisabled, {}, iframe.contentWindow);
ok(output.textContent !== "JavaScript Disabled",
'output is not "JavaScript Disabled" in iframe');
toggleJS().then(function() {
testJSEnabled(null, null, true);
});
}
function finishUp() {
doc = toolbox = null;
finish();
}

View File

@ -0,0 +1,33 @@
<html>
<head>
<title>browser_toolbox_options_disablejs.html</title>
<meta charset="UTF-8">
<style>
div {
width: 260px;
height: 24px;
border: 1px solid #000;
margin-top: 10px;
}
</style>
<script type="application/javascript;version=1.8">
function log(msg) {
let output = document.getElementById("output");
output.innerHTML = msg;
}
</script>
</head>
<body>
<input id="logJSEnabled"
type="button"
value="Log JS Enabled"
onclick="log('JavaScript Enabled')"/>
<input id="logJSDisabled"
type="button"
value="Log JS Disabled"
onclick="log('JavaScript Disabled')"/>
<br>
<div id="output">No output</div>
</body>
</html>

View File

@ -20,6 +20,7 @@ exports.OptionsPanel = OptionsPanel;
function OptionsPanel(iframeWindow, toolbox) {
this.panelDoc = iframeWindow.document;
this.panelWin = iframeWindow;
this.toolbox = toolbox;
EventEmitter.decorate(this);
};
@ -32,6 +33,11 @@ OptionsPanel.prototype = {
this.setupToolsList();
this.populatePreferences();
this._disableJSClicked = this._disableJSClicked.bind(this);
let disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
disableJSNode.addEventListener("click", this._disableJSClicked, false);
this.emit("ready");
deferred.resolve(this);
return deferred.promise;
@ -136,7 +142,34 @@ OptionsPanel.prototype = {
}
},
/**
* Disables JavaScript for the currently loaded tab. We force a page refresh
* here because setting docShell.allowJavascript to true fails to block JS
* execution from event listeners added using addEventListener(), AJAX calls
* and timers. The page refresh prevents these things from being added in the
* first place.
*
* @param {Event} event
* The event sent by checking / unchecking the disable JS checkbox.
*/
_disableJSClicked: function(event) {
let checked = event.target.checked;
let linkedBrowser = this.toolbox._host.hostTab.linkedBrowser;
let win = linkedBrowser.contentWindow;
let docShell = linkedBrowser.docShell;
if (typeof this.toolbox._origAllowJavascript == "undefined") {
this.toolbox._origAllowJavascript = docShell.allowJavascript;
}
docShell.allowJavascript = !checked;
win.location.reload();
},
destroy: function OP_destroy() {
this.panelWin = this.panelDoc = null;
let disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
disableJSNode.removeEventListener("click", this._disableJSClicked, false);
this.panelWin = this.panelDoc = this.toolbox = this._disableJSClicked = null;
}
};

View File

@ -34,14 +34,19 @@
tooltiptext="&options.enablePersistentLogging.tooltip;"
data-pref="devtools.webconsole.persistlog"/>
</vbox>
<label value="&options.context.label;"/>
<label value="&options.context.advancedSettings;"/>
<vbox id="context-options" class="options-groupbox">
<checkbox label="&options.enableChrome.label;"
<checkbox label="&options.enableChrome.label2;"
tooltiptext="&options.enableChrome.tooltip;"
data-pref="devtools.chrome.enabled"/>
<checkbox label="&options.enableRemote.label;"
<checkbox label="&options.enableRemote.label2;"
tooltiptext="&options.enableRemote.tooltip;"
data-pref="devtools.debugger.remote-enabled"/>
<checkbox id="devtools-disable-javascript"
label="&options.disableJavaScript.label;"
tooltiptext="&options.disableJavaScript.tooltip;"/>
<label value="&options.context.requiresRestart;"/>
<label value="&options.context.triggersPageRefresh;"/>
</vbox>
</vbox>
</hbox>

View File

@ -728,6 +728,14 @@ Toolbox.prototype = {
gDevTools.off("tool-registered", this._toolRegistered);
gDevTools.off("tool-unregistered", this._toolUnregistered);
// Revert docShell.allowJavascript back to it's original value if it was
// changed via the Disable JS option.
if (typeof this._origAllowJavascript != "undefined") {
let docShell = this._host.hostTab.linkedBrowser.docShell;
docShell.allowJavascript = this._origAllowJavascript;
delete this._origAllowJavascript;
}
let outstanding = [];
for (let [id, panel] of this._toolPanels) {

View File

@ -10,23 +10,38 @@
<!ENTITY toolboxCloseButton.tooltip "Close Developer Tools">
<!ENTITY toolboxOptionsButton.key "O">
<!-- LOCALIZATION NOTE (options.context.label): This is the label for the
- heading of the group of two about:config preferences to toggle chrome
- and remote debugging in the options panel. -->
<!ENTITY options.context.label "Advanced settings (requires a browser restart)">
<!-- LOCALIZATION NOTE (options.context.advancedSettings): This is the label for
- the heading of the advanced settings group in the options panel. -->
<!ENTITY options.context.advancedSettings "Advanced settings">
<!-- LOCALIZATION NOTE (options.context.requiresRestart): This is the requires
- restart label at the bottom of the advanced settings group in the options
- panel. -->
<!ENTITY options.context.requiresRestart "* Requires browser restart">
<!-- LOCALIZATION NOTE (options.context.triggersPageRefresh): This is the
- triggers page refresh label at the bottom of the advanced settings group in
- the options panel. -->
<!ENTITY options.context.triggersPageRefresh "&#8224; Triggers page refresh">
<!-- LOCALIZATION NOTE (options.enableChrome.label): This is the label for the
- checkbox that toggles chrome debugging, i.e. devtools.chrome.enabled
- boolean preference in about:config, in the options panel. -->
<!ENTITY options.enableChrome.label "Enable chrome debugging">
<!ENTITY options.enableChrome.label2 "Enable chrome debugging *">
<!ENTITY options.enableChrome.tooltip "Turning this option on will allow you to use various developer tools in browser context">
<!-- LOCALIZATION NOTE (options.enableRemote.label): This is the label for the
- checkbox that toggles remote debugging, i.e. devtools.debugger.remote-enabled
- boolean preference in about:config, in the options panel. -->
<!ENTITY options.enableRemote.label "Enable remote debugging">
<!ENTITY options.enableRemote.label2 "Enable remote debugging *">
<!ENTITY options.enableRemote.tooltip "Turning this option on will allow the developer tools to debug remote Firefox instance like Firefox OS">
<!-- LOCALIZATION NOTE (options.disableJavaScript.label,
- options.disableJavaScript.tooltip): This is the options panel label and
- tooltip for the checkbox that toggles JavaScript on or off. -->
<!ENTITY options.disableJavaScript.label "Disable JavaScript for the current tab (temporary) &#8224;">
<!ENTITY options.disableJavaScript.tooltip "Turning this option on will disable JavaScript for the current tab. If the tab or the toolbox is closed then this setting will be forgotten.">
<!-- LOCALIZATION NOTE (options.selectDefaultTools.label): This is the label for
- the heading of group of checkboxes corresponding to the default developer
- tools. -->