Bug 1273184 - Don't allow reloading of unsupported add-ons. r=ochameau
MozReview-Commit-ID: ERSpt8X9MD8
--- a/devtools/client/aboutdebugging/components/addons/panel.js
+++ b/devtools/client/aboutdebugging/components/addons/panel.js
@@ -62,17 +62,18 @@ module.exports = createClass({
updateAddonsList() {
this.props.client.listAddons()
.then(({addons}) => {
let extensions = addons.filter(addon => addon.debuggable).map(addon => {
return {
name: addon.name,
icon: addon.iconURL || ExtensionIcon,
addonID: addon.id,
- addonActor: addon.actor
+ addonActor: addon.actor,
+ temporarilyInstalled: addon.temporarilyInstalled
};
});
this.setState({ extensions });
}, error => {
throw new Error("Client error while listing addons: " + error);
});
},
--- a/devtools/client/aboutdebugging/components/addons/target.js
+++ b/devtools/client/aboutdebugging/components/addons/target.js
@@ -35,16 +35,18 @@ module.exports = createClass({
}).then(() => {}, error => {
throw new Error(
"Error reloading addon " + target.addonID + ": " + error);
});
},
render() {
let { target, debugDisabled } = this.props;
+ // Only temporarily installed add-ons can be reloaded.
+ const canBeReloaded = target.temporarilyInstalled;
return dom.li({ className: "target-container" },
dom.img({
className: "target-icon",
role: "presentation",
src: target.icon
}),
dom.div({ className: "target" },
@@ -52,13 +54,16 @@ module.exports = createClass({
),
dom.button({
className: "debug-button",
onClick: this.debug,
disabled: debugDisabled,
}, Strings.GetStringFromName("debug")),
dom.button({
className: "reload-button",
- onClick: this.reload
+ onClick: this.reload,
+ disabled: !canBeReloaded,
+ title: !canBeReloaded ?
+ Strings.GetStringFromName("reloadDisabledTooltip") : ""
}, Strings.GetStringFromName("reload"))
);
}
});
new file mode 100644
index 0000000000000000000000000000000000000000..946422b6f188b1c597d7d59236b076c3949706ac
GIT binary patch
literal 280
zc$^FHW@Zs#U|`^2m{GC8!!T$2#0(&B8W8g`$S~w4=4Ga(7MJK{73b%LhHx@4-&eN^
z{|CgS72FJrEMFNJ7{J<BKMM*7IOTihw2!y0UZ=jduGYCT=Yux|8C+uYe4_en8Iz@#
z=hBy4ZEnwwwTY>DC2+PlsXE&-cSIyPI{Kv*C2<Dqk<bX_6=CjLwp=a!`Qe=ojb}tw
zbOtcXdNr7dYd0><-s!Mo8aG3LHzSiAGcE^9Fn|EiO$<vKK`b=qvqGGY=JWt>RyK$>
MMuuP@y&h}`09TPrj{pDw
--- a/devtools/client/aboutdebugging/test/browser.ini
+++ b/devtools/client/aboutdebugging/test/browser.ini
@@ -1,16 +1,17 @@
[DEFAULT]
tags = devtools
subsuite = devtools
support-files =
head.js
addons/unpacked/bootstrap.js
addons/unpacked/install.rdf
addons/bad/manifest.json
+ addons/bug1273184.xpi
service-workers/empty-sw.html
service-workers/empty-sw.js
service-workers/push-sw.html
service-workers/push-sw.js
[browser_addons_debug_bootstrapped.js]
[browser_addons_debugging_initial_state.js]
[browser_addons_install.js]
--- a/devtools/client/aboutdebugging/test/browser_addons_reload.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_reload.js
@@ -17,26 +17,58 @@ function promiseAddonEvent(event) {
resolve(args);
}
};
AddonManager.addAddonListener(listener);
});
}
+function* tearDownAddon(addon) {
+ const onUninstalled = promiseAddonEvent("onUninstalled");
+ addon.uninstall();
+ const [uninstalledAddon] = yield onUninstalled;
+ is(uninstalledAddon.id, addon.id,
+ `Add-on was uninstalled: ${uninstalledAddon.id}`);
+}
+
function getReloadButton(document, addonName) {
const names = [...document.querySelectorAll("#addons .target-name")];
const name = names.filter(element => element.textContent === addonName)[0];
ok(name, `Found ${addonName} add-on in the list`);
const targetElement = name.parentNode.parentNode;
const reloadButton = targetElement.querySelector(".reload-button");
info(`Found reload button for ${addonName}`);
return reloadButton;
}
+function installAddonWithManager(filePath) {
+ return new Promise((resolve, reject) => {
+ AddonManager.getInstallForFile(filePath, install => {
+ if (!install) {
+ throw new Error(`An install was not created for ${filePath}`);
+ }
+ install.addListener({
+ onDownloadFailed: reject,
+ onDownloadCancelled: reject,
+ onInstallFailed: reject,
+ onInstallCancelled: reject,
+ onInstallEnded: resolve
+ });
+ install.install();
+ });
+ });
+}
+
+function getAddonByID(addonId) {
+ return new Promise(resolve => {
+ AddonManager.getAddonByID(addonId, addon => resolve(addon));
+ });
+}
+
/**
* Creates a web extension from scratch in a temporary location.
* The object must be removed when you're finished working with it.
*/
class TempWebExt {
constructor(addonId) {
this.addonId = addonId;
this.tmpDir = FileUtils.getDir("TmpD", ["browser_addons_reload"]);
@@ -76,16 +108,18 @@ class TempWebExt {
add_task(function* reloadButtonReloadsAddon() {
const { tab, document } = yield openAboutDebugging("addons");
yield waitForInitialAddonList(document);
yield installAddon(document, "addons/unpacked/install.rdf",
ADDON_NAME, ADDON_NAME);
const reloadButton = getReloadButton(document, ADDON_NAME);
+ is(reloadButton.disabled, false, "Reload button should not be disabled");
+ is(reloadButton.title, "", "Reload button should not have a tooltip");
const onInstalled = promiseAddonEvent("onInstalled");
const onBootstrapInstallCalled = new Promise(done => {
Services.obs.addObserver(function listener() {
Services.obs.removeObserver(listener, ADDON_NAME, false);
info("Add-on was re-installed: " + ADDON_NAME);
done();
}, ADDON_NAME, false);
@@ -93,24 +127,17 @@ add_task(function* reloadButtonReloadsAd
reloadButton.click();
const [reloadedAddon] = yield onInstalled;
is(reloadedAddon.name, ADDON_NAME,
"Add-on was reloaded: " + reloadedAddon.name);
yield onBootstrapInstallCalled;
-
- info("Uninstall addon installed earlier.");
- const onUninstalled = promiseAddonEvent("onUninstalled");
- reloadedAddon.uninstall();
- const [uninstalledAddon] = yield onUninstalled;
- is(uninstalledAddon.id, ADDON_ID,
- "Add-on was uninstalled: " + uninstalledAddon.id);
-
+ yield tearDownAddon(reloadedAddon);
yield closeAboutDebugging(tab);
});
add_task(function* reloadButtonRefreshesMetadata() {
const { tab, document } = yield openAboutDebugging("addons");
yield waitForInitialAddonList(document);
const manifestBase = {
@@ -148,15 +175,30 @@ add_task(function* reloadButtonRefreshes
yield onAddonReloaded;
const [reloadedAddon] = yield onReInstall;
// Make sure the name was updated correctly.
const allAddons = [...document.querySelectorAll("#addons .target-name")]
.map(element => element.textContent);
const nameWasUpdated = allAddons.some(name => name === newName);
ok(nameWasUpdated, `New name appeared in reloaded add-ons: ${allAddons}`);
- const onUninstalled = promiseAddonEvent("onUninstalled");
- reloadedAddon.uninstall();
- yield onUninstalled;
-
+ yield tearDownAddon(reloadedAddon);
tempExt.remove();
yield closeAboutDebugging(tab);
});
+
+add_task(function* onlyTempInstalledAddonsCanBeReloaded() {
+ const { tab, document } = yield openAboutDebugging("addons");
+ yield waitForInitialAddonList(document);
+ const onAddonListUpdated = waitForMutation(getAddonList(document),
+ { childList: true });
+ yield installAddonWithManager(getSupportsFile("addons/bug1273184.xpi").file);
+ yield onAddonListUpdated;
+ const addon = yield getAddonByID("bug1273184@tests");
+
+ const reloadButton = getReloadButton(document, addon.name);
+ ok(reloadButton, "Reload button exists");
+ is(reloadButton.disabled, true, "Reload button should be disabled");
+ ok(reloadButton.title, "Disabled reload button should have a tooltip");
+
+ yield tearDownAddon(addon);
+ yield closeAboutDebugging(tab);
+});
--- a/devtools/client/locales/en-US/aboutdebugging.properties
+++ b/devtools/client/locales/en-US/aboutdebugging.properties
@@ -12,16 +12,17 @@ unregister = unregister
addons = Add-ons
addonDebugging.label = Enable add-on debugging
addonDebugging.tooltip = Turning this on will allow you to debug add-ons and various other parts of the browser chrome
addonDebugging.moreInfo = more info
loadTemporaryAddon = Load Temporary Add-on
extensions = Extensions
selectAddonFromFile2 = Select Manifest File or Package (.xpi)
reload = Reload
+reloadDisabledTooltip = Only temporarily installed add-ons can be reloaded
workers = Workers
serviceWorkers = Service Workers
sharedWorkers = Shared Workers
otherWorkers = Other Workers
tabs = Tabs
--- a/devtools/server/actors/addon.js
+++ b/devtools/server/actors/addon.js
@@ -80,16 +80,17 @@ BrowserAddonActor.prototype = {
return {
actor: this.actorID,
id: this.id,
name: this._addon.name,
url: this.url,
iconURL: this._addon.iconURL,
debuggable: this._addon.isDebuggable,
+ temporarilyInstalled: this._addon.temporarilyInstalled,
consoleActor: this._consoleActor.actorID,
traits: {
highlightable: false,
networkMonitor: false,
},
};
},