Bug 1330741 - Show filesystem location of add-ons in about:debugging r?jdescottes
MozReview-Commit-ID: 3pmdAi80boT
--- a/devtools/client/aboutdebugging/aboutdebugging.css
+++ b/devtools/client/aboutdebugging/aboutdebugging.css
@@ -244,16 +244,35 @@ button {
}
.addon-target-container .name {
align-self: center;
font-size: 16px;
font-weight: 600;
}
+.addon-target-info {
+ display: grid;
+ font-size: 14px;
+ grid-template-columns: 128px 1fr;
+}
+
+.addon-target-info-label {
+ padding-inline-end: 8px;
+ padding-bottom: 8px;
+}
+
+.addon-target-info-label:last-of-type {
+ padding-bottom: 16px;
+}
+
+.addon-target-info-content {
+ margin: 0;
+}
+
.addon-target-button {
background: none;
border: none;
color: #0087ff;
font-size: 14px;
margin: 12px;
min-width: auto;
padding: 4px;
@@ -284,8 +303,23 @@ button {
text-decoration: none;
}
.addon-target-button:first-of-type {
/* Subtract the start padding so the button is still a bigger click target but
* lines up with the icon. */
margin-inline-start: -4px;
}
+
+/* We want the ellipsis on the left-hand-side, so make the parent RTL
+ * with an ellipsis and the child can be LTR. */
+.file-path {
+ direction: rtl;
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.file-path-inner {
+ direction: ltr;
+ unicode-bidi: plaintext;
+}
--- a/devtools/client/aboutdebugging/components/addons/panel.js
+++ b/devtools/client/aboutdebugging/components/addons/panel.js
@@ -71,17 +71,18 @@ module.exports = createClass({
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,
- temporarilyInstalled: addon.temporarilyInstalled
+ temporarilyInstalled: addon.temporarilyInstalled,
+ url: addon.url,
};
});
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
@@ -15,28 +15,48 @@ loader.lazyImporter(this, "BrowserToolbo
"resource://devtools/client/framework/ToolboxProcess.jsm");
loader.lazyRequireGetter(this, "DebuggerClient",
"devtools/shared/client/main", true);
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
+function filePathForTarget(target) {
+ // Only show file system paths, and only for temporarily installed add-ons.
+ if (!target.temporarilyInstalled || !target.url || !target.url.startsWith("file://")) {
+ return [];
+ }
+ let path = target.url.slice("file://".length);
+ return [
+ dom.dt(
+ { className: "addon-target-info-label" },
+ Strings.GetStringFromName("location")),
+ // Wrap the file path in a span so we can do some RTL/LTR swapping to get
+ // the ellipsis on the left.
+ dom.dd(
+ { className: "addon-target-info-content file-path" },
+ dom.span({ className: "file-path-inner", title: path }, path),
+ ),
+ ];
+}
+
module.exports = createClass({
displayName: "AddonTarget",
propTypes: {
client: PropTypes.instanceOf(DebuggerClient).isRequired,
debugDisabled: PropTypes.bool,
target: PropTypes.shape({
addonActor: PropTypes.string.isRequired,
addonID: PropTypes.string.isRequired,
icon: PropTypes.string,
name: PropTypes.string.isRequired,
- temporarilyInstalled: PropTypes.bool
+ temporarilyInstalled: PropTypes.bool,
+ url: PropTypes.string,
}).isRequired
},
debug() {
let { target } = this.props;
debugAddon(target.addonID);
},
@@ -63,16 +83,20 @@ module.exports = createClass({
dom.div({ className: "target" },
dom.img({
className: "target-icon",
role: "presentation",
src: target.icon
}),
dom.span({ className: "target-name", title: target.name }, target.name)
),
+ dom.dl(
+ { className: "addon-target-info" },
+ ...filePathForTarget(target),
+ ),
dom.div({className: "addon-target-actions"},
dom.button({
className: "debug-button addon-target-button",
onClick: this.debug,
disabled: debugDisabled,
}, Strings.GetStringFromName("debug")),
dom.button({
className: "reload-button addon-target-button",
--- a/devtools/client/aboutdebugging/test/browser.ini
+++ b/devtools/client/aboutdebugging/test/browser.ini
@@ -15,16 +15,17 @@ support-files =
service-workers/empty-sw.js
service-workers/fetch-sw.html
service-workers/fetch-sw.js
service-workers/push-sw.html
service-workers/push-sw.js
!/devtools/client/framework/test/shared-head.js
[browser_addons_debug_bootstrapped.js]
+[browser_addons_debug_info.js]
[browser_addons_debug_webextension.js]
tags = webextensions
[browser_addons_debug_webextension_inspector.js]
tags = webextensions
[browser_addons_debug_webextension_nobg.js]
tags = webextensions
[browser_addons_debug_webextension_popup.js]
tags = webextensions
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging/test/browser_addons_debug_info.js
@@ -0,0 +1,28 @@
+"use strict";
+
+const ADDON_ID = "test-devtools@mozilla.org";
+const ADDON_NAME = "test-devtools";
+
+add_task(function* () {
+ let { tab, document } = yield openAboutDebugging("addons");
+ yield waitForInitialAddonList(document);
+
+ yield installAddon({
+ document,
+ path: "addons/unpacked/install.rdf",
+ name: ADDON_NAME,
+ });
+
+ let container = document.querySelector(`[data-addon-id="${ADDON_ID}"]`);
+ let filePath = container.querySelector(".file-path");
+ let expectedFilePath = "browser/devtools/client/aboutdebugging/test/addons/unpacked/";
+
+ // Verify that the path to the install location is shown next to its label.
+ ok(filePath, "file path is in DOM");
+ ok(filePath.textContent.endsWith(expectedFilePath), "file path is set correctly");
+ is(filePath.previousElementSibling.textContent, "Location", "file path has label");
+
+ yield uninstallAddon({document, id: ADDON_ID, name: ADDON_NAME});
+
+ yield closeAboutDebugging(tab);
+});
--- a/devtools/client/locales/en-US/aboutdebugging.properties
+++ b/devtools/client/locales/en-US/aboutdebugging.properties
@@ -74,16 +74,20 @@ selectAddonFromFile2 = Select Manifest F
# This string is displayed as a label of the button that reloads a given addon.
reload = Reload
# LOCALIZATION NOTE (reloadDisabledTooltip):
# This string is displayed in a tooltip that appears when hovering over a
# disabled 'reload' button.
reloadDisabledTooltip = Only temporarily installed add-ons can be reloaded
+# LOCALIZATION NOTE (location):
+# This string is displayed as a label for the filesystem location of an extension.
+location = Location
+
# LOCALIZATION NOTE (workers):
# This string is displayed as a header of the about:debugging#workers page.
workers = Workers
serviceWorkers = Service Workers
sharedWorkers = Shared Workers
otherWorkers = Other Workers