Bug 1353073 handle contextmenu in sidebar when remote=true, r=kmag
☠☠ backed out by 9a16c329034e ☠ ☠
authorShane Caraveo <scaraveo@mozilla.com>
Fri, 14 Apr 2017 15:15:37 -0700
changeset 353336 fc91bd1a27a72e451c435acede23ecff374e56e7
parent 353335 45f5b5a65b7fffa5d68931d427f547ac4443a10e
child 353337 292f19781579c259c19039d65f73ee6a6360a21c
push id89233
push userarchaeopteryx@coole-files.de
push dateSat, 15 Apr 2017 18:11:02 +0000
treeherdermozilla-inbound@e9539186b181 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1353073
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1353073 handle contextmenu in sidebar when remote=true, r=kmag MozReview-Commit-ID: GDAd2jYrlf6
browser/base/content/nsContextMenu.js
browser/base/content/tabbrowser.xml
browser/base/content/webext-panels.js
browser/components/extensions/test/browser/browser_ext_sidebarAction.js
browser/components/extensions/test/browser/head.js
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -15,16 +15,54 @@ Components.utils.import("resource://gre/
 
 XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
   "resource://gre/modules/LoginHelper.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames",
   "resource://gre/modules/WebNavigationFrames.jsm");
 
 var gContextMenuContentData = null;
 
+function openContextMenu(aMessage) {
+  let data = aMessage.data;
+  let browser = aMessage.target;
+
+  let spellInfo = data.spellInfo;
+  if (spellInfo)
+    spellInfo.target = aMessage.target.messageManager;
+  let documentURIObject = makeURI(data.docLocation,
+                                  data.charSet,
+                                  makeURI(data.baseURI));
+  gContextMenuContentData = { isRemote: true,
+                              event: aMessage.objects.event,
+                              popupNode: aMessage.objects.popupNode,
+                              browser,
+                              editFlags: data.editFlags,
+                              spellInfo,
+                              principal: data.principal,
+                              customMenuItems: data.customMenuItems,
+                              addonInfo: data.addonInfo,
+                              documentURIObject,
+                              docLocation: data.docLocation,
+                              charSet: data.charSet,
+                              referrer: data.referrer,
+                              referrerPolicy: data.referrerPolicy,
+                              contentType: data.contentType,
+                              contentDisposition: data.contentDisposition,
+                              frameOuterWindowID: data.frameOuterWindowID,
+                              selectionInfo: data.selectionInfo,
+                              disableSetDesktopBackground: data.disableSetDesktopBg,
+                              loginFillInfo: data.loginFillInfo,
+                              parentAllowsMixedContent: data.parentAllowsMixedContent,
+                              userContextId: data.userContextId,
+                            };
+  let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
+  let event = gContextMenuContentData.event;
+  popup.openPopupAtScreen(event.screenX, event.screenY, true);
+}
+
 function nsContextMenu(aXulMenu, aIsShift) {
   this.shouldDisplay = true;
   this.initMenu(aXulMenu, aIsShift);
 }
 
 // Prototype for nsContextMenu "class."
 nsContextMenu.prototype = {
   initMenu: function CM_initMenu(aXulMenu, aIsShift) {
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4950,48 +4950,17 @@
               if (tab) {
                 // Skip running PermitUnload since it already happened in
                 // the content process.
                 this.removeTab(tab, {skipPermitUnload: true});
               }
               break;
             }
             case "contextmenu": {
-              let spellInfo = data.spellInfo;
-              if (spellInfo)
-                spellInfo.target = aMessage.target.messageManager;
-              let documentURIObject = makeURI(data.docLocation,
-                                              data.charSet,
-                                              makeURI(data.baseURI));
-              gContextMenuContentData = { isRemote: true,
-                                          event: aMessage.objects.event,
-                                          popupNode: aMessage.objects.popupNode,
-                                          browser,
-                                          editFlags: data.editFlags,
-                                          spellInfo,
-                                          principal: data.principal,
-                                          customMenuItems: data.customMenuItems,
-                                          addonInfo: data.addonInfo,
-                                          documentURIObject,
-                                          docLocation: data.docLocation,
-                                          charSet: data.charSet,
-                                          referrer: data.referrer,
-                                          referrerPolicy: data.referrerPolicy,
-                                          contentType: data.contentType,
-                                          contentDisposition: data.contentDisposition,
-                                          frameOuterWindowID: data.frameOuterWindowID,
-                                          selectionInfo: data.selectionInfo,
-                                          disableSetDesktopBackground: data.disableSetDesktopBg,
-                                          loginFillInfo: data.loginFillInfo,
-                                          parentAllowsMixedContent: data.parentAllowsMixedContent,
-                                          userContextId: data.userContextId,
-                                        };
-              let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
-              let event = gContextMenuContentData.event;
-              popup.openPopupAtScreen(event.screenX, event.screenY, true);
+              openContextMenu(aMessage);
               break;
             }
             case "DOMWindowFocus": {
               let tab = this.getTabForBrowser(browser);
               if (!tab)
                 return undefined;
               this.selectedTab = tab;
               window.focus();
--- a/browser/base/content/webext-panels.js
+++ b/browser/base/content/webext-panels.js
@@ -1,26 +1,27 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Via webext-panels.xul
-/* import-globals-from browser.js */
+/* import-globals-from browser.js nsContextMenu.js */
 
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent",
                                   "resource://gre/modules/ExtensionParent.jsm");
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 
 var {
   promiseEvent,
 } = ExtensionUtils;
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
+
 function getBrowser(sidebar) {
   let browser = document.getElementById("webext-panels-browser");
   if (browser) {
     return Promise.resolve(browser);
   }
 
   browser = document.createElementNS(XUL_NS, "browser");
   browser.setAttribute("id", "webext-panels-browser");
@@ -34,16 +35,21 @@ function getBrowser(sidebar) {
 
   let readyPromise;
   if (sidebar.remote) {
     browser.setAttribute("remote", "true");
     browser.setAttribute("remoteType",
                          E10SUtils.getRemoteTypeForURI(sidebar.uri, true,
                                                        E10SUtils.EXTENSION_REMOTE_TYPE));
     readyPromise = promiseEvent(browser, "XULFrameLoaderCreated");
+
+    window.messageManager.addMessageListener("contextmenu", openContextMenu);
+    window.addEventListener("unload", () => {
+      window.messageManager.removeMessageListener("contextmenu", openContextMenu);
+    }, {once: true});
   } else {
     readyPromise = Promise.resolve();
   }
   document.documentElement.appendChild(browser);
 
   return readyPromise.then(() => {
     browser.messageManager.loadFrameScript("chrome://browser/content/content.js", false);
     ExtensionParent.apiManager.emit("extension-browser-inserted", browser);
--- a/browser/components/extensions/test/browser/browser_ext_sidebarAction.js
+++ b/browser/components/extensions/test/browser/browser_ext_sidebarAction.js
@@ -1,14 +1,15 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 let extData = {
   manifest: {
+    "permissions": ["contextMenus"],
     "sidebar_action": {
       "default_panel": "sidebar.html",
     },
   },
   useAddonManager: "temporary",
 
   files: {
     "sidebar.html": `
@@ -25,16 +26,22 @@ let extData = {
     "sidebar.js": function() {
       window.onload = () => {
         browser.test.sendMessage("sidebar");
       };
     },
   },
 
   background: function() {
+    browser.contextMenus.create({
+      id: "clickme-page",
+      title: "Click me!",
+      contexts: ["all"],
+    });
+
     browser.test.onMessage.addListener(msg => {
       if (msg === "set-panel") {
         browser.sidebarAction.setPanel({panel: ""}).then(() => {
           browser.test.notifyFail("empty panel settable");
         }).catch(() => {
           browser.test.notifyPass("unable to set empty panel");
         });
       }
@@ -91,12 +98,26 @@ add_task(function* sidebar_empty_panel()
   // Test sidebar is opened on install
   yield extension.awaitMessage("sidebar");
   ok(!document.getElementById("sidebar-box").hidden, "sidebar box is visible in first window");
   extension.sendMessage("set-panel");
   yield extension.awaitFinish();
   yield extension.unload();
 });
 
+add_task(function* sidebar_contextmenu() {
+  let extension = ExtensionTestUtils.loadExtension(extData);
+  yield extension.startup();
+  // Test sidebar is opened on install
+  yield extension.awaitMessage("sidebar");
+
+  let contentAreaContextMenu = yield openContextMenuInSidebar();
+  let item = contentAreaContextMenu.getElementsByAttribute("label", "Click me!");
+  is(item.length, 1, "contextMenu item for page was found");
+  yield closeContextMenu(contentAreaContextMenu);
+
+  yield extension.unload();
+});
+
 add_task(function* cleanup() {
   // This is set on initial sidebar install.
   Services.prefs.clearUserPref("extensions.sidebar-button.shown");
 });
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -3,17 +3,17 @@
 "use strict";
 
 /* exported CustomizableUI makeWidgetId focusWindow forceGC
  *          getBrowserActionWidget
  *          clickBrowserAction clickPageAction
  *          getBrowserActionPopup getPageActionPopup
  *          closeBrowserAction closePageAction
  *          promisePopupShown promisePopupHidden
- *          openContextMenu closeContextMenu
+ *          openContextMenu closeContextMenu openContextMenuInSidebar
  *          openExtensionContextMenu closeExtensionContextMenu
  *          openActionContextMenu openSubmenu closeActionContextMenu
  *          openTabContextMenu closeTabContextMenu
  *          imageBuffer imageBufferFromDataURI
  *          getListStyleImage getPanelForNode
  *          awaitExtensionPanel awaitPopupResize
  *          promiseContentDimensions alterContent
  *          promisePrefChangeObserved openContextMenuInFrame
@@ -227,16 +227,26 @@ function closeBrowserAction(extension, w
   let group = getBrowserActionWidget(extension);
 
   let node = win.document.getElementById(group.viewId);
   CustomizableUI.hidePanelForNode(node);
 
   return Promise.resolve();
 }
 
+async function openContextMenuInSidebar(selector = "body") {
+  let contentAreaContextMenu = SidebarUI.browser.contentDocument.getElementById("contentAreaContextMenu");
+  let browser = SidebarUI.browser.contentDocument.getElementById("webext-panels-browser");
+  let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
+  await BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "mousedown", button: 2}, browser);
+  await BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "contextmenu"}, browser);
+  await popupShownPromise;
+  return contentAreaContextMenu;
+}
+
 async function openContextMenuInFrame(frameId) {
   let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
   let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
   let doc = gBrowser.selectedBrowser.contentDocument;
   let frame = doc.getElementById(frameId);
   EventUtils.synthesizeMouseAtCenter(frame.contentDocument.body, {type: "contextmenu"}, frame.contentWindow);
   await popupShownPromise;
   return contentAreaContextMenu;
@@ -246,18 +256,18 @@ async function openContextMenu(selector 
   let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
   let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
   await BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "mousedown", button: 2}, gBrowser.selectedBrowser);
   await BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "contextmenu"}, gBrowser.selectedBrowser);
   await popupShownPromise;
   return contentAreaContextMenu;
 }
 
-async function closeContextMenu() {
-  let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
+async function closeContextMenu(contextMenu) {
+  let contentAreaContextMenu = contextMenu || document.getElementById("contentAreaContextMenu");
   let popupHiddenPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popuphidden");
   contentAreaContextMenu.hidePopup();
   await popupHiddenPromise;
 }
 
 function* openExtensionContextMenu(selector = "#img1") {
   let contextMenu = yield openContextMenu(selector);
   let topLevelMenu = contextMenu.getElementsByAttribute("ext-type", "top-level-menu");