Bug 1419195: Show items from WebExtensions in bookmarks sidebar context menu r=mixedpuppy
☠☠ backed out by eb00c4fbfb23 ☠ ☠
authorPeter Simonyi <pts@petersimonyi.ca>
Mon, 14 Jan 2019 15:41:27 +0000
changeset 513726 ee53bdc5b1d4b868b80149e361720a9baa076c1a
parent 513725 3ef29704bc3d34cc4e3b4c804f5547d5527c2564
child 513727 732184f122e33f786637a338308efa5564d34a4e
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmixedpuppy
bugs1419195
milestone66.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 1419195: Show items from WebExtensions in bookmarks sidebar context menu r=mixedpuppy Differential Revision: https://phabricator.services.mozilla.com/D16413
browser/components/extensions/parent/ext-menus.js
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_contextMenus.js
--- a/browser/components/extensions/parent/ext-menus.js
+++ b/browser/components/extensions/parent/ext-menus.js
@@ -874,38 +874,69 @@ const menuTracker = {
       this.onWindowOpen(window);
     }
     windowTracker.addOpenListener(this.onWindowOpen);
   },
 
   unregister() {
     Services.obs.removeObserver(this, "on-build-contextmenu");
     for (const window of windowTracker.browserWindows()) {
-      for (const id of this.menuIds) {
-        const menu = window.document.getElementById(id);
-        menu.removeEventListener("popupshowing", this);
-      }
+      this.cleanupWindow(window);
     }
     windowTracker.removeOpenListener(this.onWindowOpen);
   },
 
   observe(subject, topic, data) {
     subject = subject.wrappedJSObject;
     gMenuBuilder.build(subject);
   },
 
   onWindowOpen(window) {
     for (const id of menuTracker.menuIds) {
       const menu = window.document.getElementById(id);
       menu.addEventListener("popupshowing", menuTracker);
     }
+
+    const sidebarHeader = window.document.getElementById("sidebar-switcher-target");
+    sidebarHeader.addEventListener("SidebarShown", menuTracker.onSidebarShown);
+    if (window.SidebarUI.currentID === "viewBookmarksSidebar") {
+      menuTracker.onSidebarShown({currentTarget: window.SidebarUI.browser});
+    }
+  },
+
+  cleanupWindow(window) {
+    for (const id of this.menuIds) {
+      const menu = window.document.getElementById(id);
+      menu.removeEventListener("popupshowing", this);
+    }
+
+    const sidebarHeader = window.document.getElementById("sidebar-switcher-target");
+    sidebarHeader.removeEventListener("SidebarShown", this.onSidebarShown);
+
+    if (window.SidebarUI.currentID === "viewBookmarksSidebar") {
+      const menu = window.SidebarUI.browser.contentDocument
+                         .getElementById("placesContext");
+      menu.removeEventListener("popupshowing", this.onBookmarksContextMenu);
+    }
+  },
+
+  onSidebarShown(event) {
+    // The listener is on the sidebar <browser>, so window is the regular
+    // browser window that contains the sidebar.
+    const window = event.currentTarget.ownerGlobal;
+    if (window.SidebarUI.currentID === "viewBookmarksSidebar") {
+      const menu = window.SidebarUI.browser.contentDocument
+                         .getElementById("placesContext");
+      menu.addEventListener("popupshowing", menuTracker.onBookmarksContextMenu);
+    }
   },
 
   handleEvent(event) {
     const menu = event.target;
+
     if (menu.id === "placesContext") {
       const trigger = menu.triggerNode;
       if (!trigger._placesNode) {
         return;
       }
 
       gMenuBuilder.build({
         menu,
@@ -920,16 +951,29 @@ const menuTracker = {
     }
     if (menu.id === "tabContextMenu") {
       const trigger = menu.triggerNode;
       const tab = trigger.localName === "tab" ? trigger : tabTracker.activeTab;
       const pageUrl = tab.linkedBrowser.currentURI.spec;
       gMenuBuilder.build({menu, tab, pageUrl, onTab: true});
     }
   },
+
+  onBookmarksContextMenu(event) {
+    const menu = event.target;
+    const tree = menu.triggerNode.parentElement;
+    const cell = tree.boxObject.getCellAt(event.x, event.y);
+    const node = tree.view.nodeForTreeIndex(cell.row);
+
+    gMenuBuilder.build({
+      menu,
+      bookmarkId: node.bookmarkGuid,
+      onBookmark: true,
+    });
+  },
 };
 
 this.menusInternal = class extends ExtensionAPI {
   constructor(extension) {
     super(extension);
 
     if (!gMenuMap.size) {
       menuTracker.register();
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -76,16 +76,17 @@ skip-if = (os == 'mac' || os == 'win' ||
 skip-if = (verify && (os == 'linux' || os == 'mac'))
 [browser_ext_commands_execute_sidebar_action.js]
 [browser_ext_commands_getAll.js]
 [browser_ext_commands_onCommand.js]
 [browser_ext_commands_update.js]
 [browser_ext_connect_and_move_tabs.js]
 [browser_ext_contentscript_connect.js]
 [browser_ext_contextMenus.js]
+support-files = !/browser/components/places/tests/browser/head.js
 [browser_ext_contextMenus_checkboxes.js]
 [browser_ext_contextMenus_commands.js]
 [browser_ext_contextMenus_icons.js]
 [browser_ext_contextMenus_onclick.js]
 [browser_ext_contextMenus_radioGroups.js]
 [browser_ext_contextMenus_targetUrlPatterns.js]
 [browser_ext_contextMenus_uninstall.js]
 [browser_ext_contextMenus_urlPatterns.js]
--- a/browser/components/extensions/test/browser/browser_ext_contextMenus.js
+++ b/browser/components/extensions/test/browser/browser_ext_contextMenus.js
@@ -1,12 +1,17 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
+Services.scriptloader.loadSubScript(
+  "chrome://mochitests/content/browser/browser/components/places/tests/browser/head.js",
+  this);
+/* globals withSidebarTree, synthesizeClickOnSelectedTreeCell */
+
 const PAGE = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html";
 
 add_task(async function() {
   let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
 
   gBrowser.selectedTab = tab1;
 
   let extension = ExtensionTestUtils.loadExtension({
@@ -509,23 +514,18 @@ add_task(async function testRemoveAllWit
   await confirmMenuItems("gamma");
   await closeContextMenu();
 
   await first.unload();
   await second.unload();
   BrowserTestUtils.removeTab(tab);
 });
 
-add_task(async function test_bookmark_contextmenu() {
-  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
-
-  const bookmarksToolbar = document.getElementById("PersonalToolbar");
-  setToolbarVisibility(bookmarksToolbar, true);
-
-  const extension = ExtensionTestUtils.loadExtension({
+function bookmarkContextMenuExtension() {
+  return ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: ["contextMenus", "bookmarks", "activeTab"],
     },
     async background() {
       const url = "https://example.com/";
       const title = "Example";
       let newBookmark = await browser.bookmarks.create({
         url,
@@ -547,36 +547,70 @@ add_task(async function test_bookmark_co
         browser.test.assertFalse(info.hasOwnProperty("pageUrl"), "Context menu does not expose pageUrl");
         await browser.bookmarks.remove(info.bookmarkId);
         browser.test.sendMessage("test-finish");
       });
       browser.contextMenus.create({
         title: "Get bookmark",
         contexts: ["bookmark"],
       }, () => {
-        browser.test.sendMessage("bookmark-created");
+        browser.test.sendMessage("bookmark-created", newBookmark.id);
       });
     },
   });
+}
+
+add_task(async function test_bookmark_contextmenu() {
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
+
+  const bookmarksToolbar = document.getElementById("PersonalToolbar");
+  setToolbarVisibility(bookmarksToolbar, true);
+
+  const extension = bookmarkContextMenuExtension();
+
   await extension.startup();
   await extension.awaitMessage("bookmark-created");
   let menu = await openChromeContextMenu(
     "placesContext",
     "#PersonalToolbar .bookmark-item:last-child");
 
   let menuItem = menu.getElementsByAttribute("label", "Get bookmark")[0];
   closeChromeContextMenu("placesContext", menuItem);
 
   await extension.awaitMessage("test-finish");
   await extension.unload();
   setToolbarVisibility(bookmarksToolbar, false);
 
   BrowserTestUtils.removeTab(tab);
 });
 
+add_task(async function test_bookmark_sidebar_contextmenu() {
+  await withSidebarTree("bookmarks", async (tree) => {
+    let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
+
+    let extension = bookmarkContextMenuExtension();
+    await extension.startup();
+    let bookmarkGuid = await extension.awaitMessage("bookmark-created");
+
+    let sidebar = window.SidebarUI.browser;
+    let menu = sidebar.contentDocument.getElementById("placesContext");
+    tree.selectItems([bookmarkGuid]);
+    let shown = BrowserTestUtils.waitForEvent(menu, "popupshown");
+    synthesizeClickOnSelectedTreeCell(tree, {type: "contextmenu"});
+    await shown;
+
+    let menuItem = menu.getElementsByAttribute("label", "Get bookmark")[0];
+    closeChromeContextMenu("placesContext", menuItem, sidebar.contentWindow);
+    await extension.awaitMessage("test-finish");
+    await extension.unload();
+
+    BrowserTestUtils.removeTab(tab);
+  });
+});
+
 add_task(async function test_bookmark_context_requires_permission() {
   const bookmarksToolbar = document.getElementById("PersonalToolbar");
   setToolbarVisibility(bookmarksToolbar, true);
 
   const extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: ["contextMenus"],
     },