bug 1360756 show internal ID for about:debugging r?jdescottes
MozReview-Commit-ID: 2LwFAzKSVKT
--- a/devtools/client/aboutdebugging/aboutdebugging.css
+++ b/devtools/client/aboutdebugging/aboutdebugging.css
@@ -274,16 +274,20 @@ button {
.addon-target-info-label:last-of-type {
padding-bottom: 16px;
}
.addon-target-info-content {
margin: 0;
}
+.addon-target-info-more {
+ padding-left: 1ch;
+}
+
.addon-target-button {
background: none;
border: none;
color: #0087ff;
font-size: 14px;
margin: 12px;
min-width: auto;
padding: 4px;
--- a/devtools/client/aboutdebugging/components/addons/panel.js
+++ b/devtools/client/aboutdebugging/components/addons/panel.js
@@ -75,16 +75,17 @@ module.exports = createClass({
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,
url: addon.url,
+ manifestURL: addon.manifestURL,
};
});
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
@@ -34,16 +34,44 @@ function filePathForTarget(target) {
// the ellipsis on the left.
dom.dd(
{ className: "addon-target-info-content file-path" },
dom.span({ className: "file-path-inner", title: path }, path),
),
];
}
+function internalIDForTarget(target) {
+ if (!target.manifestURL) {
+ return [];
+ }
+ // Strip off the protocol and rest, leaving us with just the UUID.
+ let uuid = /moz-extension:\/\/([^/]*)/.exec(target.manifestURL)[1];
+ return [
+ dom.dt(
+ { className: "addon-target-info-label" },
+ Strings.GetStringFromName("internalUUID"),
+ ),
+ dom.dd(
+ { className: "addon-target-info-content internal-uuid" },
+ dom.span(
+ { title: uuid },
+ uuid
+ ),
+ dom.span(
+ { className: "addon-target-info-more" },
+ dom.a(
+ { href: target.manifestURL, target: "_blank", className: "manifest-url" },
+ Strings.GetStringFromName("manifestURL"),
+ ),
+ )
+ ),
+ ];
+}
+
module.exports = createClass({
displayName: "AddonTarget",
propTypes: {
client: PropTypes.instanceOf(DebuggerClient).isRequired,
debugDisabled: PropTypes.bool,
target: PropTypes.shape({
addonActor: PropTypes.string.isRequired,
@@ -86,16 +114,17 @@ module.exports = createClass({
role: "presentation",
src: target.icon
}),
dom.span({ className: "target-name", title: target.name }, target.name)
),
dom.dl(
{ className: "addon-target-info" },
...filePathForTarget(target),
+ ...internalIDForTarget(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({
--- a/devtools/client/aboutdebugging/test/browser_addons_debug_info.js
+++ b/devtools/client/aboutdebugging/test/browser_addons_debug_info.js
@@ -1,28 +1,58 @@
"use strict";
-const ADDON_ID = "test-devtools@mozilla.org";
-const ADDON_NAME = "test-devtools";
+const UUID_REGEX = /^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
-add_task(function* () {
+function testFilePath(container, expectedFilePath) {
+ // Verify that the path to the install location is shown next to its label.
+ let filePath = container.querySelector(".file-path");
+ 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");
+}
+
+add_task(function* testLegacyAddon() {
+ let addonId = "test-devtools@mozilla.org";
+ let addonName = "test-devtools";
let { tab, document } = yield openAboutDebugging("addons");
yield waitForInitialAddonList(document);
yield installAddon({
document,
path: "addons/unpacked/install.rdf",
- name: ADDON_NAME,
+ name: addonName,
});
- let container = document.querySelector(`[data-addon-id="${ADDON_ID}"]`);
- let filePath = container.querySelector(".file-path");
- let expectedFilePath = "browser/devtools/client/aboutdebugging/test/addons/unpacked/";
+ let container = document.querySelector(`[data-addon-id="${addonId}"]`);
+ testFilePath(container, "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 uninstallAddon({document, id: addonId, name: addonName});
yield closeAboutDebugging(tab);
});
+
+add_task(function* testWebExtension() {
+ let addonId = "test-devtools-webextension-nobg@mozilla.org";
+ let addonName = "test-devtools-webextension-nobg";
+ let { tab, document } = yield openAboutDebugging("addons");
+
+ yield waitForInitialAddonList(document);
+ yield installAddon({
+ document,
+ path: "addons/test-devtools-webextension-nobg/manifest.json",
+ name: addonName,
+ isWebExtension: true
+ });
+
+ let container = document.querySelector(`[data-addon-id="${addonId}"]`);
+ testFilePath(container, "/test/addons/test-devtools-webextension-nobg/");
+
+ let internalUUID = container.querySelector(".internal-uuid span");
+ ok(internalUUID.textContent.match(UUID_REGEX), "internalUUID is correct");
+
+ let manifestURL = container.querySelector(".manifest-url");
+ ok(manifestURL.href.startsWith("moz-extension://"), "href for manifestURL exists");
+
+ yield uninstallAddon({document, id: addonId, name: addonName});
+
+ yield closeAboutDebugging(tab);
+});
--- a/devtools/client/locales/en-US/aboutdebugging.properties
+++ b/devtools/client/locales/en-US/aboutdebugging.properties
@@ -61,16 +61,26 @@ loadTemporaryAddon = Load Temporary Add-
# LOCALIZATION NOTE (extensions):
# This string is displayed as a header above the list of loaded add-ons.
extensions = Extensions
# LOCALIZATION NOTE (temporaryExtensions):
# This string is displayed as a header above the list of temporarily loaded add-ons.
temporaryExtensions = Temporary Extensions
+# LOCALIZATION NOTE (internalUUID):
+# This string is displayed as a label for the internal UUID of an extension.
+# The UUID is generated for this profile on install.
+internalUUID = Internal UUID
+
+# LOCALIZATION NOTE (manifestURL):
+# This string is displayed as a link for the manifest of an extension,
+# accessible in a browser, such as moz-extension://[internalUUID]/manifest.json.
+manifestURL = Manifest URL
+
# LOCALIZATION NOTE (webExtTip):
# This string is displayed as a message below the list of temporarily loaded add-ons.
# Web-ext is a command line tool for web-extensions developers.
# See https://developer.mozilla.org/Add-ons/WebExtensions/Getting_started_with_web-ext
webExtTip = You can use web-ext to load temporary WebExtensions from the command line.
# LOCALIZATION NOTE (webExtTip.learnMore):
# This string is displayed as a link next to webExtTip and leads the user to the MDN
--- a/devtools/server/actors/webextension-parent.js
+++ b/devtools/server/actors/webextension-parent.js
@@ -4,16 +4,17 @@
"use strict";
const {DebuggerServer} = require("devtools/server/main");
const protocol = require("devtools/shared/protocol");
const {webExtensionSpec} = require("devtools/shared/specs/webextension-parent");
loader.lazyImporter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
+loader.lazyImporter(this, "ExtensionManagement", "resource://gre/modules/ExtensionManagement.jsm");
loader.lazyImporter(this, "ExtensionParent", "resource://gre/modules/ExtensionParent.jsm");
/**
* Creates the actor that represents the addon in the parent process, which connects
* itself to a WebExtensionChildActor counterpart which is created in the
* extension process (or in the main process if the WebExtensions OOP mode is disabled).
*
* The WebExtensionParentActor subscribes itself as an AddonListener on the AddonManager
@@ -63,20 +64,22 @@ const WebExtensionParentActor = protocol
});
},
form() {
return {
actor: this.actorID,
id: this.id,
name: this.addon.name,
+ url: this.addon.sourceURI ? this.addon.sourceURI.spec : undefined,
iconURL: this.addon.iconURL,
debuggable: this.addon.isDebuggable,
temporarilyInstalled: this.addon.temporarilyInstalled,
isWebExtension: true,
+ manifestURL: ExtensionManagement.getURLForExtension(this.id, "manifest.json"),
};
},
connect() {
if (this._childFormPormise) {
return this._childFormPromise;
}