Bug 1419195: Show items from WebExtensions in bookmarks sidebar context menu r=mixedpuppy
☠☠ backed out by 65b6d0b670b4 ☠ ☠
authorPeter Simonyi <pts@petersimonyi.ca>
Tue, 15 Jan 2019 14:06:03 +0000
changeset 453928 d9a81de35ac3bee7f1e69d59d90a6ad7ee82c5c9
parent 453916 5090d461e169e160de477c06b3606c9e130f9f00
child 453929 c04c2376a2133c875df0e71749572688abe562a0
push id35380
push userdluca@mozilla.com
push dateTue, 15 Jan 2019 22:13:12 +0000
treeherdermozilla-central@a51d26029042 [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"],
     },