summaryrefslogtreecommitdiffstats
path: root/browser/modules/test/browser/browser_PageActions_contextMenus.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/modules/test/browser/browser_PageActions_contextMenus.js')
-rw-r--r--browser/modules/test/browser/browser_PageActions_contextMenus.js226
1 files changed, 226 insertions, 0 deletions
diff --git a/browser/modules/test/browser/browser_PageActions_contextMenus.js b/browser/modules/test/browser/browser_PageActions_contextMenus.js
new file mode 100644
index 0000000000..a76a5bcb16
--- /dev/null
+++ b/browser/modules/test/browser/browser_PageActions_contextMenus.js
@@ -0,0 +1,226 @@
+"use strict";
+
+// This is a test for PageActions.jsm, specifically the context menus.
+
+ChromeUtils.defineESModuleGetters(this, {
+ ExtensionCommon: "resource://gre/modules/ExtensionCommon.sys.mjs",
+});
+
+// Initialization. Must run first.
+add_setup(async function () {
+ // The page action urlbar button, and therefore the panel, is only shown when
+ // the current tab is actionable -- i.e., a normal web page. about:blank is
+ // not, so open a new tab first thing, and close it when this test is done.
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "http://example.com/",
+ });
+ registerCleanupFunction(async () => {
+ BrowserTestUtils.removeTab(tab);
+ });
+
+ await initPageActionsTest();
+});
+
+// Opens the context menu on a non-built-in action. (The context menu for
+// built-in actions is tested in browser_page_action_menu.js.)
+add_task(async function contextMenu() {
+ // Add an extension with a page action so we can test its context menu.
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ name: "Page action test",
+ page_action: { show_matches: ["<all_urls>"] },
+ },
+ useAddonManager: "temporary",
+ });
+ await extension.startup();
+ let actionId = ExtensionCommon.makeWidgetId(extension.id);
+
+ // Open the main panel.
+ await promiseOpenPageActionPanel();
+ let panelButton = BrowserPageActions.panelButtonNodeForActionID(actionId);
+ let cxmenu = document.getElementById("pageActionContextMenu");
+
+ let contextMenuPromise;
+ let menuItems;
+
+ // Open the context menu again on the action's button in the panel. (The
+ // panel should still be open.)
+ contextMenuPromise = promisePanelShown("pageActionContextMenu");
+ EventUtils.synthesizeMouseAtCenter(panelButton, {
+ type: "contextmenu",
+ button: 2,
+ });
+ await contextMenuPromise;
+ menuItems = collectContextMenuItems();
+ Assert.deepEqual(makeMenuItemSpecs(menuItems), makeContextMenuItemSpecs());
+
+ // Click the "manage extension" context menu item. about:addons should open.
+ let manageItemIndex = 0;
+ contextMenuPromise = promisePanelHidden("pageActionContextMenu");
+ let aboutAddonsPromise = BrowserTestUtils.waitForNewTab(
+ gBrowser,
+ "about:addons"
+ );
+ cxmenu.activateItem(menuItems[manageItemIndex]);
+ let values = await Promise.all([aboutAddonsPromise, contextMenuPromise]);
+ let aboutAddonsTab = values[0];
+ BrowserTestUtils.removeTab(aboutAddonsTab);
+
+ // Wait for the urlbar button to become visible again after about:addons is
+ // closed and the test tab becomes selected.
+ await BrowserTestUtils.waitForCondition(() => {
+ return BrowserPageActions.urlbarButtonNodeForActionID(actionId);
+ }, "Waiting for urlbar button to be added back");
+
+ // Open the context menu on the action's urlbar button.
+ let urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(actionId);
+ contextMenuPromise = promisePanelShown("pageActionContextMenu");
+ EventUtils.synthesizeMouseAtCenter(urlbarButton, {
+ type: "contextmenu",
+ button: 2,
+ });
+ await contextMenuPromise;
+ menuItems = collectContextMenuItems();
+ Assert.deepEqual(makeMenuItemSpecs(menuItems), makeContextMenuItemSpecs());
+
+ // Click the "manage" context menu item. about:addons should open.
+ contextMenuPromise = promisePanelHidden("pageActionContextMenu");
+ aboutAddonsPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
+ cxmenu.activateItem(menuItems[manageItemIndex]);
+ values = await Promise.all([aboutAddonsPromise, contextMenuPromise]);
+ aboutAddonsTab = values[0];
+ BrowserTestUtils.removeTab(aboutAddonsTab);
+
+ // Wait for the urlbar button to become visible again after about:addons is
+ // closed and the test tab becomes selected.
+ await BrowserTestUtils.waitForCondition(() => {
+ return BrowserPageActions.urlbarButtonNodeForActionID(actionId);
+ }, "Waiting for urlbar button to be added back");
+
+ // Open the context menu on the action's urlbar button.
+ urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(actionId);
+ contextMenuPromise = promisePanelShown("pageActionContextMenu");
+ EventUtils.synthesizeMouseAtCenter(urlbarButton, {
+ type: "contextmenu",
+ button: 2,
+ });
+ await contextMenuPromise;
+ menuItems = collectContextMenuItems();
+ Assert.deepEqual(makeMenuItemSpecs(menuItems), makeContextMenuItemSpecs());
+
+ // Below we'll click the "remove extension" context menu item, which first
+ // opens a prompt using the prompt service and requires confirming the prompt.
+ // Set up a mock prompt service that returns 0 to indicate that the user
+ // pressed the OK button.
+ let { prompt } = Services;
+ let promptService = {
+ QueryInterface: ChromeUtils.generateQI(["nsIPromptService"]),
+ confirmEx() {
+ return 0;
+ },
+ };
+ Services.prompt = promptService;
+ registerCleanupFunction(() => {
+ Services.prompt = prompt;
+ });
+
+ // Now click the "remove extension" context menu item.
+ let removeItemIndex = manageItemIndex + 1;
+ contextMenuPromise = promisePanelHidden("pageActionContextMenu");
+ let promiseUninstalled = promiseAddonUninstalled(extension.id);
+ cxmenu.activateItem(menuItems[removeItemIndex]);
+ await contextMenuPromise;
+ await promiseUninstalled;
+ await extension.unload();
+ Services.prompt = prompt;
+
+ // urlbar tests that run after this one can break if the mouse is left over
+ // the area where the urlbar popup appears, which seems to happen due to the
+ // above synthesized mouse events. Move it over the urlbar.
+ EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" });
+ gURLBar.focus();
+});
+
+// The context menu shouldn't open on separators in the panel.
+add_task(async function contextMenuOnSeparator() {
+ // Add a non-built-in action so the built-in separator will appear in the
+ // panel.
+ let action = PageActions.addAction(
+ new PageActions.Action({
+ id: "contextMenuOnSeparator",
+ title: "contextMenuOnSeparator",
+ pinnedToUrlbar: true,
+ })
+ );
+
+ // Open the panel and get the built-in separator.
+ await promiseOpenPageActionPanel();
+ let separator = BrowserPageActions.panelButtonNodeForActionID(
+ PageActions.ACTION_ID_BUILT_IN_SEPARATOR
+ );
+ Assert.ok(separator, "The built-in separator should be in the panel");
+
+ // Context-click it. popupshowing should be fired, but by the time the event
+ // reaches this listener, preventDefault should have been called on it.
+ let showingPromise = BrowserTestUtils.waitForEvent(
+ document.getElementById("pageActionContextMenu"),
+ "popupshowing",
+ false
+ );
+ EventUtils.synthesizeMouseAtCenter(separator, {
+ type: "contextmenu",
+ button: 2,
+ });
+ let event = await showingPromise;
+ Assert.ok(
+ event.defaultPrevented,
+ "defaultPrevented should be true on popupshowing event"
+ );
+
+ // Click the main button to hide the main panel.
+ EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
+ await promisePageActionPanelHidden();
+
+ action.remove();
+
+ // urlbar tests that run after this one can break if the mouse is left over
+ // the area where the urlbar popup appears, which seems to happen due to the
+ // above synthesized mouse events. Move it over the urlbar.
+ EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" });
+ gURLBar.focus();
+});
+
+function collectContextMenuItems() {
+ let contextMenu = document.getElementById("pageActionContextMenu");
+ return Array.prototype.filter.call(contextMenu.children, node => {
+ return window.getComputedStyle(node).visibility == "visible";
+ });
+}
+
+function makeMenuItemSpecs(elements) {
+ return elements.map(e =>
+ e.localName == "menuseparator" ? {} : { label: e.label }
+ );
+}
+
+function makeContextMenuItemSpecs() {
+ let items = [
+ { label: "Manage Extension\u2026" },
+ { label: "Remove Extension" },
+ ];
+ return items;
+}
+
+function promiseAddonUninstalled(addonId) {
+ return new Promise(resolve => {
+ let listener = {};
+ listener.onUninstalled = addon => {
+ if (addon.id == addonId) {
+ AddonManager.removeAddonListener(listener);
+ resolve();
+ }
+ };
+ AddonManager.addAddonListener(listener);
+ });
+}