Bug 1412170 - Integrate WebExtension page action context menus with the Photon page action context menu: WebExtensions changes. r?mixedpuppy draft
authorDrew Willcoxon <adw@mozilla.com>
Mon, 30 Oct 2017 17:50:33 -0400
changeset 688897 3eabcc1c9e60c9a5ceec19e364423d377b06ed58
parent 688896 1ee007964539bef3ce8d5541bc075601bb04ed5f
child 738197 cc774e35864f1576b995aee0cf34e95d263a2f22
push id86885
push userdwillcoxon@mozilla.com
push dateMon, 30 Oct 2017 21:55:06 +0000
reviewersmixedpuppy
bugs1412170
milestone58.0a1
Bug 1412170 - Integrate WebExtension page action context menus with the Photon page action context menu: WebExtensions changes. r?mixedpuppy MozReview-Commit-ID: 4vBNSmCU1a0
browser/components/extensions/ext-pageAction.js
browser/components/extensions/test/browser/browser_ext_menus.js
browser/components/extensions/test/browser/head.js
--- a/browser/components/extensions/ext-pageAction.js
+++ b/browser/components/extensions/ext-pageAction.js
@@ -68,16 +68,25 @@ this.pageAction = class extends Extensio
         id: widgetId,
         title: this.defaults.title,
         iconURL: this.defaults.icon,
         shownInUrlbar: true,
         disabled: true,
         onCommand: (event, buttonNode) => {
           this.handleClick(event.target.ownerGlobal);
         },
+        onBeforePlacedInWindow: browserWindow => {
+          if (this.extension.hasPermission("menus") ||
+              this.extension.hasPermission("contextMenus")) {
+            browserWindow.document.addEventListener("popupshowing", this);
+          }
+        },
+        onRemovedFromWindow: browserWindow => {
+          browserWindow.document.removeEventListener("popupshowing", this);
+        },
       }));
     }
   }
 
   onShutdown(reason) {
     pageActionMap.delete(this.extension);
 
     this.tabContext.shutdown();
@@ -146,16 +155,35 @@ this.pageAction = class extends Extensio
    */
   triggerAction(window) {
     let pageAction = pageActionMap.get(this.extension);
     if (pageAction.getProperty(window.gBrowser.selectedTab, "show")) {
       pageAction.handleClick(window);
     }
   }
 
+  handleEvent(event) {
+    switch (event.type) {
+      case "popupshowing":
+        const menu = event.target;
+        const trigger = menu.triggerNode;
+
+        if (menu.id === "pageActionContextMenu" &&
+            trigger &&
+            trigger.getAttribute("actionid") === this.browserPageAction.id) {
+          global.actionContextMenu({
+            extension: this.extension,
+            onPageAction: true,
+            menu: menu,
+          });
+        }
+        break;
+    }
+  }
+
   // Handles a click event on the page action button for the given
   // window.
   // If the page action has a |popup| property, a panel is opened to
   // that URL. Otherwise, a "click" event is emitted, and dispatched to
   // the any click listeners in the add-on.
   async handleClick(window) {
     TelemetryStopwatch.start(popupOpenTimingHistogram, this);
     let tab = window.gBrowser.selectedTab;
--- a/browser/components/extensions/test/browser/browser_ext_menus.js
+++ b/browser/components/extensions/test/browser/browser_ext_menus.js
@@ -63,20 +63,17 @@ add_task(async function test_actionConte
   }
 
   const extension = ExtensionTestUtils.loadExtension({manifest, background});
   const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
 
   await extension.startup();
   const tabId = await extension.awaitMessage("ready");
 
-  // TODO bug 1412170: Allow WebExtensions to hook into the browser page action
-  // context menu.
-//   for (const kind of ["page", "browser"]) {
-  for (const kind of ["browser"]) {
+  for (const kind of ["page", "browser"]) {
     const menu = await openActionContextMenu(extension, kind);
     const [submenu, second, , , , last, separator] = menu.children;
 
     is(submenu.tagName, "menu", "Correct submenu type");
     is(submenu.label, "parent", "Correct submenu title");
 
     const popup = await openSubmenu(submenu);
     is(popup, submenu.firstChild, "Correct submenu opened");
@@ -87,17 +84,17 @@ add_task(async function test_actionConte
     is(second.tagName, "menuitem", "Second menu item type is correct");
     is(second.label, "click 1", "Second menu item title is correct");
     is(second.id, `${idPrefix}1`, "Second menu item id is correct");
 
     is(last.label, "click 5", "Last menu item title is correct");
     is(last.id, `${idPrefix}5`, "Last menu item id is correct");
     is(separator.tagName, "menuseparator", "Separator after last menu item");
 
-    await closeActionContextMenu(popup.firstChild);
+    await closeActionContextMenu(popup.firstChild, kind);
     const {info, tab} = await extension.awaitMessage("click");
     is(info.pageUrl, "http://example.com/", "Click info pageUrl is correct");
     is(tab.id, tabId, "Click event tab ID is correct");
   }
 
   await BrowserTestUtils.removeTab(tab);
   await extension.unload();
 });
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -388,25 +388,31 @@ function closeChromeContextMenu(menuId, 
   }
   return hidden;
 }
 
 async function openActionContextMenu(extension, kind, win = window) {
   // See comment from clickPageAction below.
   SetPageProxyState("valid");
   await promiseAnimationFrame(win);
-  const id =
-    kind == "page" ?
-    `#${BrowserPageActions.urlbarButtonNodeIDForActionID(makeWidgetId(extension.id))}` :
-    `#${makeWidgetId(extension.id)}-${kind}-action`;
-  return openChromeContextMenu("toolbar-context-menu", id, win);
+  let buttonID;
+  let menuID;
+  if (kind == "page") {
+    buttonID = "#" + BrowserPageActions.urlbarButtonNodeIDForActionID(makeWidgetId(extension.id));
+    menuID = "pageActionContextMenu";
+  } else {
+    buttonID = `#${makeWidgetId(extension.id)}-${kind}-action`;
+    menuID = "toolbar-context-menu";
+  }
+  return openChromeContextMenu(menuID, buttonID, win);
 }
 
-function closeActionContextMenu(itemToSelect, win = window) {
-  return closeChromeContextMenu("toolbar-context-menu", itemToSelect, win);
+function closeActionContextMenu(itemToSelect, kind, win = window) {
+  let menuID = kind == "page" ? "pageActionContextMenu" : "toolbar-context-menu";
+  return closeChromeContextMenu(menuID, itemToSelect, win);
 }
 
 function openTabContextMenu(win = window) {
   return openChromeContextMenu("tabContextMenu", ".tabbrowser-tab[selected]", win);
 }
 
 function closeTabContextMenu(itemToSelect, win = window) {
   return closeChromeContextMenu("tabContextMenu", itemToSelect, win);