From 086c044dc34dfc0f74fbe41f4ecb402b2cd34884 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:13:33 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- dom/security/test/general/browser.toml | 10 + .../browser_restrict_privileged_about_script.js | 2 +- .../test/general/browser_test_data_download.js | 4 +- .../test/general/browser_test_data_text_csv.js | 4 +- .../test/general/browser_test_http_download.js | 275 +++++++++++++++++++++ .../test/general/browser_test_report_blocking.js | 2 +- .../browser_test_toplevel_data_navigations.js | 2 +- .../browser_test_view_image_data_navigation.js | 4 +- dom/security/test/general/http_download_page.html | 23 ++ dom/security/test/general/http_download_server.sjs | 20 ++ .../test/general/test_block_script_wrong_mime.html | 6 +- .../test_block_toplevel_data_navigation.html | 2 +- dom/security/test/general/test_bug1277803.xhtml | 2 +- ...est_contentpolicytype_targeted_link_iframe.html | 2 +- dom/security/test/general/test_meta_referrer.html | 2 +- .../general/test_same_site_cookies_subrequest.html | 2 +- .../test_same_site_cookies_toplevel_nav.html | 2 +- 17 files changed, 346 insertions(+), 18 deletions(-) create mode 100644 dom/security/test/general/browser_test_http_download.js create mode 100644 dom/security/test/general/http_download_page.html create mode 100644 dom/security/test/general/http_download_server.sjs (limited to 'dom/security/test/general') diff --git a/dom/security/test/general/browser.toml b/dom/security/test/general/browser.toml index 0f4ec5b224..c6d6b4bf79 100644 --- a/dom/security/test/general/browser.toml +++ b/dom/security/test/general/browser.toml @@ -48,6 +48,16 @@ support-files = [ "file_gpc_server.sjs", ] +["browser_test_http_download.js"] +skip-if = [ + "win11_2009", # Bug 1784764 + "os == 'linux' && !debug", +] +support-files = [ + "http_download_page.html", + "http_download_server.sjs" +] + ["browser_test_referrer_loadInOtherProcess.js"] ["browser_test_report_blocking.js"] diff --git a/dom/security/test/general/browser_restrict_privileged_about_script.js b/dom/security/test/general/browser_restrict_privileged_about_script.js index 0baa6e3d4d..7dfb6d691a 100644 --- a/dom/security/test/general/browser_restrict_privileged_about_script.js +++ b/dom/security/test/general/browser_restrict_privileged_about_script.js @@ -20,7 +20,7 @@ add_task(async function test_principal_click() { }); await BrowserTestUtils.withNewTab( "about:test-about-privileged-with-scripts", - async function (browser) { + async function () { // Wait for page to fully load info("Waiting for tab to be loaded.."); // let's look into the fully loaded about page diff --git a/dom/security/test/general/browser_test_data_download.js b/dom/security/test/general/browser_test_data_download.js index df5a8aeac4..9cebb97b30 100644 --- a/dom/security/test/general/browser_test_data_download.js +++ b/dom/security/test/general/browser_test_data_download.js @@ -22,13 +22,13 @@ function addWindowListener(aURL) { resolve(domwindow); }, domwindow); }, - onCloseWindow(aXULWindow) {}, + onCloseWindow() {}, }); }); } function waitDelay(delay) { - return new Promise((resolve, reject) => { + return new Promise(resolve => { /* eslint-disable mozilla/no-arbitrary-setTimeout */ window.setTimeout(resolve, delay); }); diff --git a/dom/security/test/general/browser_test_data_text_csv.js b/dom/security/test/general/browser_test_data_text_csv.js index 9855ddce46..b6c9f46336 100644 --- a/dom/security/test/general/browser_test_data_text_csv.js +++ b/dom/security/test/general/browser_test_data_text_csv.js @@ -6,7 +6,7 @@ const kTestPath = getRootDirectory(gTestPath).replace( ); const kTestURI = kTestPath + "file_data_text_csv.html"; -function addWindowListener(aURL, aCallback) { +function addWindowListener(aURL) { return new Promise(resolve => { Services.wm.addListener({ onOpenWindow(aXULWindow) { @@ -22,7 +22,7 @@ function addWindowListener(aURL, aCallback) { resolve(domwindow); }, domwindow); }, - onCloseWindow(aXULWindow) {}, + onCloseWindow() {}, }); }); } diff --git a/dom/security/test/general/browser_test_http_download.js b/dom/security/test/general/browser_test_http_download.js new file mode 100644 index 0000000000..35e3fdfc4b --- /dev/null +++ b/dom/security/test/general/browser_test_http_download.js @@ -0,0 +1,275 @@ +/* Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ */ + +ChromeUtils.defineESModuleGetters(this, { + Downloads: "resource://gre/modules/Downloads.sys.mjs", + DownloadsCommon: "resource:///modules/DownloadsCommon.sys.mjs", +}); + +const HandlerService = Cc[ + "@mozilla.org/uriloader/handler-service;1" +].getService(Ci.nsIHandlerService); + +const MIMEService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService); + +// Using insecure HTTP URL for a test cases around HTTP downloads +let INSECURE_BASE_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content/", + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + "http://example.com/" + ) + "http_download_page.html"; + +function promiseFocus() { + return new Promise(resolve => { + waitForFocus(resolve); + }); +} + +async function task_openPanel() { + await promiseFocus(); + + let promise = BrowserTestUtils.waitForPopupEvent( + DownloadsPanel.panel, + "shown" + ); + DownloadsPanel.showPanel(); + await promise; +} + +const downloadMonitoringView = { + _listeners: [], + onDownloadAdded(download) { + for (let listener of this._listeners) { + listener(download); + } + this._listeners = []; + }, + waitForDownload(listener) { + this._listeners.push(listener); + }, +}; + +/** + * Waits until a download is triggered. + * Unless the always_ask_before_handling_new_types pref is true, the download + * will simply be saved, so resolve when the view is notified of the new + * download. Otherwise, it waits until a prompt is shown, selects the choosen + * , then accepts the dialog + * @param [action] Which action to select, either: + * "handleInternally", "save" or "open". + * @returns {Promise} Resolved once done. + */ + +function shouldTriggerDownload(action = "save") { + if ( + Services.prefs.getBoolPref( + "browser.download.always_ask_before_handling_new_types" + ) + ) { + return new Promise((resolve, reject) => { + Services.wm.addListener({ + onOpenWindow(xulWin) { + Services.wm.removeListener(this); + let win = xulWin.docShell.domWindow; + waitForFocus(() => { + if ( + win.location == + "chrome://mozapps/content/downloads/unknownContentType.xhtml" + ) { + let dialog = win.document.getElementById("unknownContentType"); + let button = dialog.getButton("accept"); + let actionRadio = win.document.getElementById(action); + actionRadio.click(); + button.disabled = false; + dialog.acceptDialog(); + resolve(); + } else { + reject(); + } + }, win); + }, + }); + }); + } + return new Promise(res => { + downloadMonitoringView.waitForDownload(res); + }); +} + +const CONSOLE_ERROR_MESSAGE = "We blocked a download that’s not secure"; + +function shouldConsoleError() { + // Waits until CONSOLE_ERROR_MESSAGE was logged + return new Promise((resolve, reject) => { + function listener(msgObj) { + let text = msgObj.message; + if (text.includes(CONSOLE_ERROR_MESSAGE)) { + Services.console.unregisterListener(listener); + resolve(); + } + } + Services.console.registerListener(listener); + }); +} + +async function resetDownloads() { + // Removes all downloads from the download List + const types = new Set(); + let publicList = await Downloads.getList(Downloads.PUBLIC); + let downloads = await publicList.getAll(); + for (let download of downloads) { + if (download.contentType) { + types.add(download.contentType); + } + publicList.remove(download); + await download.finalize(true); + } + + if (types.size) { + // reset handlers for the contentTypes of any files previously downloaded + for (let type of types) { + const mimeInfo = MIMEService.getFromTypeAndExtension(type, ""); + info("resetting handler for type: " + type); + HandlerService.remove(mimeInfo); + } + } +} + +function shouldNotifyDownloadUI() { + return new Promise(res => { + downloadMonitoringView.waitForDownload(async aDownload => { + let { error } = aDownload; + if ( + error.becauseBlockedByReputationCheck && + error.reputationCheckVerdict == Downloads.Error.BLOCK_VERDICT_INSECURE + ) { + // It's an insecure Download, now Check that it has been cleaned up properly + if ((await IOUtils.stat(aDownload.target.path)).size != 0) { + throw new Error(`Download target is not empty!`); + } + if ((await IOUtils.stat(aDownload.target.path)).size != 0) { + throw new Error(`Download partFile was not cleaned up properly`); + } + // Assert that the Referrer is presnt + if (!aDownload.source.referrerInfo) { + throw new Error("The Blocked download is missing the ReferrerInfo"); + } + + res(aDownload); + } else { + ok(false, "No error for download that was expected to error!"); + } + }); + }); +} + +async function runTest(url, link, checkFunction, description) { + await SpecialPowers.pushPrefEnv({ + set: [["dom.block_download_insecure", true]], + }); + await resetDownloads(); + + let tab = BrowserTestUtils.addTab(gBrowser, url); + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + info("Checking: " + description); + + let checkPromise = checkFunction(); + // Click the Link to trigger the download + SpecialPowers.spawn(gBrowser.selectedBrowser, [link], contentLink => { + content.document.getElementById(contentLink).click(); + }); + + await checkPromise; + + ok(true, description); + BrowserTestUtils.removeTab(tab); + + await SpecialPowers.popPrefEnv(); +} + +add_setup(async () => { + let list = await Downloads.getList(Downloads.ALL); + list.addView(downloadMonitoringView); + registerCleanupFunction(() => list.removeView(downloadMonitoringView)); +}); + +// Test Blocking +add_task(async function test_blocking() { + for (let prefVal of [true, false]) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.download.always_ask_before_handling_new_types", prefVal]], + }); + await runTest( + INSECURE_BASE_URL, + "http-link", + () => + Promise.all([ + shouldTriggerDownload(), + shouldNotifyDownloadUI(), + shouldConsoleError(), + ]), + "Insecure (HTTP) toplevel -> Insecure (HTTP) download should Error" + ); + await SpecialPowers.popPrefEnv(); + } +}); + +// Test Manual Unblocking +add_task(async function test_manual_unblocking() { + for (let prefVal of [true, false]) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.download.always_ask_before_handling_new_types", prefVal]], + }); + await runTest( + INSECURE_BASE_URL, + "http-link", + async () => { + let [, download] = await Promise.all([ + shouldTriggerDownload(), + shouldNotifyDownloadUI(), + ]); + await download.unblock(); + Assert.equal( + download.error, + null, + "There should be no error after unblocking" + ); + }, + "A blocked download should succeed to download after a manual unblock" + ); + await SpecialPowers.popPrefEnv(); + } +}); + +// Test Unblock Download Visible +add_task(async function test_unblock_download_visible() { + for (let prefVal of [true, false]) { + await SpecialPowers.pushPrefEnv({ + set: [["browser.download.always_ask_before_handling_new_types", prefVal]], + }); + await promiseFocus(); + await runTest( + INSECURE_BASE_URL, + "http-link", + async () => { + let panelHasOpened = BrowserTestUtils.waitForPopupEvent( + DownloadsPanel.panel, + "shown" + ); + info("awaiting that the download is triggered and added to the list"); + await Promise.all([shouldTriggerDownload(), shouldNotifyDownloadUI()]); + info("awaiting that the Download list shows itself"); + await panelHasOpened; + DownloadsPanel.hidePanel(); + ok(true, "The Download Panel should have opened on blocked download"); + }, + "A blocked download should open the download panel" + ); + await SpecialPowers.popPrefEnv(); + } +}); diff --git a/dom/security/test/general/browser_test_report_blocking.js b/dom/security/test/general/browser_test_report_blocking.js index ebd7514097..ab66f1d836 100644 --- a/dom/security/test/general/browser_test_report_blocking.js +++ b/dom/security/test/general/browser_test_report_blocking.js @@ -108,7 +108,7 @@ async function testReporting(test) { return iframe.browsingContext; }); - await SpecialPowers.spawn(frameBC, [type], async obj => { + await SpecialPowers.spawn(frameBC, [type], async () => { // Wait until the reporting UI is visible. await ContentTaskUtils.waitForCondition(() => { let reportUI = content.document.getElementById("blockingErrorReporting"); diff --git a/dom/security/test/general/browser_test_toplevel_data_navigations.js b/dom/security/test/general/browser_test_toplevel_data_navigations.js index 0e006f1fd2..cf7c116eba 100644 --- a/dom/security/test/general/browser_test_toplevel_data_navigations.js +++ b/dom/security/test/general/browser_test_toplevel_data_navigations.js @@ -15,7 +15,7 @@ add_task(async function test_nav_data_uri() { await SpecialPowers.pushPrefEnv({ set: [["security.data_uri.block_toplevel_data_uri_navigations", true]], }); - await BrowserTestUtils.withNewTab(kDataURI, async function (browser) { + await BrowserTestUtils.withNewTab(kDataURI, async function () { await SpecialPowers.spawn( gBrowser.selectedBrowser, [{ kDataBody }], diff --git a/dom/security/test/general/browser_test_view_image_data_navigation.js b/dom/security/test/general/browser_test_view_image_data_navigation.js index 90aace1e3e..6e4173e343 100644 --- a/dom/security/test/general/browser_test_view_image_data_navigation.js +++ b/dom/security/test/general/browser_test_view_image_data_navigation.js @@ -8,7 +8,7 @@ add_task(async function test_principal_right_click_open_link_in_new_tab() { const TEST_PAGE = getRootDirectory(gTestPath) + "file_view_image_data_navigation.html"; - await BrowserTestUtils.withNewTab(TEST_PAGE, async function (browser) { + await BrowserTestUtils.withNewTab(TEST_PAGE, async function () { let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true); // simulate right-click->view-image @@ -43,7 +43,7 @@ add_task(async function test_right_click_open_bg_image() { const TEST_PAGE = getRootDirectory(gTestPath) + "file_view_bg_image_data_navigation.html"; - await BrowserTestUtils.withNewTab(TEST_PAGE, async function (browser) { + await BrowserTestUtils.withNewTab(TEST_PAGE, async function () { let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true); // simulate right-click->view-image diff --git a/dom/security/test/general/http_download_page.html b/dom/security/test/general/http_download_page.html new file mode 100644 index 0000000000..c5461eaed3 --- /dev/null +++ b/dom/security/test/general/http_download_page.html @@ -0,0 +1,23 @@ + + + + Test for the download attribute + + + hi + + + + diff --git a/dom/security/test/general/http_download_server.sjs b/dom/security/test/general/http_download_server.sjs new file mode 100644 index 0000000000..e659df2f40 --- /dev/null +++ b/dom/security/test/general/http_download_server.sjs @@ -0,0 +1,20 @@ +// force the Browser to Show a Download Prompt + +function handleRequest(request, response) { + let type = "image/png"; + let filename = "hello.png"; + request.queryString.split("&").forEach(val => { + var [key, value] = val.split("="); + if (key == "type") { + type = value; + } + if (key == "name") { + filename = value; + } + }); + + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Disposition", `attachment; filename=${filename}`); + response.setHeader("Content-Type", type); + response.write("πŸ™ˆπŸ™ŠπŸ΅πŸ™Š"); +} diff --git a/dom/security/test/general/test_block_script_wrong_mime.html b/dom/security/test/general/test_block_script_wrong_mime.html index 93a4b9d220..7122363dfc 100644 --- a/dom/security/test/general/test_block_script_wrong_mime.html +++ b/dom/security/test/general/test_block_script_wrong_mime.html @@ -25,7 +25,7 @@ const MIMETypes = [ //