mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1227135 - about:debugging : disable debug buttons if addons debugging disabled;r=ochameau
When a preference impacting about:debugging changes, the current tab will be rendered again. Each "target" is responsible for checking if Debugging should be allowed. If not, the debug button should be disabled. Currently only extensions/addons can be disabled, depending on the value of the "devtools.chrome.enabled" preference Adds a mochitest checking this scenario.
This commit is contained in:
parent
87341a135e
commit
41595106e9
@ -33,6 +33,9 @@ const Strings = Services.strings.createBundle(
|
||||
var AboutDebugging = {
|
||||
_prefListeners: [],
|
||||
|
||||
// Pointer to the current React component.
|
||||
_component: null,
|
||||
|
||||
_categories: null,
|
||||
get categories() {
|
||||
// If needed, initialize the list of available categories.
|
||||
@ -66,11 +69,11 @@ var AboutDebugging = {
|
||||
location.hash = "#" + category;
|
||||
|
||||
if (category == "addons") {
|
||||
React.render(React.createElement(AddonsComponent, { client: this.client }),
|
||||
document.querySelector("#addons"));
|
||||
this._component = React.render(React.createElement(AddonsComponent,
|
||||
{client: this.client}), document.querySelector("#addons"));
|
||||
} else if (category == "workers") {
|
||||
React.render(React.createElement(WorkersComponent, { client: this.client }),
|
||||
document.querySelector("#workers"));
|
||||
this._component = React.render(React.createElement(WorkersComponent,
|
||||
{client: this.client}), document.querySelector("#workers"));
|
||||
}
|
||||
},
|
||||
|
||||
@ -82,16 +85,22 @@ var AboutDebugging = {
|
||||
let elements = document.querySelectorAll("input[type=checkbox][data-pref]");
|
||||
Array.map(elements, element => {
|
||||
let pref = element.dataset.pref;
|
||||
|
||||
let updatePref = () => {
|
||||
Services.prefs.setBoolPref(pref, element.checked);
|
||||
};
|
||||
element.addEventListener("change", updatePref, false);
|
||||
let updateCheckbox = () => {
|
||||
|
||||
let onPreferenceChanged = () => {
|
||||
element.checked = Services.prefs.getBoolPref(pref);
|
||||
this.update();
|
||||
};
|
||||
Services.prefs.addObserver(pref, updateCheckbox, false);
|
||||
this._prefListeners.push([pref, updateCheckbox]);
|
||||
updateCheckbox();
|
||||
|
||||
Services.prefs.addObserver(pref, onPreferenceChanged, false);
|
||||
this._prefListeners.push([pref, onPreferenceChanged]);
|
||||
|
||||
// Initialize the current checkbox element.
|
||||
element.checked = Services.prefs.getBoolPref(pref);
|
||||
});
|
||||
|
||||
// Link buttons to their associated actions.
|
||||
@ -112,6 +121,12 @@ var AboutDebugging = {
|
||||
});
|
||||
},
|
||||
|
||||
update() {
|
||||
if (this._component) {
|
||||
this._component.setState({});
|
||||
}
|
||||
},
|
||||
|
||||
loadAddonFromFile() {
|
||||
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
fp.init(window,
|
||||
|
@ -41,8 +41,10 @@ exports.AddonsComponent = React.createClass({
|
||||
let client = this.props.client;
|
||||
let targets = this.state.extensions;
|
||||
let name = Strings.GetStringFromName("extensions");
|
||||
let debugDisabled = !Services.prefs.getBoolPref("devtools.chrome.enabled");
|
||||
return React.createElement("div", null,
|
||||
React.createElement(TargetListComponent, { name, targets, client })
|
||||
React.createElement(TargetListComponent,
|
||||
{ name, targets, client, debugDisabled })
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -23,8 +23,10 @@ exports.TargetListComponent = React.createClass({
|
||||
|
||||
render() {
|
||||
let client = this.props.client;
|
||||
let debugDisabled = this.props.debugDisabled;
|
||||
let targets = this.props.targets.sort(LocaleCompare).map(target => {
|
||||
return React.createElement(TargetComponent, { client, target });
|
||||
return React.createElement(TargetComponent,
|
||||
{ client, target, debugDisabled });
|
||||
});
|
||||
return (
|
||||
React.createElement("div", { id: this.props.id, className: "targets" },
|
||||
|
@ -54,6 +54,8 @@ exports.TargetComponent = React.createClass({
|
||||
|
||||
render() {
|
||||
let target = this.props.target;
|
||||
let debugDisabled = this.props.debugDisabled;
|
||||
|
||||
return React.createElement("div", { className: "target" },
|
||||
React.createElement("img", {
|
||||
className: "target-icon",
|
||||
@ -62,8 +64,11 @@ exports.TargetComponent = React.createClass({
|
||||
React.createElement("div", { className: "target-name" }, target.name),
|
||||
React.createElement("div", { className: "target-url" }, target.url)
|
||||
),
|
||||
React.createElement("button", { onClick: this.debug },
|
||||
Strings.GetStringFromName("debug"))
|
||||
React.createElement("button", {
|
||||
className: "debug-button",
|
||||
onClick: this.debug,
|
||||
disabled: debugDisabled,
|
||||
}, Strings.GetStringFromName("debug"))
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -9,5 +9,6 @@ support-files =
|
||||
service-workers/empty-sw.js
|
||||
|
||||
[browser_addons_install.js]
|
||||
[browser_addons_toggle_debug.js]
|
||||
[browser_service_workers.js]
|
||||
[browser_service_workers_timeout.js]
|
||||
|
@ -2,33 +2,13 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
var {AddonManager} = Cu.import("resource://gre/modules/AddonManager.jsm", {});
|
||||
|
||||
const ADDON_ID = "test-devtools@mozilla.org";
|
||||
const ADDON_NAME = "test-devtools";
|
||||
|
||||
add_task(function *() {
|
||||
let { tab, document } = yield openAboutDebugging("addons");
|
||||
|
||||
// Mock the file picker to select a test addon
|
||||
let MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.init(null);
|
||||
let file = get_supports_file("addons/unpacked/install.rdf");
|
||||
MockFilePicker.returnFiles = [file.file];
|
||||
|
||||
// Wait for a message sent by the addon's bootstrap.js file
|
||||
let promise = new Promise(done => {
|
||||
Services.obs.addObserver(function listener() {
|
||||
Services.obs.removeObserver(listener, "test-devtools", false);
|
||||
ok(true, "Addon installed and running its bootstrap.js file");
|
||||
done();
|
||||
}, "test-devtools", false);
|
||||
});
|
||||
// Trigger the file picker by clicking on the button
|
||||
document.getElementById("load-addon-from-file").click();
|
||||
|
||||
// Wait for the addon execution
|
||||
yield promise;
|
||||
yield installAddon(document, "addons/unpacked/install.rdf", "test-devtools");
|
||||
|
||||
// Check that the addon appears in the UI
|
||||
let names = [...document.querySelectorAll("#addons .target-name")];
|
||||
@ -36,21 +16,7 @@ add_task(function *() {
|
||||
ok(names.includes(ADDON_NAME), "The addon name appears in the list of addons: " + names);
|
||||
|
||||
// Now uninstall this addon
|
||||
yield new Promise(done => {
|
||||
AddonManager.getAddonByID(ADDON_ID, addon => {
|
||||
let listener = {
|
||||
onUninstalled: function(aUninstalledAddon) {
|
||||
if (aUninstalledAddon != addon) {
|
||||
return;
|
||||
}
|
||||
AddonManager.removeAddonListener(listener);
|
||||
done();
|
||||
}
|
||||
};
|
||||
AddonManager.addAddonListener(listener);
|
||||
addon.uninstall();
|
||||
});
|
||||
});
|
||||
yield uninstallAddon(ADDON_ID);
|
||||
|
||||
// Ensure that the UI removes the addon from the list
|
||||
names = [...document.querySelectorAll("#addons .target-name")];
|
||||
|
@ -0,0 +1,58 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that individual Debug buttons are disabled when "Addons debugging"
|
||||
// is disabled.
|
||||
// Test that the buttons are updated dynamically if the preference changes.
|
||||
|
||||
const ADDON_ID = "test-devtools@mozilla.org";
|
||||
|
||||
add_task(function* () {
|
||||
info("Turn off addon debugging.");
|
||||
yield new Promise(resolve => {
|
||||
let options = {"set": [
|
||||
["devtools.chrome.enabled", false],
|
||||
]};
|
||||
SpecialPowers.pushPrefEnv(options, resolve);
|
||||
});
|
||||
|
||||
let { tab, document } = yield openAboutDebugging("addons");
|
||||
|
||||
info("Install a test addon.");
|
||||
yield installAddon(document, "addons/unpacked/install.rdf", "test-devtools");
|
||||
|
||||
let addonDebugCheckbox = document.querySelector("#enable-addon-debugging");
|
||||
ok(!addonDebugCheckbox.checked, "Addons debugging should be disabled.");
|
||||
|
||||
info("Check all debug buttons are disabled.");
|
||||
let debugButtons = [...document.querySelectorAll("#addons .debug-button")];
|
||||
ok(debugButtons.every(b => b.disabled), "Debug buttons should be disabled");
|
||||
|
||||
info("Click on 'Enable addons debugging' checkbox.");
|
||||
let addonsContainer = document.getElementById("addons");
|
||||
let onAddonsMutation = waitForMutation(addonsContainer,
|
||||
{ subtree: true, attributes: true });
|
||||
addonDebugCheckbox.click();
|
||||
yield onAddonsMutation;
|
||||
|
||||
info("Check all debug buttons are enabled.");
|
||||
ok(addonDebugCheckbox.checked, "Addons debugging should be enabled.");
|
||||
debugButtons = [...document.querySelectorAll("#addons .debug-button")];
|
||||
ok(debugButtons.every(b => !b.disabled), "Debug buttons should be enabled");
|
||||
|
||||
info("Click again on 'Enable addons debugging' checkbox.");
|
||||
onAddonsMutation = waitForMutation(addonsContainer,
|
||||
{ subtree: true, attributes: true });
|
||||
addonDebugCheckbox.click();
|
||||
yield onAddonsMutation;
|
||||
|
||||
info("Check all debug buttons are disabled again.");
|
||||
debugButtons = [...document.querySelectorAll("#addons .debug-button")];
|
||||
ok(debugButtons.every(b => b.disabled), "Debug buttons should be disabled");
|
||||
|
||||
info("Uninstall addon installed earlier.");
|
||||
yield uninstallAddon(ADDON_ID);
|
||||
|
||||
yield closeAboutDebugging(tab);
|
||||
});
|
@ -9,17 +9,6 @@ const HTTP_ROOT = CHROME_ROOT.replace("chrome://mochitests/content/",
|
||||
const SERVICE_WORKER = HTTP_ROOT + "service-workers/empty-sw.js";
|
||||
const TAB_URL = HTTP_ROOT + "service-workers/empty-sw.html";
|
||||
|
||||
function waitForWorkersUpdate(document) {
|
||||
return new Promise(done => {
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
observer.disconnect();
|
||||
done();
|
||||
});
|
||||
var target = document.getElementById("service-workers");
|
||||
observer.observe(target, { childList: true });
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function *() {
|
||||
yield new Promise(done => {
|
||||
let options = {"set": [
|
||||
@ -32,7 +21,8 @@ add_task(function *() {
|
||||
|
||||
let swTab = yield addTab(TAB_URL);
|
||||
|
||||
yield waitForWorkersUpdate(document);
|
||||
let serviceWorkersElement = document.getElementById("service-workers");
|
||||
yield waitForMutation(serviceWorkersElement, { childList: true });
|
||||
|
||||
// Check that the service worker appears in the UI
|
||||
let names = [...document.querySelectorAll("#service-workers .target-name")];
|
||||
@ -40,7 +30,8 @@ add_task(function *() {
|
||||
ok(names.includes(SERVICE_WORKER), "The service worker url appears in the list: " + names);
|
||||
|
||||
// Finally, unregister the service worker itself
|
||||
let aboutDebuggingUpdate = waitForWorkersUpdate(document);
|
||||
let aboutDebuggingUpdate = waitForMutation(serviceWorkersElement,
|
||||
{ childList: true });
|
||||
|
||||
// Use message manager to work with e10s
|
||||
let frameScript = function () {
|
||||
|
@ -11,17 +11,6 @@ const TAB_URL = HTTP_ROOT + "service-workers/empty-sw.html";
|
||||
|
||||
const SW_TIMEOUT = 1000;
|
||||
|
||||
function waitForWorkersUpdate(document) {
|
||||
return new Promise(done => {
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
observer.disconnect();
|
||||
done();
|
||||
});
|
||||
var target = document.getElementById("service-workers");
|
||||
observer.observe(target, { childList: true });
|
||||
});
|
||||
}
|
||||
|
||||
function assertHasWorker(expected, document, type, name) {
|
||||
let names = [...document.querySelectorAll("#" + type + " .target-name")];
|
||||
names = names.map(element => element.textContent);
|
||||
@ -45,7 +34,8 @@ add_task(function *() {
|
||||
|
||||
let swTab = yield addTab(TAB_URL);
|
||||
|
||||
yield waitForWorkersUpdate(document);
|
||||
let serviceWorkersElement = document.getElementById("service-workers");
|
||||
yield waitForMutation(serviceWorkersElement, { childList: true });
|
||||
|
||||
assertHasWorker(true, document, "service-workers", SERVICE_WORKER);
|
||||
|
||||
@ -100,7 +90,7 @@ add_task(function *() {
|
||||
// Now ensure that the worker is correctly destroyed
|
||||
// after we destroy the toolbox.
|
||||
// The list should update once it get destroyed.
|
||||
yield waitForWorkersUpdate(document);
|
||||
yield waitForMutation(serviceWorkersElement, { childList: true });
|
||||
|
||||
assertHasWorker(false, document, "service-workers", SERVICE_WORKER);
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
var {utils: Cu, classes: Cc, interfaces: Ci} = Components;
|
||||
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const {AddonManager} = Cu.import("resource://gre/modules/AddonManager.jsm", {});
|
||||
const Services = require("Services");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
DevToolsUtils.testing = true;
|
||||
@ -27,7 +28,6 @@ function openAboutDebugging(page) {
|
||||
return {
|
||||
tab,
|
||||
document: browser.contentDocument,
|
||||
window: browser.contentWindow
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -80,3 +80,61 @@ function get_supports_file(path) {
|
||||
let fileurl = cr.convertChromeURL(Services.io.newURI(CHROME_ROOT + path, null, null));
|
||||
return fileurl.QueryInterface(Ci.nsIFileURL);
|
||||
}
|
||||
|
||||
function installAddon(document, path, evt) {
|
||||
// Mock the file picker to select a test addon
|
||||
let MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.init(null);
|
||||
let file = get_supports_file(path);
|
||||
MockFilePicker.returnFiles = [file.file];
|
||||
|
||||
// Wait for a message sent by the addon's bootstrap.js file
|
||||
let onAddonInstalled = new Promise(done => {
|
||||
Services.obs.addObserver(function listener() {
|
||||
Services.obs.removeObserver(listener, evt, false);
|
||||
ok(true, "Addon installed and running its bootstrap.js file");
|
||||
done();
|
||||
}, evt, false);
|
||||
});
|
||||
// Trigger the file picker by clicking on the button
|
||||
document.getElementById("load-addon-from-file").click();
|
||||
|
||||
// Wait for the addon execution
|
||||
return onAddonInstalled;
|
||||
}
|
||||
|
||||
function uninstallAddon(addonId) {
|
||||
// Now uninstall this addon
|
||||
return new Promise(done => {
|
||||
AddonManager.getAddonByID(addonId, addon => {
|
||||
let listener = {
|
||||
onUninstalled: function(uninstalledAddon) {
|
||||
if (uninstalledAddon != addon) {
|
||||
return;
|
||||
}
|
||||
AddonManager.removeAddonListener(listener);
|
||||
done();
|
||||
}
|
||||
};
|
||||
AddonManager.addAddonListener(listener);
|
||||
addon.uninstall();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise that will resolve after receiving a mutation matching the
|
||||
* provided mutation options on the provided target.
|
||||
* @param {Node} target
|
||||
* @param {Object} mutationOptions
|
||||
* @return {Promise}
|
||||
*/
|
||||
function waitForMutation(target, mutationOptions) {
|
||||
return new Promise(resolve => {
|
||||
let observer = new MutationObserver(() => {
|
||||
observer.disconnect();
|
||||
resolve();
|
||||
});
|
||||
observer.observe(target, mutationOptions);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user