summaryrefslogtreecommitdiffstats
path: root/dom/events/test/clipboard/browser_navigator_clipboard_readText_multiple.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/events/test/clipboard/browser_navigator_clipboard_readText_multiple.js')
-rw-r--r--dom/events/test/clipboard/browser_navigator_clipboard_readText_multiple.js316
1 files changed, 316 insertions, 0 deletions
diff --git a/dom/events/test/clipboard/browser_navigator_clipboard_readText_multiple.js b/dom/events/test/clipboard/browser_navigator_clipboard_readText_multiple.js
new file mode 100644
index 0000000000..1d0d2884b7
--- /dev/null
+++ b/dom/events/test/clipboard/browser_navigator_clipboard_readText_multiple.js
@@ -0,0 +1,316 @@
+/* -*- Mode: JavaScript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const kBaseUrlForContent = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "https://example.com"
+);
+const kContentFileName = "file_toplevel.html";
+const kContentFileUrl = kBaseUrlForContent + kContentFileName;
+
+async function waitForPasteContextMenu() {
+ await waitForPasteMenuPopupEvent("shown");
+ const pasteButton = document.getElementById(kPasteMenuItemId);
+ info("Wait for paste button enabled");
+ await BrowserTestUtils.waitForMutationCondition(
+ pasteButton,
+ { attributeFilter: ["disabled"] },
+ () => !pasteButton.disabled,
+ "Wait for paste button enabled"
+ );
+}
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.events.asyncClipboard.readText", true],
+ ["test.events.async.enabled", true],
+ // Avoid paste button delay enabling making test too long.
+ ["security.dialog_enable_delay", 0],
+ ],
+ });
+});
+
+add_task(async function test_multiple_readText_from_same_frame_allow() {
+ // Randomized text to avoid overlapping with other tests.
+ const clipboardText = await promiseWritingRandomTextToClipboard();
+
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
+ const pasteButtonIsShown = waitForPasteContextMenu();
+ const readTextRequest1 = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ });
+ await pasteButtonIsShown;
+
+ info("readText() from same frame again before interact with paste button");
+ const readTextRequest2 = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ });
+ // Give some time for the second request to arrive parent process.
+ await SpecialPowers.spawn(browser, [], async () => {
+ return new Promise(resolve => {
+ content.setTimeout(resolve, 0);
+ });
+ });
+
+ info("Click paste button, both request should be resolved");
+ await promiseClickPasteButton();
+ is(
+ await readTextRequest1,
+ clipboardText,
+ "First request should be resolved"
+ );
+ is(
+ await readTextRequest2,
+ clipboardText,
+ "Second request should be resolved"
+ );
+ });
+});
+
+add_task(async function test_multiple_readText_from_same_frame_deny() {
+ // Randomized text to avoid overlapping with other tests.
+ const clipboardText = await promiseWritingRandomTextToClipboard();
+
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
+ const pasteButtonIsShown = waitForPasteContextMenu();
+ const readTextRequest1 = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ });
+ await pasteButtonIsShown;
+
+ info("readText() from same frame again before interact with paste button");
+ const readTextRequest2 = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ });
+ // Give some time for the second request to arrive parent process.
+ await SpecialPowers.spawn(browser, [], async () => {
+ return new Promise(resolve => {
+ content.setTimeout(resolve, 0);
+ });
+ });
+
+ info("Dismiss paste button, both request should be rejected");
+ await promiseDismissPasteButton();
+ await Assert.rejects(
+ readTextRequest1,
+ /NotAllowedError/,
+ "First request should be rejected"
+ );
+ await Assert.rejects(
+ readTextRequest2,
+ /NotAllowedError/,
+ "Second request should be rejected"
+ );
+ });
+});
+
+add_task(async function test_multiple_readText_from_same_origin_frame() {
+ // Randomized text to avoid overlapping with other tests.
+ const clipboardText = await promiseWritingRandomTextToClipboard();
+
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
+ const pasteButtonIsShown = waitForPasteContextMenu();
+ const readTextRequest1 = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ });
+ await pasteButtonIsShown;
+
+ info(
+ "readText() from same origin child frame again before interacting with paste button"
+ );
+ const sameOriginFrame = browser.browsingContext.children[0];
+ const readTextRequest2 = SpecialPowers.spawn(
+ sameOriginFrame,
+ [],
+ async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ }
+ );
+ // Give some time for the second request to arrive parent process.
+ await SpecialPowers.spawn(sameOriginFrame, [], async () => {
+ return new Promise(resolve => {
+ content.setTimeout(resolve, 0);
+ });
+ });
+
+ info("Click paste button, both request should be resolved");
+ await promiseClickPasteButton();
+ is(
+ await readTextRequest1,
+ clipboardText,
+ "First request should be resolved"
+ );
+ is(
+ await readTextRequest2,
+ clipboardText,
+ "Second request should be resolved"
+ );
+ });
+});
+
+add_task(async function test_multiple_readText_from_cross_origin_frame() {
+ // Randomized text to avoid overlapping with other tests.
+ const clipboardText = await promiseWritingRandomTextToClipboard();
+
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
+ const pasteButtonIsShown = waitForPasteContextMenu();
+ const readTextRequest1 = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ });
+ await pasteButtonIsShown;
+
+ info(
+ "readText() from different origin child frame again before interacting with paste button"
+ );
+ const crossOriginFrame = browser.browsingContext.children[1];
+ await Assert.rejects(
+ SpecialPowers.spawn(crossOriginFrame, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ }),
+ /NotAllowedError/,
+ "Second request should be rejected"
+ );
+
+ info("Click paste button, both request should be resolved");
+ await promiseClickPasteButton();
+ is(
+ await readTextRequest1,
+ clipboardText,
+ "First request should be resolved"
+ );
+ });
+});
+
+add_task(async function test_multiple_readText_from_background_frame() {
+ // Randomized text to avoid overlapping with other tests.
+ const clipboardText = await promiseWritingRandomTextToClipboard();
+
+ const backgroundTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ kContentFileUrl
+ );
+
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
+ const pasteButtonIsShown = waitForPasteContextMenu();
+ const readTextRequest1 = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ });
+ await pasteButtonIsShown;
+
+ info(
+ "readText() from background tab again before interact with paste button"
+ );
+ await Assert.rejects(
+ SpecialPowers.spawn(backgroundTab.linkedBrowser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ }),
+ /NotAllowedError/,
+ "Second request should be rejected"
+ );
+
+ info("Click paste button, both request should be resolved");
+ await promiseClickPasteButton();
+ is(
+ await readTextRequest1,
+ clipboardText,
+ "First request should be resolved"
+ );
+ });
+
+ await BrowserTestUtils.removeTab(backgroundTab);
+});
+
+add_task(async function test_multiple_readText_from_background_window() {
+ // Randomized text to avoid overlapping with other tests.
+ const clipboardText = await promiseWritingRandomTextToClipboard();
+
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
+ const newWin = await BrowserTestUtils.openNewBrowserWindow();
+ const backgroundTab = await BrowserTestUtils.openNewForegroundTab(
+ newWin.gBrowser,
+ kContentFileUrl
+ );
+ await SimpleTest.promiseFocus(browser);
+
+ info("readText() from background window");
+ await Assert.rejects(
+ SpecialPowers.spawn(backgroundTab.linkedBrowser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ }),
+ /NotAllowedError/,
+ "Request from background window should be rejected"
+ );
+
+ const pasteButtonIsShown = waitForPasteContextMenu();
+ const readTextRequest1 = SpecialPowers.spawn(browser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ });
+ await pasteButtonIsShown;
+
+ info(
+ "readText() from background window again before interact with paste button"
+ );
+ await Assert.rejects(
+ SpecialPowers.spawn(backgroundTab.linkedBrowser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ }),
+ /NotAllowedError/,
+ "Second request should be rejected"
+ );
+
+ info("Click paste button, both request should be resolved");
+ await promiseClickPasteButton();
+ is(
+ await readTextRequest1,
+ clipboardText,
+ "First request should be resolved"
+ );
+
+ await BrowserTestUtils.closeWindow(newWin);
+ });
+});
+
+add_task(async function test_multiple_readText_focuse_in_chrome_document() {
+ // Randomized text to avoid overlapping with other tests.
+ const clipboardText = await promiseWritingRandomTextToClipboard();
+
+ const win = await BrowserTestUtils.openNewBrowserWindow();
+ const tab = await BrowserTestUtils.openNewForegroundTab(
+ win.gBrowser,
+ kContentFileUrl
+ );
+
+ info("Move focus to url bar");
+ win.gURLBar.focus();
+
+ info("readText() from web content");
+ await Assert.rejects(
+ SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
+ content.document.notifyUserGestureActivation();
+ return content.eval(`navigator.clipboard.readText();`);
+ }),
+ /NotAllowedError/,
+ "Request should be rejected when focus is not in content"
+ );
+
+ await BrowserTestUtils.closeWindow(win);
+});