Bug 1461115 - Emit menus.onShown even if there is no tab draft
authorRob Wu <rob@robwu.nl>
Fri, 18 May 2018 13:55:09 +0200
changeset 796871 9fbbe8283df7776b600f8d08d8d7db3a6790c083
parent 796870 11ee70f24ea52c4dc4f113593c288f4a6dc92c55
push id110368
push userbmo:rob@robwu.nl
push dateFri, 18 May 2018 11:57:15 +0000
bugs1461115
milestone62.0a1
Bug 1461115 - Emit menus.onShown even if there is no tab MozReview-Commit-ID: 6Bc7HHvaCRW
browser/components/extensions/parent/ext-menus.js
browser/components/extensions/test/browser/browser_ext_menus_events.js
--- a/browser/components/extensions/parent/ext-menus.js
+++ b/browser/components/extensions/parent/ext-menus.js
@@ -818,26 +818,28 @@ this.menusInternal = class extends Exten
         name: "menus.onShown",
         register: fire => {
           let listener = (event, menuIds, contextData) => {
             let info = {
               menuIds,
               contexts: Array.from(getMenuContexts(contextData)),
             };
 
+            let nativeTab = contextData.tab;
+
             // The menus.onShown event is fired before the user has consciously
             // interacted with an extension, so we require permissions before
             // exposing sensitive contextual data.
             let includeSensitiveData =
-            extension.tabManager.hasActiveTabPermission(contextData.tab) ||
-            extension.whiteListedHosts.matches(contextData.inFrame ? contextData.frameUrl : contextData.pageUrl);
+              (nativeTab && extension.tabManager.hasActiveTabPermission(nativeTab)) ||
+              extension.whiteListedHosts.matches(contextData.inFrame ? contextData.frameUrl : contextData.pageUrl);
 
             addMenuEventInfo(info, contextData, includeSensitiveData);
 
-            let tab = extension.tabManager.convert(contextData.tab);
+            let tab = nativeTab && extension.tabManager.convert(nativeTab);
             fire.sync(info, tab);
           };
           gOnShownSubscribers.add(extension);
           extension.on("webext-menu-shown", listener);
           return () => {
             gOnShownSubscribers.delete(extension);
             extension.off("webext-menu-shown", listener);
           };
--- a/browser/components/extensions/test/browser/browser_ext_menus_events.js
+++ b/browser/components/extensions/test/browser/browser_ext_menus_events.js
@@ -42,17 +42,21 @@ async function testShowHideEvent({menuCr
     let menuCreateParams = await awaitMessage("create-params");
     const [tab] = await browser.tabs.query({active: true, currentWindow: true});
 
     let shownEvents = [];
     let hiddenEvents = [];
 
     browser.menus.onShown.addListener((...args) => {
       shownEvents.push(args[0]);
-      browser.test.assertEq(tab.id, args[1].id, "expected tab");
+      if (menuCreateParams.title.includes("TEST_EXPECT_NO_TAB")) {
+        browser.test.assertEq(undefined, args[1], "expect no tab");
+      } else {
+        browser.test.assertEq(tab.id, args[1].id, "expected tab");
+      }
       browser.test.assertEq(2, args.length, "expected number of onShown args");
     });
     browser.menus.onHidden.addListener(event => hiddenEvents.push(event));
 
     await browser.pageAction.show(tab.id);
 
     let menuId;
     await new Promise(resolve => {
@@ -78,50 +82,55 @@ async function testShowHideEvent({menuCr
   }
 
   const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
 
   let extension = ExtensionTestUtils.loadExtension({
     background,
     manifest: {
       page_action: {},
-      browser_action: {},
+      browser_action: {
+        default_popup: "popup.html",
+      },
       permissions: ["menus"],
       optional_permissions: [PAGE_HOST_PATTERN],
     },
+    files: {
+      "popup.html": `<!DOCTYPE html><meta charset="utf-8">Popup body`,
+    },
   });
   await extension.startup();
   extension.sendMessage("create-params", menuCreateParams);
   let menuId = await extension.awaitMessage("menu-registered");
 
   await doOpenMenu(extension);
   extension.sendMessage("assert-menu-shown");
   let shownEvent = await extension.awaitMessage("onShown-event-data");
 
   // menuCreateParams.id is not set, therefore a numeric ID is generated.
   expectedShownEvent.menuIds = [menuId];
   Assert.deepEqual(shownEvent, expectedShownEvent, "expected onShown info");
 
-  await doCloseMenu();
+  await doCloseMenu(extension);
   extension.sendMessage("assert-menu-hidden");
   let hiddenEvent = await extension.awaitMessage("onHidden-event-data");
   is(hiddenEvent, undefined, "expected no event data for onHidden event");
 
   if (expectedShownEventWithPermissions) {
     expectedShownEventWithPermissions.menuIds = [menuId];
     await grantOptionalPermission(extension, {
       permissions: [],
       origins: [PAGE_HOST_PATTERN],
     });
     await doOpenMenu(extension);
     extension.sendMessage("optional-menu-shown-with-permissions");
     let shownEvent2 = await extension.awaitMessage("onShown-event-data2");
     Assert.deepEqual(shownEvent2, expectedShownEventWithPermissions,
                      "expected onShown info when host permissions are enabled");
-    await doCloseMenu();
+    await doCloseMenu(extension);
   }
 
   await extension.unload();
   BrowserTestUtils.removeTab(tab);
 }
 
 // Make sure that we won't trigger onShown when extensions cannot add menus.
 add_task(async function test_no_show_hide_for_unsupported_menu() {
@@ -253,16 +262,47 @@ add_task(async function test_show_hide_b
       await openActionContextMenu(extension, "browser");
     },
     async doCloseMenu() {
       await closeActionContextMenu();
     },
   });
 });
 
+add_task(async function test_show_hide_browserAction_popup() {
+  let popupUrl;
+  await testShowHideEvent({
+    menuCreateParams: {
+      title: "browserAction popup - TEST_EXPECT_NO_TAB",
+      contexts: ["all", "browser_action"],
+    },
+    expectedShownEvent: {
+      contexts: ["page", "all"],
+      frameId: 0,
+      editable: false,
+      get pageUrl() { return popupUrl; },
+    },
+    expectedShownEventWithPermissions: {
+      contexts: ["page", "all"],
+      frameId: 0,
+      editable: false,
+      get pageUrl() { return popupUrl; },
+    },
+    async doOpenMenu(extension) {
+      popupUrl = `moz-extension://${extension.uuid}/popup.html`;
+      await clickBrowserAction(extension);
+      await openContextMenuInPopup(extension);
+    },
+    async doCloseMenu(extension) {
+      await closeExtensionContextMenu();
+      await closeBrowserAction(extension);
+    },
+  });
+});
+
 add_task(async function test_show_hide_tab() {
   await testShowHideEvent({
     menuCreateParams: {
       title: "tab menu item",
       contexts: ["tab"],
     },
     expectedShownEvent: {
       contexts: ["tab"],