bug 1360756 show internal ID for about:debugging r?jdescottes draft
authorAndy McKay <amckay@mozilla.com>
Fri, 12 May 2017 12:32:54 -0700
changeset 577072 74bfb809e9a334073abc4b3dfbb32daa2d82e2df
parent 576982 1e2fe13035e13b7b4001ade3b48f226957cef5fc
child 577160 847c14e31aea73cbd326c51e471a28906b398429
push id58592
push userbmo:amckay@mozilla.com
push dateFri, 12 May 2017 19:33:41 +0000
reviewersjdescottes
bugs1360756
milestone55.0a1
bug 1360756 show internal ID for about:debugging r?jdescottes MozReview-Commit-ID: 2LwFAzKSVKT
devtools/client/aboutdebugging/aboutdebugging.css
devtools/client/aboutdebugging/components/addons/panel.js
devtools/client/aboutdebugging/components/addons/target.js
devtools/client/aboutdebugging/test/browser_addons_debug_info.js
devtools/client/locales/en-US/aboutdebugging.properties
devtools/server/actors/webextension.js
--- 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,
+            baseURL: addon.baseURL,
           };
         });
 
         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.baseURL) {
+    return [];
+  }
+  // Strip off the protocol and trailing slash.
+  let uuid = /moz-extension:\/\/([^/]*)/.exec(target.baseURL)[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.baseURL, target: "_blank", className: "base-url" },
+          Strings.GetStringFromName("baseURL"),
+        ),
+      )
+    ),
+  ];
+}
+
 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,61 @@
 "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* () {
+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 container = document.querySelector(`[data-addon-id="${addonId}"]`);
   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 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}"]`);
+  let filePath = container.querySelector(".file-path");
+  let expectedFilePath = "/test/addons/test-devtools-webextension-nobg/";
+
+  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");
+
+  let internalUUID = container.querySelector(".internal-uuid span");
+  ok(internalUUID.textContent.match(UUID_REGEX), "internalUUID is correct");
+
+  let baseURL = container.querySelector(".base-url");
+  ok(baseURL.href.startsWith("moz-extension://"), "href for baseURL 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,25 @@ 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.
+internalUUID = Internal UUID
+
+# LOCALIZATION NOTE (baseURL):
+# This string is displayed as a label for the base URL of an extension.
+baseURL = Base 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.js
+++ b/devtools/server/actors/webextension.js
@@ -11,16 +11,17 @@ const makeDebugger = require("./utils/ma
 
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 var { assert } = DevToolsUtils;
 
 loader.lazyRequireGetter(this, "mapURIToAddonID", "devtools/server/actors/utils/map-uri-to-addon-id");
 loader.lazyRequireGetter(this, "unwrapDebuggerObjectGlobal", "devtools/server/actors/script", true);
 
 loader.lazyImporter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
+loader.lazyImporter(this, "ExtensionManagement", "resource://gre/modules/ExtensionManagement.jsm");
 loader.lazyImporter(this, "XPIProvider", "resource://gre/modules/addons/XPIProvider.jsm");
 
 const FALLBACK_DOC_MESSAGE = "Your addon does not have any document opened yet.";
 
 /**
  * Creates a TabActor for debugging all the contexts associated to a target WebExtensions
  * add-on.
  * Most of the implementation is inherited from ChromeActor (which inherits most of its
@@ -96,16 +97,17 @@ WebExtensionActor.prototype.form = funct
     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: this.addon.isWebExtension,
+    baseURL: ExtensionManagement.getURLForExtension(this.id),
   });
 };
 
 WebExtensionActor.prototype._attach = function () {
   // NOTE: we need to be sure that `this.window` can return a
   // window before calling the ChromeActor.onAttach, or the TabActor
   // will not be subscribed to the child doc shell updates.