Bug 1425224 - Use manifest.ExtensionURL in devtools.panels.create API schema. r=mixedpuppy a=gchang
authorLuca Greco <lgreco@mozilla.com>
Thu, 14 Dec 2017 18:20:59 +0100
changeset 445568 aca965dcf4386ed4bf92f5ac7da70f9d8fa84907
parent 445567 612d5931c32866800f22287574fa2a1b5fb9d1bc
child 445569 d5b2854b166bd6ef57ea3b4a46dd4bb70ba6e2ab
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmixedpuppy, gchang
bugs1425224
milestone58.0
Bug 1425224 - Use manifest.ExtensionURL in devtools.panels.create API schema. r=mixedpuppy a=gchang MozReview-Commit-ID: AR6j1fC0PmJ
browser/components/extensions/schemas/devtools_panels.json
browser/components/extensions/test/browser/browser_ext_devtools_panel.js
--- a/browser/components/extensions/schemas/devtools_panels.json
+++ b/browser/components/extensions/schemas/devtools_panels.json
@@ -329,22 +329,25 @@
         "parameters": [
           {
             "name": "title",
             "type": "string",
             "description": "Title that is displayed next to the extension icon in the Developer Tools toolbar."
           },
           {
             "name": "iconPath",
-            "type": "string",
-            "description": "Path of the panel's icon relative to the extension directory."
+            "description": "Path of the panel's icon relative to the extension directory, or an empty string to use the default extension icon as the panel icon.",
+            "choices": [
+              {"type": "string", "enum": [""]},
+              {"$ref": "manifest.ExtensionURL"}
+            ]
           },
           {
             "name": "pagePath",
-            "type": "string",
+            "$ref": "manifest.ExtensionURL",
             "description": "Path of the panel's HTML page relative to the extension directory."
           },
           {
             "name": "callback",
             "type": "function",
             "optional": true,
             "description": "A function that is called when the panel is created.",
             "parameters": [
--- a/browser/components/extensions/test/browser/browser_ext_devtools_panel.js
+++ b/browser/components/extensions/test/browser/browser_ext_devtools_panel.js
@@ -425,8 +425,140 @@ add_task(async function test_devtools_pa
 
   await gDevTools.closeToolbox(target);
   await target.destroy();
 
   await extension.unload();
 
   await BrowserTestUtils.removeTab(tab);
 });
+
+add_task(async function test_devtools_page_invalid_panel_urls() {
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
+
+  async function devtools_page() {
+    const matchInvalidPanelURL = /must be a relative URL/;
+    const matchInvalidIconURL = /be one of \[""\], or match the format "strictRelativeUrl"/;
+
+    const test_cases = [
+      // Invalid panel urls (validated by the schema wrappers, throws on invalid urls).
+      {panel: "about:about", icon: "icon.png", expectError: matchInvalidPanelURL},
+      {panel: "about:addons", icon: "icon.png", expectError: matchInvalidPanelURL},
+      {panel: "http://mochi.test:8888", icon: "icon.png", expectError: matchInvalidPanelURL},
+      // Invalid icon urls (validated inside the API method because of the empty icon string
+      // which have to be resolved to the default icon, reject the returned promise).
+      {panel: "panel.html", icon: "about:about", expectError: matchInvalidIconURL},
+      {panel: "panel.html", icon: "http://mochi.test:8888", expectError: matchInvalidIconURL},
+      // Valid panel urls
+      {panel: "panel.html", icon: "icon.png"},
+      {panel: "./panel.html", icon: "icon.png"},
+      {panel: "/panel.html", icon: "icon.png"},
+      {panel: "/panel.html", icon: ""},
+    ];
+
+    browser.test.onMessage.addListener(async msg => {
+      if (msg !== "start_test_panel_create") {
+        return;
+      }
+
+      for (let {panel, icon, expectError} of test_cases) {
+        browser.test.log(`Testing devtools.panels.create for ${JSON.stringify({panel, icon})}`);
+
+        if (expectError) {
+          // Verify that invalid panel urls throw.
+          browser.test.assertThrows(
+            () => browser.devtools.panels.create("Test Panel", icon, panel),
+            expectError,
+            "Got the expected rejection on creating a devtools panel with " +
+            `panel url ${panel} and icon ${icon}`
+          );
+        } else {
+          // Verify that with valid panel and icon urls the panel is created and loaded
+          // as expected.
+          try {
+            const pane = await browser.devtools.panels.create("Test Panel", icon, panel);
+
+            // Wait the panel to be loaded.
+            const oncePanelLoaded = new Promise(resolve => {
+              pane.onShown.addListener(paneWin => {
+                browser.test.assertTrue(
+                  paneWin.location.href.endsWith("/panel.html"),
+                  `The panel has loaded the expected extension URL with ${panel}`);
+                resolve();
+              });
+            });
+
+            // Ask the privileged code to select the last created panel.
+            browser.test.sendMessage("select-devtools-panel");
+            await oncePanelLoaded;
+          } catch (err) {
+            browser.test.fail("Unexpected failure on creating a devtools panel with " +
+                              `panel url ${panel} and icon ${icon}`);
+          }
+        }
+      }
+
+      browser.test.sendMessage("test_invalid_devtools_panel_urls_done");
+    });
+
+    browser.test.sendMessage("devtools_page_ready");
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      devtools_page: "devtools_page.html",
+      icons: {
+        "32": "icon.png",
+      },
+    },
+    files: {
+      "devtools_page.html": `<!DOCTYPE html>
+        <html>
+         <head>
+           <meta charset="utf-8">
+         </head>
+         <body>
+           <script src="devtools_page.js"></script>
+         </body>
+        </html>`,
+      "devtools_page.js": devtools_page,
+      "panel.html":  `<!DOCTYPE html>
+        <html>
+         <head>
+           <meta charset="utf-8">
+         </head>
+         <body>
+           DEVTOOLS PANEL
+         </body>
+        </html>`,
+      "icon.png": imageBuffer,
+      "default-icon.png": imageBuffer,
+    },
+  });
+
+  await extension.startup();
+
+  let target = gDevTools.getTargetForTab(tab);
+
+  let toolbox = await gDevTools.showToolbox(target, "webconsole");
+
+  extension.onMessage("select-devtools-panel", () => {
+    const toolboxAdditionalTools = toolbox.getAdditionalTools();
+    const lastTool = toolboxAdditionalTools[toolboxAdditionalTools.length - 1];
+
+    gDevTools.showToolbox(target, lastTool.id);
+  });
+
+  info("developer toolbox opened");
+
+  await extension.awaitMessage("devtools_page_ready");
+
+  extension.sendMessage("start_test_panel_create");
+
+  await extension.awaitMessage("test_invalid_devtools_panel_urls_done");
+
+  await gDevTools.closeToolbox(target);
+  await target.destroy();
+
+  await extension.unload();
+
+  await BrowserTestUtils.removeTab(tab);
+});