diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /browser/extensions/screenshots/test | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/extensions/screenshots/test')
5 files changed, 199 insertions, 0 deletions
diff --git a/browser/extensions/screenshots/test/browser/.eslintrc.yml b/browser/extensions/screenshots/test/browser/.eslintrc.yml new file mode 100644 index 0000000000..f5cf5d3929 --- /dev/null +++ b/browser/extensions/screenshots/test/browser/.eslintrc.yml @@ -0,0 +1,5 @@ +env: + node: true + +extends: + - plugin:mozilla/browser-test diff --git a/browser/extensions/screenshots/test/browser/browser.ini b/browser/extensions/screenshots/test/browser/browser.ini new file mode 100644 index 0000000000..9c27b311fe --- /dev/null +++ b/browser/extensions/screenshots/test/browser/browser.ini @@ -0,0 +1,4 @@ +[browser_screenshots_injection.js] +support-files = injection-page.html +[browser_screenshots_ui_check.js] +skip-if = os == 'win' && debug # Bug 1394967 diff --git a/browser/extensions/screenshots/test/browser/browser_screenshots_injection.js b/browser/extensions/screenshots/test/browser/browser_screenshots_injection.js new file mode 100644 index 0000000000..571d7d6615 --- /dev/null +++ b/browser/extensions/screenshots/test/browser/browser_screenshots_injection.js @@ -0,0 +1,72 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_PATH = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" +); + +/** + * Check that web content cannot break into screenshots. + */ +add_task(async function test_inject_srcdoc() { + // If Screenshots was disabled, enable it just for this test. + const addon = await AddonManager.getAddonByID("screenshots@mozilla.org"); + const isEnabled = addon.enabled; + if (!isEnabled) { + await addon.enable({allowSystemAddons: true}); + registerCleanupFunction(async () => { + await addon.disable({allowSystemAddons: true}); + }); + } + + await BrowserTestUtils.withNewTab(TEST_PATH + "injection-page.html", + async (browser) => { + // Set up the content hijacking. Do this so we can see it without + // awaiting - the promise should never resolve. + let response = null; + let responsePromise = SpecialPowers.spawn(browser, [], () => { + return new Promise(resolve => { + // We can't pass `resolve` directly because of sandboxing. + // `responseHandler` gets invoked from the content page. + content.wrappedJSObject.responseHandler = Cu.exportFunction( + function(arg) { + resolve(arg) + }, + content + ); + }); + }).then( + r => { + ok(false, "Should not have gotten HTML but got: " + r); + response = r; + }, + () => { + // Do nothing - we expect this to error when the test finishes + // and the actor is destroyed, while the promise still hasn't + // been resolved. We need to catch it in order not to throw + // uncaught rejection errors and inadvertently fail the test. + } + ); + + let error; + let errorPromise = new Promise(resolve => { + SpecialPowers.registerConsoleListener(msg => { + if (msg.message?.match(/iframe URL does not match expected blank.html/)) { + error = msg; + resolve(); + } + }); + }); + + // Now try to start the screenshot flow: + document.querySelector("keyset[id*=screenshot] > key").doCommand(); + await Promise.race([errorPromise, responsePromise]); + ok(error, "Should get the relevant error: " + error?.message); + ok(!response, "Should not get a response from the webpage."); + + SpecialPowers.postConsoleSentinel(); + }); +}); diff --git a/browser/extensions/screenshots/test/browser/browser_screenshots_ui_check.js b/browser/extensions/screenshots/test/browser/browser_screenshots_ui_check.js new file mode 100644 index 0000000000..f77d6c32ea --- /dev/null +++ b/browser/extensions/screenshots/test/browser/browser_screenshots_ui_check.js @@ -0,0 +1,94 @@ +"use strict"; + +ChromeUtils.defineModuleGetter(this, "AddonManager", + "resource://gre/modules/AddonManager.jsm"); + +const BUTTON_ID = "pageAction-panel-screenshots_mozilla_org"; + +function checkElements(expectPresent, l) { + for (const id of l) { + is(!!document.getElementById(id), expectPresent, "element " + id + (expectPresent ? " is" : " is not") + " present"); + } +} + +async function togglePageActionPanel() { + await promiseOpenPageActionPanel(); + EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {}); + await promisePageActionPanelEvent("popuphidden"); +} + +function promiseOpenPageActionPanel() { + return BrowserTestUtils.waitForCondition(() => { + // Wait for the main page action button to become visible. It's hidden for + // some URIs, so depending on when this is called, it may not yet be quite + // visible. It's up to the caller to make sure it will be visible. + info("Waiting for main page action button to have non-0 size"); + const bounds = window.windowUtils.getBoundsWithoutFlushing(BrowserPageActions.mainButtonNode); + return bounds.width > 0 && bounds.height > 0; + }).then(() => { + // Wait for the panel to become open, by clicking the button if necessary. + info("Waiting for main page action panel to be open"); + if (BrowserPageActions.panelNode.state === "open") { + return Promise.resolve(); + } + const shownPromise = promisePageActionPanelEvent("popupshown"); + EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {}); + return shownPromise; + }).then(() => { + // Wait for items in the panel to become visible. + return promisePageActionViewChildrenVisible(BrowserPageActions.mainViewNode); + }); +} + +function promisePageActionPanelEvent(eventType) { + return new Promise(resolve => { + const panel = BrowserPageActions.panelNode; + if ((eventType === "popupshown" && panel.state === "open") || + (eventType === "popuphidden" && panel.state === "closed")) { + executeSoon(resolve); + return; + } + panel.addEventListener(eventType, () => { + executeSoon(resolve); + }, { once: true }); + }); +} + +function promisePageActionViewChildrenVisible(panelViewNode) { + info("promisePageActionViewChildrenVisible waiting for a child node to be visible"); + return BrowserTestUtils.waitForCondition(() => { + const bodyNode = panelViewNode.firstElementChild; + for (const childNode of bodyNode.children) { + const bounds = window.windowUtils.getBoundsWithoutFlushing(childNode); + if (bounds.width > 0 && bounds.height > 0) { + return true; + } + } + return false; + }); +} + +add_task(async function() { + // If Screenshots was disabled, enable it just for this test. + const addon = await AddonManager.getAddonByID("screenshots@mozilla.org"); + const isEnabled = addon.enabled; + if (!isEnabled) { + await addon.enable({allowSystemAddons: true}); + registerCleanupFunction(async () => { + await addon.disable({allowSystemAddons: true}); + }); + } + + // Toggle the page action panel to get it to rebuild itself. An actionable + // page must be opened first. + const url = "http://example.com/browser_screenshots_ui_check"; + await BrowserTestUtils.withNewTab(url, async () => { // eslint-disable-line space-before-function-paren + await togglePageActionPanel(); + + await BrowserTestUtils.waitForCondition( + () => document.getElementById(BUTTON_ID), + "Screenshots button should be present", 100, 100); + + checkElements(true, [BUTTON_ID]); + }); +}); diff --git a/browser/extensions/screenshots/test/browser/injection-page.html b/browser/extensions/screenshots/test/browser/injection-page.html new file mode 100644 index 0000000000..c7579aa8b5 --- /dev/null +++ b/browser/extensions/screenshots/test/browser/injection-page.html @@ -0,0 +1,24 @@ +<body> +<script> +let callback = function(mutationsList, observer) { + for (let mutation of mutationsList) { + let [added] = mutation.addedNodes; + if (added instanceof HTMLIFrameElement && added.id == "firefox-screenshots-preview-iframe") { + added.srcdoc = "<html></html>"; + // Now we have to wait for the doc to be populated. + let interval = setInterval(() => { + console.log(added.contentDocument.innerHTML); + if (added.contentDocument.body.innerHTML) { + clearInterval(interval); + window.responseHandler(added.contentDocument.body.innerHTML); + } + }, 100); + observer.disconnect(); + } + } +}; + +observer = new MutationObserver(callback); +observer.observe(document.body, {childList: true}); +</script> +</body> |