--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -210,25 +210,25 @@ nsContextMenu.prototype = {
this.showItem("context-openlinkinusercontext-menu", shouldShow && !isWindowPrivate && showContainers);
this.showItem("context-openlinkincurrent", this.onPlainTextLink);
this.showItem("context-sep-open", shouldShow);
},
initNavigationItems: function CM_initNavigationItems() {
var shouldShow = !(this.isContentSelected || this.onLink || this.onImage ||
this.onCanvas || this.onVideo || this.onAudio ||
- this.onTextInput || this.onSocial);
+ this.onTextInput) && this.inTabBrowser;
this.showItem("context-navigation", shouldShow);
this.showItem("context-sep-navigation", shouldShow);
let stopped = XULBrowserWindow.stopCommand.getAttribute("disabled") == "true";
let stopReloadItem = "";
- if (shouldShow || this.onSocial) {
- stopReloadItem = (stopped || this.onSocial) ? "reload" : "stop";
+ if (shouldShow || !this.inTabBrowser) {
+ stopReloadItem = (stopped || !this.inTabBrowser) ? "reload" : "stop";
}
this.showItem("context-reload", stopReloadItem == "reload");
this.showItem("context-stop", stopReloadItem == "stop");
// XXX: Stop is determined in browser.js; the canStop broadcaster is broken
// this.setItemAttrFromNode( "context-stop", "disabled", "canStop" );
},
@@ -285,19 +285,22 @@ nsContextMenu.prototype = {
this.isContentSelected);
this.showItem("context-viewpartialsource-mathml",
this.onMathML && !this.isContentSelected);
var shouldShow = !(this.isContentSelected ||
this.onImage || this.onCanvas ||
this.onVideo || this.onAudio ||
this.onLink || this.onTextInput);
- var showInspect = !this.onSocial && gPrefService.getBoolPref("devtools.inspector.enabled");
+ var showInspect = this.inTabBrowser && gPrefService.getBoolPref("devtools.inspector.enabled");
this.showItem("context-viewsource", shouldShow);
this.showItem("context-viewinfo", shouldShow);
+ // The page info is broken for WebExtension popups, as the browser is
+ // destroyed when the popup is closed.
+ this.setItemAttr("context-viewinfo", "disabled", this.webExtBrowserType === "popup");
this.showItem("inspect-separator", showInspect);
this.showItem("context-inspect", showInspect);
this.showItem("context-sep-viewsource", shouldShow);
// Set as Desktop background depends on whether an image was clicked on,
// and only works if we have a shell service.
var haveSetDesktopBackground = false;
@@ -336,30 +339,34 @@ nsContextMenu.prototype = {
!this.inSyntheticDoc);
this.showItem("context-sep-viewbgimage", shouldShow &&
!this._hasMultipleBGImages &&
!this.inSyntheticDoc);
document.getElementById("context-viewbgimage")
.disabled = !this.hasBGImage;
this.showItem("context-viewimageinfo", this.onImage);
+ // The image info popup is broken for WebExtension popups, since the browser
+ // is destroyed when the popup is closed.
+ this.setItemAttr("context-viewimageinfo", "disabled", this.webExtBrowserType === "popup");
this.showItem("context-viewimagedesc", this.onImage && this.imageDescURL !== "");
},
initMiscItems: function CM_initMiscItems() {
// Use "Bookmark This Link" if on a link.
let bookmarkPage = document.getElementById("context-bookmarkpage");
this.showItem(bookmarkPage,
!(this.isContentSelected || this.onTextInput || this.onLink ||
this.onImage || this.onVideo || this.onAudio || this.onSocial ||
- this.onCanvas));
+ this.onCanvas || this.inWebExtBrowser));
bookmarkPage.setAttribute("tooltiptext", bookmarkPage.getAttribute("buttontooltiptext"));
this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink &&
- !this.onSocial) || this.onPlainTextLink);
+ !this.onSocial && !this.onMozExtLink) ||
+ this.onPlainTextLink);
this.showItem("context-keywordfield",
this.onTextInput && this.onKeywordField);
this.showItem("frame", this.inFrame);
let showSearchSelect = (this.isTextSelected || this.onLink) && !this.onImage;
this.showItem("context-searchselect", showSearchSelect);
if (showSearchSelect) {
this.formatSearchContextItem();
@@ -393,23 +400,24 @@ nsContextMenu.prototype = {
this.showItem("context-bidi-page-direction-toggle",
!this.onTextInput && top.gBidiUI);
// SocialShare
let shareButton = SocialShare.shareButton;
let shareEnabled = shareButton && !shareButton.disabled && !this.onSocial;
let pageShare = shareEnabled && !(this.isContentSelected ||
this.onTextInput || this.onLink || this.onImage ||
- this.onVideo || this.onAudio || this.onCanvas);
+ this.onVideo || this.onAudio || this.onCanvas ||
+ this.inWebExtBrowser);
this.showItem("context-sharepage", pageShare);
this.showItem("context-shareselect", shareEnabled && this.isContentSelected);
- this.showItem("context-sharelink", shareEnabled && (this.onLink || this.onPlainTextLink) && !this.onMailtoLink);
+ this.showItem("context-sharelink", shareEnabled && (this.onLink || this.onPlainTextLink) && !this.onMailtoLink && !this.onMozExtLink);
this.showItem("context-shareimage", shareEnabled && this.onImage);
this.showItem("context-sharevideo", shareEnabled && this.onVideo);
- this.setItemAttr("context-sharevideo", "disabled", !this.mediaURL || this.mediaURL.startsWith("blob:"));
+ this.setItemAttr("context-sharevideo", "disabled", !this.mediaURL || this.mediaURL.startsWith("blob:") || this.mediaURL.startsWith("moz-extension:"));
},
initSpellingItems() {
var canSpell = InlineSpellCheckerUI.canSpellCheck &&
!InlineSpellCheckerUI.initialSpellCheckPending &&
this.canSpellCheck;
let showDictionaries = canSpell && InlineSpellCheckerUI.enabled;
var onMisspelling = InlineSpellCheckerUI.overMisspelling;
@@ -672,16 +680,20 @@ nsContextMenu.prototype = {
this.inSyntheticDoc = false;
this.hasBGImage = false;
this.bgImageURL = "";
this.onEditableArea = false;
this.isDesignMode = false;
this.onCTPPlugin = false;
this.canSpellCheck = false;
this.onPassword = false;
+ this.webExtBrowserType = "";
+ this.inWebExtBrowser = false;
+ this.inTabBrowser = true;
+ this.onMozExtLink = false;
if (this.isRemote) {
this.selectionInfo = gContextMenuContentData.selectionInfo;
} else {
this.selectionInfo = BrowserUtils.getSelectionDetails(window);
}
this.textSelected = this.selectionInfo.text;
@@ -708,16 +720,20 @@ nsContextMenu.prototype = {
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
this.principal = ownerDoc.nodePrincipal;
this.frameOuterWindowID = WebNavigationFrames.getFrameId(ownerDoc.defaultView);
}
this.onSocial = !!this.browser.getAttribute("origin");
+ this.webExtBrowserType = this.browser.getAttribute("webextension-view-type");
+ this.inWebExtBrowser = !!this.webExtBrowserType;
+ this.inTabBrowser = this.browser.ownerGlobal.gBrowser ?
+ !!this.browser.ownerGlobal.gBrowser.getTabForBrowser(this.browser) : false;
// Check if we are in a synthetic document (stand alone image, video, etc.).
this.inSyntheticDoc = ownerDoc.mozSyntheticDocument;
this._setTargetForNodesNoChildren(editFlags, aRangeParent, aRangeOffset);
this._setTargetForNodesWithChildren(editFlags, aRangeParent, aRangeOffset);
},
@@ -864,16 +880,17 @@ nsContextMenu.prototype = {
// Remember corresponding element.
this.link = elem;
this.linkURL = this.getLinkURL();
this.linkURI = this.getLinkURI();
this.linkTextStr = this.getLinkText();
this.linkProtocol = this.getLinkProtocol();
this.onMailtoLink = (this.linkProtocol == "mailto");
+ this.onMozExtLink = (this.linkProtocol == "moz-extension");
this.onSaveableLink = this.isLinkSaveable( this.link );
this.linkHasNoReferrer = BrowserUtils.linkHasNoReferrer(elem);
try {
if (elem.download) {
// Ignore download attribute on cross-origin links
this.principal.checkMayLoad(this.linkURI, false, true);
this.linkDownload = elem.download;
}
@@ -1906,17 +1923,17 @@ nsContextMenu.prototype = {
};
aXulMenu.ownerDocument.addEventListener("command", activationHandler, true);
aXulMenu.addEventListener("popuphiding", this._onPopupHiding, true);
},
_getTelemetryPageContextInfo() {
let rv = [];
for (let k of ["isContentSelected", "onLink", "onImage", "onCanvas", "onVideo", "onAudio",
- "onTextInput", "onSocial"]) {
+ "onTextInput", "onSocial", "inWebExtBrowser", "inTabBrowser"]) {
if (this[k]) {
rv.push(k.replace(/^(?:is|on)(.)/, (match, firstLetter) => firstLetter.toLowerCase()));
}
}
if (!rv.length) {
rv.push("other");
}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/contextMenu/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+ "extends": [
+ "plugin:mozilla/browser-test"
+ ]
+};
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/contextMenu/browser.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+support-files =
+ !/browser/base/content/test/general/contextmenu_common.js
+ subtst_contextmenu_webext.html
+
+[browser_contextmenu_mozextension.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/contextMenu/browser_contextmenu_mozextension.js
@@ -0,0 +1,82 @@
+"use strict";
+
+var { SocialService } = Cu.import("resource:///modules/SocialService.jsm", {});
+
+let contextMenu;
+let hasPocket = Services.prefs.getBoolPref("extensions.pocket.enabled");
+let hasContainers = Services.prefs.getBoolPref("privacy.userContext.enabled");
+
+// A social share provider
+let manifest = {
+ name: "provider 1",
+ origin: "https://example.com",
+ iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png",
+ shareURL: "https://example.com/browser/browser/base/content/test/social/share.html"
+};
+
+add_task(function* test_setup() {
+ const example_base = "http://example.com/browser/browser/base/content/test/contextMenu/";
+ const url = example_base + "subtst_contextmenu_webext.html";
+ yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+
+ const chrome_base = "chrome://mochitests/content/browser/browser/base/content/test/general/";
+ const contextmenu_common = chrome_base + "contextmenu_common.js";
+ /* import-globals-from ../general/contextmenu_common.js */
+ Services.scriptloader.loadSubScript(contextmenu_common, this);
+
+ // Enable social sharing functions in the browser, so the context menu item is shown.
+ CustomizableUI.addWidgetToArea("social-share-button", CustomizableUI.AREA_NAVBAR);
+
+ yield new Promise((resolve) => SocialService.addProvider(manifest, resolve));
+ ok(SocialShare.shareButton && !SocialShare.shareButton.disabled, "Sharing is enabled");
+});
+
+add_task(function* test_link() {
+ // gets hidden for this case.
+ yield test_contextmenu("#link",
+ ["context-openlinkintab", true,
+ ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
+ // We need a blank entry here because the containers submenu is
+ // dynamically generated with no ids.
+ ...(hasContainers ? ["", null] : []),
+ "context-openlink", true,
+ "context-openlinkprivate", true,
+ "---", null,
+ "context-savelink", true,
+ "context-copylink", true,
+ "context-searchselect", true]);
+});
+
+add_task(function* test_video() {
+ yield test_contextmenu("#video",
+ ["context-media-play", null,
+ "context-media-mute", null,
+ "context-media-playbackrate", null,
+ ["context-media-playbackrate-050x", null,
+ "context-media-playbackrate-100x", null,
+ "context-media-playbackrate-125x", null,
+ "context-media-playbackrate-150x", null,
+ "context-media-playbackrate-200x", null], null,
+ "context-media-loop", null,
+ "context-media-showcontrols", null,
+ "context-video-fullscreen", null,
+ "---", null,
+ "context-viewvideo", null,
+ "context-copyvideourl", null,
+ "---", null,
+ "context-savevideo", null,
+ "context-sharevideo", false,
+ "context-video-saveimage", null,
+ "context-sendvideo", null,
+ "context-castvideo", null,
+ [], null
+ ]);
+});
+
+add_task(function* test_cleanup() {
+ lastElementSelector = null;
+ yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ yield new Promise((resolve) => {
+ return SocialService.disableProvider(manifest.origin, resolve);
+ });
+});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/contextMenu/subtst_contextmenu_webext.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Subtest for browser context menu</title>
+</head>
+<body>
+ Browser context menu subtest.
+ <a href="moz-extension://foo-bar/tab.html" id="link">Link to an extension resource</a>
+ <video src="moz-extension://foo-bar/video.ogg" id="video"></video>
+</body>
+</html>
--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -12,16 +12,17 @@ MOCHITEST_MANIFESTS += [
MOCHITEST_CHROME_MANIFESTS += [
'content/test/chrome/chrome.ini',
]
BROWSER_CHROME_MANIFESTS += [
'content/test/alerts/browser.ini',
'content/test/captivePortal/browser.ini',
+ 'content/test/contextMenu/browser.ini',
'content/test/forms/browser.ini',
'content/test/general/browser.ini',
'content/test/newtab/browser.ini',
'content/test/pageinfo/browser.ini',
'content/test/permissions/browser.ini',
'content/test/plugins/browser.ini',
'content/test/popupNotifications/browser.ini',
'content/test/popups/browser.ini',
--- a/browser/components/extensions/ExtensionPopups.jsm
+++ b/browser/components/extensions/ExtensionPopups.jsm
@@ -228,16 +228,17 @@ class BasePopup {
let document = viewNode.ownerDocument;
let browser = document.createElementNS(XUL_NS, "browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
browser.setAttribute("transparent", "true");
browser.setAttribute("class", "webextension-popup-browser");
browser.setAttribute("webextension-view-type", "popup");
browser.setAttribute("tooltip", "aHTMLTooltip");
+ browser.setAttribute("contextmenu", "contentAreaContextMenu");
if (this.extension.remote) {
browser.setAttribute("remote", "true");
browser.setAttribute("remoteType", E10SUtils.EXTENSION_REMOTE_TYPE);
}
// We only need flex sizing for the sake of the slide-in sub-views of the
// main menu panel, so that the browser occupies the full width of the view,
@@ -281,16 +282,19 @@ class BasePopup {
}
return setupBrowser(browser);
}
return readyPromise.then(() => {
setupBrowser(browser);
let mm = browser.messageManager;
+ // Sets the context information for context menus.
+ mm.loadFrameScript("chrome://browser/content/content.js", true);
+
mm.loadFrameScript(
"chrome://extensions/content/ext-browser-content.js", false);
mm.sendAsyncMessage("Extension:InitBrowser", {
allowScriptsToClose: true,
blockParser: this.blockParser,
fixedWidth: this.fixedWidth,
maxWidth: 800,
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -26,16 +26,17 @@ support-files =
webNav_createdTargetSource_subframe.html
serviceWorker.js
searchSuggestionEngine.xml
searchSuggestionEngine.sjs
../../../../../toolkit/components/extensions/test/mochitest/head_webrequest.js
[browser_ext_browserAction_area.js]
[browser_ext_browserAction_context.js]
+[browser_ext_browserAction_contextMenu.js]
[browser_ext_browserAction_disabled.js]
[browser_ext_browserAction_pageAction_icon.js]
[browser_ext_browserAction_pageAction_icon_permissions.js]
[browser_ext_browserAction_popup.js]
[browser_ext_browserAction_popup_preload.js]
[browser_ext_browserAction_popup_resize.js]
[browser_ext_browserAction_simple.js]
[browser_ext_browsingData_formData.js]
@@ -68,16 +69,17 @@ support-files =
[browser_ext_incognito_views.js]
[browser_ext_incognito_popup.js]
[browser_ext_lastError.js]
[browser_ext_omnibox.js]
skip-if = debug || asan # Bug 1354681
[browser_ext_optionsPage_browser_style.js]
[browser_ext_optionsPage_privileges.js]
[browser_ext_pageAction_context.js]
+[browser_ext_pageAction_contextMenu.js]
[browser_ext_pageAction_popup.js]
[browser_ext_pageAction_popup_resize.js]
[browser_ext_pageAction_simple.js]
[browser_ext_pageAction_title.js]
[browser_ext_popup_api_injection.js]
[browser_ext_popup_background.js]
[browser_ext_popup_corners.js]
[browser_ext_popup_sendMessage.js]
@@ -88,16 +90,17 @@ skip-if = debug || asan # Bug 1354681
[browser_ext_sessions_forgetClosedTab.js]
[browser_ext_sessions_forgetClosedWindow.js]
[browser_ext_sessions_getRecentlyClosed.js]
[browser_ext_sessions_getRecentlyClosed_private.js]
[browser_ext_sessions_getRecentlyClosed_tabs.js]
[browser_ext_sessions_restore.js]
[browser_ext_sidebarAction.js]
[browser_ext_sidebarAction_context.js]
+[browser_ext_sidebarAction_contextMenu.js]
[browser_ext_sidebarAction_tabs.js]
[browser_ext_sidebarAction_windows.js]
[browser_ext_simple.js]
[browser_ext_tab_runtimeConnect.js]
[browser_ext_tabs_audio.js]
[browser_ext_tabs_captureVisibleTab.js]
[browser_ext_tabs_create.js]
[browser_ext_tabs_create_invalid_url.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_contextMenu.js
@@ -0,0 +1,106 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+let extData = {
+ manifest: {
+ "permissions": ["contextMenus"],
+ "browser_action": {
+ "default_popup": "popup.html",
+ },
+ },
+ useAddonManager: "temporary",
+
+ files: {
+ "popup.html": `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"/>
+ </head>
+ <body>
+ <span id="text">A Test Popup</span>
+ <img id="testimg" src="data:image/svg+xml,<svg></svg>" height="10" width="10">
+ </body></html>
+ `,
+ },
+
+ background: function() {
+ browser.contextMenus.create({
+ id: "clickme-page",
+ title: "Click me!",
+ contexts: ["all"],
+ });
+ },
+};
+
+let contextMenuItems = {
+ "context-navigation": "hidden",
+ "context-sep-navigation": "hidden",
+ "context-viewsource": "",
+ "context-viewinfo": "disabled",
+ "inspect-separator": "hidden",
+ "context-inspect": "hidden",
+ "context-bookmarkpage": "hidden",
+ "context-sharepage": "hidden",
+};
+
+add_task(function* browseraction_popup_contextmenu() {
+ let extension = ExtensionTestUtils.loadExtension(extData);
+ yield extension.startup();
+
+ yield clickBrowserAction(extension, window);
+
+ let contentAreaContextMenu = yield openContextMenuInPopup(extension);
+ let item = contentAreaContextMenu.getElementsByAttribute("label", "Click me!");
+ is(item.length, 1, "contextMenu item for page was found");
+ yield closeContextMenu(contentAreaContextMenu);
+
+ yield extension.unload();
+});
+
+add_task(function* browseraction_popup_contextmenu_hidden_items() {
+ let extension = ExtensionTestUtils.loadExtension(extData);
+ yield extension.startup();
+
+ yield clickBrowserAction(extension);
+
+ let contentAreaContextMenu = yield openContextMenuInPopup(extension, "#text");
+
+ let item, state;
+ for (const itemID in contextMenuItems) {
+ item = contentAreaContextMenu.querySelector(`#${itemID}`);
+ state = contextMenuItems[itemID];
+
+ if (state !== "") {
+ ok(item[state], `${itemID} is ${state}`);
+
+ if (state !== "hidden") {
+ ok(!item.hidden, `Disabled ${itemID} is not hidden`);
+ }
+ } else {
+ ok(!item.hidden, `${itemID} is not hidden`);
+ ok(!item.disabled, `${itemID} is not disabled`);
+ }
+ }
+
+ yield closeContextMenu(contentAreaContextMenu);
+
+ yield extension.unload();
+});
+
+add_task(function* browseraction_popup_image_contextmenu() {
+ let extension = ExtensionTestUtils.loadExtension(extData);
+ yield extension.startup();
+
+ yield clickBrowserAction(extension);
+
+ let contentAreaContextMenu = yield openContextMenuInPopup(extension, "#testimg");
+
+ let item = contentAreaContextMenu.querySelector("#context-viewimageinfo");
+ ok(!item.hidden);
+ ok(item.disabled);
+
+ yield closeContextMenu(contentAreaContextMenu);
+
+ yield extension.unload();
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_contextMenu.js
@@ -0,0 +1,116 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+let extData = {
+ manifest: {
+ "permissions": ["contextMenus"],
+ "page_action": {
+ "default_popup": "popup.html",
+ },
+ },
+ useAddonManager: "temporary",
+
+ files: {
+ "popup.html": `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"/>
+ </head>
+ <body>
+ <span id="text">A Test Popup</span>
+ <img id="testimg" src="data:image/svg+xml,<svg></svg>" height="10" width="10">
+ </body></html>
+ `,
+ },
+
+ background: function() {
+ browser.contextMenus.create({
+ id: "clickme-page",
+ title: "Click me!",
+ contexts: ["all"],
+ });
+ browser.tabs.query({active: true, currentWindow: true}, tabs => {
+ const tabId = tabs[0].id;
+
+ browser.pageAction.show(tabId).then(() => {
+ browser.test.sendMessage("action-shown");
+ });
+ });
+ },
+};
+
+let contextMenuItems = {
+ "context-navigation": "hidden",
+ "context-sep-navigation": "hidden",
+ "context-viewsource": "",
+ "context-viewinfo": "disabled",
+ "inspect-separator": "hidden",
+ "context-inspect": "hidden",
+ "context-bookmarkpage": "hidden",
+ "context-sharepage": "hidden",
+};
+
+add_task(function* pageaction_popup_contextmenu() {
+ let extension = ExtensionTestUtils.loadExtension(extData);
+ yield extension.startup();
+ yield extension.awaitMessage("action-shown");
+
+ yield clickPageAction(extension, window);
+
+ let contentAreaContextMenu = yield openContextMenuInPopup(extension);
+ let item = contentAreaContextMenu.getElementsByAttribute("label", "Click me!");
+ is(item.length, 1, "contextMenu item for page was found");
+ yield closeContextMenu(contentAreaContextMenu);
+
+ yield extension.unload();
+});
+
+add_task(function* pageaction_popup_contextmenu_hidden_items() {
+ let extension = ExtensionTestUtils.loadExtension(extData);
+ yield extension.startup();
+ yield extension.awaitMessage("action-shown");
+
+ yield clickPageAction(extension, window);
+
+ let contentAreaContextMenu = yield openContextMenuInPopup(extension, "#text");
+
+ let item, state;
+ for (const itemID in contextMenuItems) {
+ item = contentAreaContextMenu.querySelector(`#${itemID}`);
+ state = contextMenuItems[itemID];
+
+ if (state !== "") {
+ ok(item[state], `${itemID} is ${state}`);
+
+ if (state !== "hidden") {
+ ok(!item.hidden, `Disabled ${itemID} is not hidden`);
+ }
+ } else {
+ ok(!item.hidden, `${itemID} is not hidden`);
+ ok(!item.disabled, `${itemID} is not disabled`);
+ }
+ }
+
+ yield closeContextMenu(contentAreaContextMenu);
+
+ yield extension.unload();
+});
+
+add_task(function* pageaction_popup_image_contextmenu() {
+ let extension = ExtensionTestUtils.loadExtension(extData);
+ yield extension.startup();
+ yield extension.awaitMessage("action-shown");
+
+ yield clickPageAction(extension, window);
+
+ let contentAreaContextMenu = yield openContextMenuInPopup(extension, "#testimg");
+
+ let item = contentAreaContextMenu.querySelector("#context-viewimageinfo");
+ ok(!item.hidden);
+ ok(item.disabled);
+
+ yield closeContextMenu(contentAreaContextMenu);
+
+ yield extension.unload();
+});
--- a/browser/components/extensions/test/browser/browser_ext_sidebarAction.js
+++ b/browser/components/extensions/test/browser/browser_ext_sidebarAction.js
@@ -1,15 +1,14 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
let extData = {
manifest: {
- "permissions": ["contextMenus"],
"sidebar_action": {
"default_panel": "sidebar.html",
},
},
useAddonManager: "temporary",
files: {
"sidebar.html": `
@@ -26,22 +25,16 @@ let extData = {
"sidebar.js": function() {
window.onload = () => {
browser.test.sendMessage("sidebar");
};
},
},
background: function() {
- browser.contextMenus.create({
- id: "clickme-page",
- title: "Click me!",
- contexts: ["all"],
- });
-
browser.test.onMessage.addListener(msg => {
if (msg === "set-panel") {
browser.sidebarAction.setPanel({panel: ""}).then(() => {
browser.test.notifyFail("empty panel settable");
}).catch(() => {
browser.test.notifyPass("unable to set empty panel");
});
}
@@ -98,26 +91,12 @@ add_task(function* sidebar_empty_panel()
// Test sidebar is opened on install
yield extension.awaitMessage("sidebar");
ok(!document.getElementById("sidebar-box").hidden, "sidebar box is visible in first window");
extension.sendMessage("set-panel");
yield extension.awaitFinish();
yield extension.unload();
});
-add_task(function* sidebar_contextmenu() {
- let extension = ExtensionTestUtils.loadExtension(extData);
- yield extension.startup();
- // Test sidebar is opened on install
- yield extension.awaitMessage("sidebar");
-
- let contentAreaContextMenu = yield openContextMenuInSidebar();
- let item = contentAreaContextMenu.getElementsByAttribute("label", "Click me!");
- is(item.length, 1, "contextMenu item for page was found");
- yield closeContextMenu(contentAreaContextMenu);
-
- yield extension.unload();
-});
-
add_task(function* cleanup() {
// This is set on initial sidebar install.
Services.prefs.clearUserPref("extensions.sidebar-button.shown");
});
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_sidebarAction_contextMenu.js
@@ -0,0 +1,119 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+let extData = {
+ manifest: {
+ "permissions": ["contextMenus"],
+ "sidebar_action": {
+ "default_panel": "sidebar.html",
+ },
+ },
+ useAddonManager: "temporary",
+
+ files: {
+ "sidebar.html": `
+ <!DOCTYPE html>
+ <html>
+ <head><meta charset="utf-8"/>
+ <script src="sidebar.js"></script>
+ </head>
+ <body>
+ <span id="text">A Test Sidebar</span>
+ <img id="testimg" src="data:image/svg+xml,<svg></svg>" height="10" width="10">
+ </body></html>
+ `,
+
+ "sidebar.js": function() {
+ window.onload = () => {
+ browser.test.sendMessage("sidebar");
+ };
+ },
+ },
+
+ background: function() {
+ browser.contextMenus.create({
+ id: "clickme-page",
+ title: "Click me!",
+ contexts: ["all"],
+ });
+ },
+};
+
+let contextMenuItems = {
+ "context-navigation": "hidden",
+ "context-sep-navigation": "hidden",
+ "context-viewsource": "",
+ "context-viewinfo": "",
+ "inspect-separator": "hidden",
+ "context-inspect": "hidden",
+ "context-bookmarkpage": "hidden",
+ "context-sharepage": "hidden",
+};
+
+add_task(function* sidebar_contextmenu() {
+ let extension = ExtensionTestUtils.loadExtension(extData);
+ yield extension.startup();
+ // Test sidebar is opened on install
+ yield extension.awaitMessage("sidebar");
+
+ let contentAreaContextMenu = yield openContextMenuInSidebar();
+ let item = contentAreaContextMenu.getElementsByAttribute("label", "Click me!");
+ is(item.length, 1, "contextMenu item for page was found");
+ yield closeContextMenu(contentAreaContextMenu);
+
+ yield extension.unload();
+});
+
+
+add_task(function* sidebar_contextmenu_hidden_items() {
+ let extension = ExtensionTestUtils.loadExtension(extData);
+ yield extension.startup();
+ // Test sidebar is opened on install
+ yield extension.awaitMessage("sidebar");
+
+ let contentAreaContextMenu = yield openContextMenuInSidebar("#text");
+
+ let item, state;
+ for (const itemID in contextMenuItems) {
+ item = contentAreaContextMenu.querySelector(`#${itemID}`);
+ state = contextMenuItems[itemID];
+
+ if (state !== "") {
+ ok(item[state], `${itemID} is ${state}`);
+
+ if (state !== "hidden") {
+ ok(!item.hidden, `Disabled ${itemID} is not hidden`);
+ }
+ } else {
+ ok(!item.hidden, `${itemID} is not hidden`);
+ ok(!item.disabled, `${itemID} is not disabled`);
+ }
+ }
+
+ yield closeContextMenu(contentAreaContextMenu);
+
+ yield extension.unload();
+});
+
+add_task(function* sidebar_image_contextmenu() {
+ let extension = ExtensionTestUtils.loadExtension(extData);
+ yield extension.startup();
+ // Test sidebar is opened on install
+ yield extension.awaitMessage("sidebar");
+
+ let contentAreaContextMenu = yield openContextMenuInSidebar("#testimg");
+
+ let item = contentAreaContextMenu.querySelector("#context-viewimageinfo");
+ ok(!item.hidden);
+ ok(!item.disabled);
+
+ yield closeContextMenu(contentAreaContextMenu);
+
+ yield extension.unload();
+});
+
+add_task(function* cleanup() {
+ // This is set on initial sidebar install.
+ Services.prefs.clearUserPref("extensions.sidebar-button.shown");
+});
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -3,17 +3,18 @@
"use strict";
/* exported CustomizableUI makeWidgetId focusWindow forceGC
* getBrowserActionWidget
* clickBrowserAction clickPageAction
* getBrowserActionPopup getPageActionPopup
* closeBrowserAction closePageAction
* promisePopupShown promisePopupHidden
- * openContextMenu closeContextMenu openContextMenuInSidebar
+ * openContextMenu closeContextMenu
+ * openContextMenuInSidebar openContextMenuInPopup
* openExtensionContextMenu closeExtensionContextMenu
* openActionContextMenu openSubmenu closeActionContextMenu
* openTabContextMenu closeTabContextMenu
* imageBuffer imageBufferFromDataURI
* getListStyleImage getPanelForNode
* awaitExtensionPanel awaitPopupResize
* promiseContentDimensions alterContent
* promisePrefChangeObserved openContextMenuInFrame
@@ -227,16 +228,26 @@ function closeBrowserAction(extension, w
let group = getBrowserActionWidget(extension);
let node = win.document.getElementById(group.viewId);
CustomizableUI.hidePanelForNode(node);
return Promise.resolve();
}
+async function openContextMenuInPopup(extension, selector = "body") {
+ let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
+ let browser = await awaitExtensionPanel(extension);
+ let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
+ await BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "mousedown", button: 2}, browser);
+ await BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "contextmenu"}, browser);
+ await popupShownPromise;
+ return contentAreaContextMenu;
+}
+
async function openContextMenuInSidebar(selector = "body") {
let contentAreaContextMenu = SidebarUI.browser.contentDocument.getElementById("contentAreaContextMenu");
let browser = SidebarUI.browser.contentDocument.getElementById("webext-panels-browser");
let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "mousedown", button: 2}, browser);
await BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "contextmenu"}, browser);
await popupShownPromise;
return contentAreaContextMenu;