Bug 1446956 - Grant access to the clicked tab in menus.onClicked draft
authorRob Wu <rob@robwu.nl>
Wed, 18 Jul 2018 22:04:58 +0200
changeset 824646 282bf0e0db3c9deda0e386c449a3e695d7b061e3
parent 824607 0d72c7996d60a7c07e35c5f90d78b02a47d17460
child 824647 2e9002e7938d3901af562f21e33aaca7712a38d6
push id117964
push userbmo:rob@robwu.nl
push dateTue, 31 Jul 2018 14:45:16 +0000
bugs1446956
milestone63.0a1
Bug 1446956 - Grant access to the clicked tab in menus.onClicked MozReview-Commit-ID: 3mVWOEcZFYn
browser/components/extensions/parent/ext-menus.js
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_menus_activeTab.js
--- a/browser/components/extensions/parent/ext-menus.js
+++ b/browser/components/extensions/parent/ext-menus.js
@@ -265,18 +265,18 @@ var gMenuBuilder = {
           if (child.type == "radio" && child.groupName == item.groupName) {
             child.checked = false;
           }
         }
         // Select the clicked radio item.
         item.checked = true;
       }
 
-      if (!contextData.onBookmark) {
-        item.tabManager.addActiveTabPermission();
+      if (contextData.tab) {
+        item.tabManager.addActiveTabPermission(contextData.tab);
       }
 
       let info = item.getClickInfo(contextData, wasChecked);
 
       const map = {shiftKey: "Shift", altKey: "Alt", metaKey: "Command", ctrlKey: "Ctrl"};
       info.modifiers = Object.keys(map).filter(key => event[key]).map(key => map[key]);
       if (event.ctrlKey && AppConstants.platform === "macosx") {
         info.modifiers.push("MacCtrl");
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -98,16 +98,17 @@ support-files =
 skip-if = (verify && (os == 'linux' || os == 'mac'))
 [browser_ext_getViews.js]
 [browser_ext_history_redirect.js]
 [browser_ext_identity_indication.js]
 [browser_ext_incognito_views.js]
 [browser_ext_incognito_popup.js]
 [browser_ext_lastError.js]
 [browser_ext_menus.js]
+[browser_ext_menus_activeTab.js]
 [browser_ext_menus_errors.js]
 [browser_ext_menus_event_order.js]
 [browser_ext_menus_events.js]
 [browser_ext_menus_refresh.js]
 [browser_ext_omnibox.js]
 skip-if = (debug && (os == 'linux' || os == 'mac')) || (verify && (os == 'linux' || os == 'mac')) # Bug 1417052
 [browser_ext_openPanel.js]
 skip-if = (verify && !debug && (os == 'linux' || os == 'mac'))
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_menus_activeTab.js
@@ -0,0 +1,84 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+// Opens two tabs at the start of the tab strip and focuses the second tab.
+// Then an extension menu is registered for the "tab" context and a menu is
+// opened on the first tab and the extension menu item is clicked.
+// This triggers the onTabMenuClicked handler.
+async function openTwoTabsAndOpenTabMenu(onTabMenuClicked) {
+  const PAGE_URL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html";
+  const OTHER_URL = "http://127.0.0.1:8888/browser/browser/components/extensions/test/browser/context.html";
+
+  let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE_URL);
+  let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, OTHER_URL);
+  // Move the first tab to the start so that it can be found by the .tabbrowser-tab selector below.
+  gBrowser.moveTabTo(tab1, 0);
+  gBrowser.moveTabTo(tab2, 1);
+
+  async function background(onTabMenuClicked) {
+    browser.menus.onClicked.addListener(async (info, tab) => {
+      await onTabMenuClicked(info, tab);
+      browser.test.sendMessage("onCommand_on_tab_click");
+    });
+
+    browser.menus.create({
+      title: "menu item on tab",
+      contexts: ["tab"],
+    }, () => {
+      browser.test.sendMessage("ready");
+    });
+  }
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "permissions": ["menus", "activeTab"],
+    },
+    background: `(${background})(${onTabMenuClicked})`,
+  });
+
+  await extension.startup();
+  await extension.awaitMessage("ready");
+
+  // The .tabbrowser-tab selector matches the first tab (tab1).
+  let menu = await openChromeContextMenu("tabContextMenu", ".tabbrowser-tab", window);
+  let menuItem = menu.getElementsByAttribute("label", "menu item on tab")[0];
+  await closeTabContextMenu(menuItem);
+  await extension.awaitMessage("onCommand_on_tab_click");
+
+  await extension.unload();
+
+  BrowserTestUtils.removeTab(tab1);
+  BrowserTestUtils.removeTab(tab2);
+}
+
+add_task(async function activeTabForTabMenu() {
+  await openTwoTabsAndOpenTabMenu(async function onTabMenuClicked(info, tab) {
+    browser.test.assertEq(0, tab.index, "Expected a menu on the first tab.");
+
+    try {
+      let [actualUrl] = await browser.tabs.executeScript(tab.id, {code: "document.URL"});
+      browser.test.assertEq(tab.url, actualUrl, "Content script to execute in the first tab");
+      // (the activeTab permission should have been granted to the first tab.)
+    } catch (e) {
+      browser.test.fail(`Unexpected error in executeScript: ${e} :: ${e.stack}`);
+    }
+  });
+});
+
+add_task(async function noActiveTabForCurrentTab() {
+  await openTwoTabsAndOpenTabMenu(async function onTabMenuClicked(info, tab) {
+    const PAGE_URL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html";
+    browser.test.assertEq(0, tab.index, "Expected a menu on the first tab.");
+    browser.test.assertEq(PAGE_URL, tab.url, "Expected tab.url to be available for the first tab");
+
+    let [tab2] = await browser.tabs.query({windowId: tab.windowId, index: 1});
+    browser.test.assertTrue(tab2.active, "The second tab should be focused.");
+    browser.test.assertEq(undefined, tab2.url, "Expected tab.url to be unavailable for the second tab.");
+
+    await browser.test.assertRejects(
+      browser.tabs.executeScript(tab2.id, {code: "document.URL"}),
+      /Missing host permission for the tab/,
+      "Content script should not run in the second tab");
+    // (The activeTab permission was granted to the first tab, not tab2.)
+  });
+});