Bug 1419195: Show items from WebExtensions in bookmarks sidebar context menu
MozReview-Commit-ID: Bku5RM11TSC
--- a/browser/components/extensions/parent/ext-menus.js
+++ b/browser/components/extensions/parent/ext-menus.js
@@ -728,38 +728,75 @@ 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 browser = window.document.getElementById("sidebar");
+ browser.addEventListener("load", menuTracker.onSidebarLoad,
+ {capture: true}); // Load events don't bubble.
+ if (window.sidebar.document.readyState === "complete") {
+ menuTracker.onSidebarLoad({currentTarget: browser});
+ }
+ },
+
+ cleanupWindow(window) {
+ for (const id of this.menuIds) {
+ const menu = window.document.getElementById(id);
+ menu.removeEventListener("popupshowing", this);
+ }
+ const browser = window.document.getElementById("sidebar");
+ browser.removeEventListener("load", this.onSidebarLoad, {capture: true});
+
+ const URL = window.document.getElementById("viewBookmarksSidebar")
+ .getAttribute("sidebarurl");
+ if (window.sidebar.location.href === URL) {
+ const menu = window.sidebar.document.getElementById("placesContext");
+ menu.removeEventListener("popupshowing", this);
+ }
+ },
+
+ onSidebarLoad(event) {
+ // The listener is on the sidebar <browser>, so window is the regular
+ // browser window that contains the sidebar.
+ const window = event.currentTarget.ownerGlobal;
+ const URL = window.document.getElementById("viewBookmarksSidebar")
+ .getAttribute("sidebarurl");
+ if (window.sidebar.location.href === URL) {
+ const menu = window.sidebar.document.getElementById("placesContext");
+ menu.addEventListener("popupshowing", menuTracker);
+ }
},
handleEvent(event) {
const menu = event.target;
+
+ if (event.view === event.view.parent.sidebar) {
+ return menuTracker.handleSidebarCtxMenu(event);
+ }
+
if (menu.id === "placesContext") {
const trigger = menu.triggerNode;
if (!trigger._placesNode) {
return;
}
gMenuBuilder.build({
menu,
@@ -774,16 +811,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});
}
},
+
+ handleSidebarCtxMenu(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
@@ -71,16 +71,17 @@ skip-if = (verify && debug && (os == 'ma
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_uninstall.js]
[browser_ext_contextMenus_urlPatterns.js]
[browser_ext_currentWindow.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,63 +514,87 @@ 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() {
- const bookmarksToolbar = document.getElementById("PersonalToolbar");
- setToolbarVisibility(bookmarksToolbar, true);
-
- const extension = ExtensionTestUtils.loadExtension({
+function bookmarkContextMenuExtension() {
+ return ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["contextMenus", "bookmarks"],
},
async background() {
const url = "https://example.com/";
const title = "Example";
let newBookmark = await browser.bookmarks.create({
url,
title,
parentId: "toolbar_____",
});
await browser.contextMenus.create({
title: "Get bookmark",
contexts: ["bookmark"],
});
- browser.test.sendMessage("bookmark-created");
+ browser.test.sendMessage("bookmark-created", newBookmark.id);
browser.contextMenus.onClicked.addListener(async (info) => {
browser.test.assertEq(newBookmark.id, info.bookmarkId, "Bookmark ID matches");
let [bookmark] = await browser.bookmarks.get(info.bookmarkId);
browser.test.assertEq(title, bookmark.title, "Bookmark title matches");
browser.test.assertEq(url, bookmark.url, "Bookmark url matches");
browser.test.assertFalse(info.hasOwnProperty("pageUrl"), "Context menu does not expose pageUrl");
await browser.bookmarks.remove(info.bookmarkId);
browser.test.sendMessage("test-finish");
});
},
});
+}
+
+add_task(async function test_bookmark_contextmenu() {
+ 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);
});
+add_task(async function test_bookmark_sidebar_contextmenu() {
+ await withSidebarTree("bookmarks", async (tree) => {
+ let extension = bookmarkContextMenuExtension();
+ await extension.startup();
+ let bookmarkGuid = await extension.awaitMessage("bookmark-created");
+
+ let menu = window.sidebar.document.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, window.sidebar);
+ await extension.awaitMessage("test-finish");
+ await extension.unload();
+ });
+});
+
add_task(async function test_bookmark_context_requires_permission() {
const bookmarksToolbar = document.getElementById("PersonalToolbar");
setToolbarVisibility(bookmarksToolbar, true);
const extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["contextMenus"],
},