summaryrefslogtreecommitdiffstats
path: root/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js')
-rw-r--r--dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js163
1 files changed, 156 insertions, 7 deletions
diff --git a/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js b/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js
index f504e499c9..97066cd2eb 100644
--- a/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js
+++ b/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_suppression.js
@@ -238,16 +238,10 @@ add_task(async function test_context_menu_suppression_image() {
await pasteButtonIsShown;
info("Test read from same-origin frame before paste contextmenu is closed");
- const clipboarCacheEnabled = SpecialPowers.getBoolPref(
- "widget.clipboard.use-cached-data.enabled",
- false
- );
// If the cached data is used, it uses type order in cached transferable.
SimpleTest.isDeeply(
await readTypes(browser.browsingContext.children[0]),
- clipboarCacheEnabled
- ? ["text/plain", "text/html", "image/png"]
- : ["text/html", "text/plain", "image/png"],
+ ["text/html", "text/plain", "image/png"],
"read from same-origin should just be resolved without showing paste contextmenu shown"
);
@@ -262,3 +256,158 @@ add_task(async function test_context_menu_suppression_image() {
);
});
});
+
+function testPasteContextMenuSuppressionPasteEvent(
+ aTriggerPasteFun,
+ aSuppress,
+ aMsg
+) {
+ add_task(async function test_context_menu_suppression_paste_event() {
+ await BrowserTestUtils.withNewTab(
+ kContentFileUrl,
+ async function (browser) {
+ info(`Write data by in cross-origin frame`);
+ const clipboardText = "X" + Math.random();
+ await SpecialPowers.spawn(
+ browser.browsingContext.children[1],
+ [clipboardText],
+ async text => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.writeText("${text}");`);
+ }
+ );
+
+ info("Test read should show contextmenu");
+ let pasteButtonIsShown = waitForPasteContextMenu();
+ let readTextRequest = readText(browser);
+ await pasteButtonIsShown;
+
+ info("Click paste button, request should be resolved");
+ await promiseClickPasteButton();
+ is(await readTextRequest, clipboardText, "Request should be resolved");
+
+ info("Test read in paste event handler");
+ readTextRequest = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`
+ (() => {
+ return new Promise(resolve => {
+ document.addEventListener("paste", function(e) {
+ e.preventDefault();
+ resolve(navigator.clipboard.readText());
+ }, { once: true });
+ });
+ })();
+ `);
+ });
+
+ if (aSuppress) {
+ let listener = function (e) {
+ if (e.target.getAttribute("id") == kPasteMenuPopupId) {
+ ok(!aSuppress, "paste contextmenu should not be shown");
+ }
+ };
+ document.addEventListener("popupshown", listener);
+ info(`Trigger paste event by ${aMsg}`);
+ // trigger paste event
+ await aTriggerPasteFun(browser);
+ is(
+ await readTextRequest,
+ clipboardText,
+ "Request should be resolved"
+ );
+ document.removeEventListener("popupshown", listener);
+ } else {
+ let pasteButtonIsShown = waitForPasteContextMenu();
+ info(
+ `Trigger paste event by ${aMsg}, read should still show contextmenu`
+ );
+ // trigger paste event
+ await aTriggerPasteFun(browser);
+ await pasteButtonIsShown;
+
+ info("Click paste button, request should be resolved");
+ await promiseClickPasteButton();
+ is(
+ await readTextRequest,
+ clipboardText,
+ "Request should be resolved"
+ );
+ }
+
+ info("Test read should still show contextmenu");
+ pasteButtonIsShown = waitForPasteContextMenu();
+ readTextRequest = readText(browser);
+ await pasteButtonIsShown;
+
+ info("Click paste button, request should be resolved");
+ await promiseClickPasteButton();
+ is(await readTextRequest, clipboardText, "Request should be resolved");
+ }
+ );
+ });
+}
+
+// If platform supports selection clipboard, the middle click paste the content
+// from selection clipboard instead, in such case, we don't suppress the
+// contextmenu when access global clipboard via async clipboard API.
+if (
+ !Services.clipboard.isClipboardTypeSupported(
+ Services.clipboard.kSelectionClipboard
+ )
+) {
+ testPasteContextMenuSuppressionPasteEvent(
+ async browser => {
+ await SpecialPowers.pushPrefEnv({
+ set: [["middlemouse.paste", true]],
+ });
+
+ await SpecialPowers.spawn(browser, [], async () => {
+ EventUtils.synthesizeMouse(
+ content.document.documentElement,
+ 1,
+ 1,
+ { button: 1 },
+ content.window
+ );
+ });
+ },
+ true,
+ "middle click"
+ );
+}
+
+testPasteContextMenuSuppressionPasteEvent(
+ async browser => {
+ await EventUtils.synthesizeAndWaitKey(
+ "v",
+ kIsMac ? { accelKey: true } : { ctrlKey: true }
+ );
+ },
+ true,
+ "keyboard shortcut"
+);
+
+testPasteContextMenuSuppressionPasteEvent(
+ async browser => {
+ await SpecialPowers.spawn(browser, [], async () => {
+ return SpecialPowers.doCommand(content.window, "cmd_paste");
+ });
+ },
+ true,
+ "paste command"
+);
+
+testPasteContextMenuSuppressionPasteEvent(
+ async browser => {
+ await SpecialPowers.spawn(browser, [], async () => {
+ let div = content.document.createElement("div");
+ div.setAttribute("contenteditable", "true");
+ content.document.documentElement.appendChild(div);
+ div.focus();
+ return SpecialPowers.doCommand(content.window, "cmd_pasteNoFormatting");
+ });
+ },
+ false,
+ "pasteNoFormatting command"
+);