diff options
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.js | 316 |
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); +}); |