/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* vim: set sts=2 sw=2 et tw=80: */ "use strict"; async function openContextMenuInOptionsPage(optionsBrowser) { let contentAreaContextMenu = document.getElementById( "contentAreaContextMenu" ); let popupShownPromise = BrowserTestUtils.waitForEvent( contentAreaContextMenu, "popupshown" ); info("Trigger context menu in the extension options page"); // Instead of BrowserTestUtils.synthesizeMouseAtCenter, we are dispatching a contextmenu // event directly on the target element to prevent intermittent failures on debug builds // (especially linux32-debug), see Bug 1519808 for a rationale. SpecialPowers.spawn(optionsBrowser, [], () => { let el = content.document.querySelector("a"); el.dispatchEvent( new content.MouseEvent("contextmenu", { bubbles: true, cancelable: true, view: el.ownerGlobal, }) ); }); info("Wait the context menu to be shown"); await popupShownPromise; return contentAreaContextMenu; } async function contextMenuClosed(contextMenu) { info("Wait context menu popup to be closed"); await closeContextMenu(contextMenu); is(contextMenu.state, "closed", "The context menu popup has been closed"); } add_task(async function test_tab_options_popups() { async function backgroundScript() { browser.menus.onShown.addListener(info => { browser.test.sendMessage("extension-menus-onShown", info); }); await browser.menus.create({ id: "sidebaronly", title: "sidebaronly", viewTypes: ["sidebar"], }); await browser.menus.create({ id: "tabonly", title: "tabonly", viewTypes: ["tab"], }); await browser.menus.create({ id: "anypage", title: "anypage" }); browser.runtime.openOptionsPage(); } function optionsScript() { browser.test.sendMessage("options-page:loaded", document.documentURI); } let extension = ExtensionTestUtils.loadExtension({ useAddonManager: "temporary", manifest: { permissions: ["tabs", "menus"], options_ui: { page: "options.html", }, }, files: { "options.html": `

Extensions Options

options page link `, "options.js": optionsScript, }, background: backgroundScript, }); const aboutAddonsTab = await BrowserTestUtils.openNewForegroundTab( gBrowser, "about:addons" ); await extension.startup(); const pageUrl = await extension.awaitMessage("options-page:loaded"); const optionsBrowser = getInlineOptionsBrowser(gBrowser.selectedBrowser); const contentAreaContextMenu = await openContextMenuInOptionsPage( optionsBrowser ); let contextMenuItemIds = [ "context-openlinkintab", "context-openlinkprivate", "context-copylink", ]; // Test that the "open link in container" menu is available if the containers are enabled // (which is the default on Nightly, but not on Beta). if (Services.prefs.getBoolPref("privacy.userContext.enabled")) { contextMenuItemIds.push("context-openlinkinusercontext-menu"); } for (const itemID of contextMenuItemIds) { const item = contentAreaContextMenu.querySelector(`#${itemID}`); ok(!item.hidden, `${itemID} should not be hidden`); ok(!item.disabled, `${itemID} should not be disabled`); } const menuDetails = await extension.awaitMessage("extension-menus-onShown"); isnot( menuDetails.targetElementId, undefined, "Got a targetElementId in the menu details" ); delete menuDetails.targetElementId; Assert.deepEqual( menuDetails, { menuIds: ["anypage"], contexts: ["link", "all"], viewType: undefined, frameId: 0, editable: false, linkText: "options page link", linkUrl: "http://mochi.test:8888/", pageUrl, }, "Got the expected menu details from menus.onShown" ); await contextMenuClosed(contentAreaContextMenu); BrowserTestUtils.removeTab(aboutAddonsTab); await extension.unload(); }); add_task(async function overrideContext_in_options_page() { function optionsScript() { document.addEventListener( "contextmenu", () => { browser.menus.overrideContext({}); browser.test.sendMessage("contextmenu-overridden"); }, { once: true } ); browser.test.sendMessage("options-page:loaded"); } let extension = ExtensionTestUtils.loadExtension({ useAddonManager: "temporary", manifest: { permissions: ["tabs", "menus", "menus.overrideContext"], options_ui: { page: "options.html", }, }, files: { "options.html": `

Extensions Options

options page link `, "options.js": optionsScript, }, async background() { // Expected to match and be shown. await new Promise(resolve => { browser.menus.create({ id: "bg_1_1", title: "bg_1_1" }); browser.menus.create({ id: "bg_1_2", title: "bg_1_2" }); // Expected to not match and be hidden. browser.menus.create( { id: "bg_1_3", title: "bg_1_3", targetUrlPatterns: ["*://nomatch/*"], }, // menus.create returns a number and gets a callback, the order // is deterministic and so we just need to wait for the last one. resolve ); }); browser.runtime.openOptionsPage(); }, }); const aboutAddonsTab = await BrowserTestUtils.openNewForegroundTab( gBrowser, "about:addons" ); await extension.startup(); await extension.awaitMessage("options-page:loaded"); const optionsBrowser = getInlineOptionsBrowser(gBrowser.selectedBrowser); const contentAreaContextMenu = await openContextMenuInOptionsPage( optionsBrowser ); await extension.awaitMessage("contextmenu-overridden"); const allVisibleMenuItems = Array.from(contentAreaContextMenu.children) .filter(elem => { return !elem.hidden; }) .map(elem => elem.id); Assert.deepEqual( allVisibleMenuItems, [ `${makeWidgetId(extension.id)}-menuitem-_bg_1_1`, `${makeWidgetId(extension.id)}-menuitem-_bg_1_2`, ], "Expected only extension menu items" ); await contextMenuClosed(contentAreaContextMenu); BrowserTestUtils.removeTab(aboutAddonsTab); await extension.unload(); });