From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- dom/fetch/tests/browser.ini | 23 +++ dom/fetch/tests/browser_blobFromFile.js | 64 ++++++++ ...owser_origin_trial_coep_credentialless_cache.js | 139 +++++++++++++++++ ...ser_origin_trial_coep_credentialless_fetch_1.js | 145 ++++++++++++++++++ ...ser_origin_trial_coep_credentialless_fetch_2.js | 145 ++++++++++++++++++ ...ser_origin_trial_coep_credentialless_fetch_3.js | 150 +++++++++++++++++++ ...wser_origin_trial_coep_credentialless_worker.js | 164 +++++++++++++++++++++ dom/fetch/tests/crashtests/1577196.html | 26 ++++ dom/fetch/tests/crashtests/1664514.html | 5 + dom/fetch/tests/crashtests/crashtests.list | 2 + dom/fetch/tests/crashtests/url.url | 5 + dom/fetch/tests/credentialless_resource.sjs | 21 +++ dom/fetch/tests/credentialless_worker.sjs | 25 ++++ dom/fetch/tests/mochitest.ini | 2 + dom/fetch/tests/open_credentialless_document.sjs | 28 ++++ dom/fetch/tests/store_header.sjs | 23 +++ dom/fetch/tests/test_ext_response_constructor.html | 47 ++++++ dom/fetch/tests/test_invalid_header_exception.html | 39 +++++ 18 files changed, 1053 insertions(+) create mode 100644 dom/fetch/tests/browser.ini create mode 100644 dom/fetch/tests/browser_blobFromFile.js create mode 100644 dom/fetch/tests/browser_origin_trial_coep_credentialless_cache.js create mode 100644 dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_1.js create mode 100644 dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_2.js create mode 100644 dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_3.js create mode 100644 dom/fetch/tests/browser_origin_trial_coep_credentialless_worker.js create mode 100644 dom/fetch/tests/crashtests/1577196.html create mode 100644 dom/fetch/tests/crashtests/1664514.html create mode 100644 dom/fetch/tests/crashtests/crashtests.list create mode 100644 dom/fetch/tests/crashtests/url.url create mode 100644 dom/fetch/tests/credentialless_resource.sjs create mode 100644 dom/fetch/tests/credentialless_worker.sjs create mode 100644 dom/fetch/tests/mochitest.ini create mode 100644 dom/fetch/tests/open_credentialless_document.sjs create mode 100644 dom/fetch/tests/store_header.sjs create mode 100644 dom/fetch/tests/test_ext_response_constructor.html create mode 100644 dom/fetch/tests/test_invalid_header_exception.html (limited to 'dom/fetch/tests') diff --git a/dom/fetch/tests/browser.ini b/dom/fetch/tests/browser.ini new file mode 100644 index 0000000000..6fd8244288 --- /dev/null +++ b/dom/fetch/tests/browser.ini @@ -0,0 +1,23 @@ +[DEFAULT] +[browser_blobFromFile.js] +[browser_origin_trial_coep_credentialless_fetch_1.js] +support-files = + open_credentialless_document.sjs + store_header.sjs +[browser_origin_trial_coep_credentialless_fetch_2.js] +support-files = + open_credentialless_document.sjs + store_header.sjs +[browser_origin_trial_coep_credentialless_fetch_3.js] +support-files = + open_credentialless_document.sjs + store_header.sjs +[browser_origin_trial_coep_credentialless_worker.js] +support-files = + open_credentialless_document.sjs + store_header.sjs + credentialless_worker.sjs +[browser_origin_trial_coep_credentialless_cache.js] +support-files = + open_credentialless_document.sjs + credentialless_resource.sjs diff --git a/dom/fetch/tests/browser_blobFromFile.js b/dom/fetch/tests/browser_blobFromFile.js new file mode 100644 index 0000000000..07a8c6669e --- /dev/null +++ b/dom/fetch/tests/browser_blobFromFile.js @@ -0,0 +1,64 @@ +add_task(async function test() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.tabs.remote.separateFileUriProcess", true]], + }); + + let fileData = ""; + for (var i = 0; i < 100; ++i) { + fileData += "hello world!"; + } + + let file = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIDirectoryService) + .QueryInterface(Ci.nsIProperties) + .get("ProfD", Ci.nsIFile); + file.append("file.txt"); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + + let outStream = Cc[ + "@mozilla.org/network/file-output-stream;1" + ].createInstance(Ci.nsIFileOutputStream); + outStream.init( + file, + 0x02 | 0x08 | 0x20, // write, create, truncate + 0o666, + 0 + ); + outStream.write(fileData, fileData.length); + outStream.close(); + + let fileHandler = Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService) + .getProtocolHandler("file") + .QueryInterface(Ci.nsIFileProtocolHandler); + + let fileURL = fileHandler.getURLSpecFromActualFile(file); + + info("Opening url: " + fileURL); + let tab = BrowserTestUtils.addTab(gBrowser, fileURL); + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + let blob = await SpecialPowers.spawn( + browser, + [file.leafName], + function (fileName) { + return new content.window.Promise(resolve => { + content.window + .fetch(fileName) + .then(r => r.blob()) + .then(blob => resolve(blob)); + }); + } + ); + + ok(File.isInstance(blob), "We have a file"); + + is(blob.size, file.fileSize, "The size matches"); + is(blob.name, file.leafName, "The name is correct"); + + file.remove(false); + + gBrowser.removeTab(tab); +}); diff --git a/dom/fetch/tests/browser_origin_trial_coep_credentialless_cache.js b/dom/fetch/tests/browser_origin_trial_coep_credentialless_cache.js new file mode 100644 index 0000000000..c9b72a3393 --- /dev/null +++ b/dom/fetch/tests/browser_origin_trial_coep_credentialless_cache.js @@ -0,0 +1,139 @@ +const TOP_LEVEL_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "open_credentialless_document.sjs"; + +const SAME_ORIGIN = "https://example.com"; +const CROSS_ORIGIN = "https://test1.example.com"; + +const RESOURCE_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://test1.example.com" + ) + "credentialless_resource.sjs"; + +async function store(storer, url, requestCredentialMode) { + await SpecialPowers.spawn( + storer.linkedBrowser, + [url, requestCredentialMode], + async function (url, requestCredentialMode) { + const cache = await content.caches.open("v1"); + const fetchRequest = new content.Request(url, { + mode: "no-cors", + credentials: requestCredentialMode, + }); + + const fetchResponse = await content.fetch(fetchRequest); + content.wrappedJSObject.console.log(fetchResponse.headers); + await cache.put(fetchRequest, fetchResponse); + } + ); +} + +async function retrieve(retriever, resourceURL) { + return await SpecialPowers.spawn( + retriever.linkedBrowser, + [resourceURL], + async function (url) { + const cache = await content.caches.open("v1"); + try { + await cache.match(url); + return "retrieved"; + } catch (error) { + return "error"; + } + } + ); +} + +async function testCache( + storer, + storeRequestCredentialMode, + resourceCOEP, + retriever, + expectation +) { + const resourceURL = RESOURCE_URL + "?" + resourceCOEP; + + await store(storer, resourceURL, storeRequestCredentialMode); + const result = await retrieve(retriever, resourceURL); + + is(result, expectation); +} + +add_task(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.tabs.remote.coep.credentialless", false], + ["dom.origin-trials.enabled", true], + ["dom.origin-trials.test-key.enabled", true], + ], + }); + + const noneTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + TOP_LEVEL_URL + ); + const requireCorpTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + TOP_LEVEL_URL + "?requirecorp" + ); + const credentiallessTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + TOP_LEVEL_URL + "?credentialless" + ); + + await testCache(noneTab, "include", "", noneTab, "retrieved"); + await testCache(noneTab, "include", "", credentiallessTab, "error"); + await testCache(noneTab, "omit", "", credentiallessTab, "retrieved"); + await testCache( + noneTab, + "include", + "corp_cross_origin", + credentiallessTab, + "retrieved" + ); + await testCache(noneTab, "include", "", requireCorpTab, "error"); + await testCache( + noneTab, + "include", + "corp_cross_origin", + requireCorpTab, + "retrieved" + ); + await testCache(credentiallessTab, "include", "", noneTab, "retrieved"); + await testCache( + credentiallessTab, + "include", + "", + credentiallessTab, + "retrieved" + ); + await testCache(credentiallessTab, "include", "", requireCorpTab, "error"); + await testCache( + requireCorpTab, + "include", + "corp_cross_origin", + noneTab, + "retrieved" + ); + await testCache( + requireCorpTab, + "include", + "corp_cross_origin", + credentiallessTab, + "retrieved" + ); + await testCache( + requireCorpTab, + "include", + "corp_cross_origin", + requireCorpTab, + "retrieved" + ); + + await BrowserTestUtils.removeTab(noneTab); + await BrowserTestUtils.removeTab(requireCorpTab); + await BrowserTestUtils.removeTab(credentiallessTab); +}); diff --git a/dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_1.js b/dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_1.js new file mode 100644 index 0000000000..773c15e72a --- /dev/null +++ b/dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_1.js @@ -0,0 +1,145 @@ +const TOP_LEVEL_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "open_credentialless_document.sjs"; + +const SAME_ORIGIN = "https://example.com"; +const CROSS_ORIGIN = "https://test1.example.com"; + +const GET_STATE_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "store_header.sjs?getstate"; + +async function addCookieToOrigin(origin) { + const fetchRequestURL = + getRootDirectory(gTestPath).replace("chrome://mochitests/content", origin) + + "store_header.sjs?addcookie"; + + const addcookieTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + fetchRequestURL + ); + + await SpecialPowers.spawn(addcookieTab.linkedBrowser, [], async function () { + content.document.cookie = "coep=credentialless; SameSite=None; Secure"; + }); + await BrowserTestUtils.removeTab(addcookieTab); +} + +async function testOrigin( + fetchOrigin, + isCredentialless, + useMetaTag, + fetchRequestMode, + fetchRequestCrendentials, + expectedCookieResult +) { + let params = []; + if (isCredentialless) { + params.push("credentialless"); + } + if (useMetaTag) { + params.push("meta"); + } + + let topLevelUrl = TOP_LEVEL_URL; + if (params.length) { + topLevelUrl += "?" + params.join("&"); + } + + const noCredentiallessTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + topLevelUrl + ); + + const fetchRequestURL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + fetchOrigin + ) + "store_header.sjs?checkheader"; + + await SpecialPowers.spawn( + noCredentiallessTab.linkedBrowser, + [ + !useMetaTag && isCredentialless, + fetchRequestURL, + fetchRequestMode, + fetchRequestCrendentials, + GET_STATE_URL, + expectedCookieResult, + ], + async function ( + sharedArrayBufferEnabled, + fetchRequestURL, + fetchRequestMode, + fetchRequestCrendentials, + getStateURL, + expectedCookieResult + ) { + if (sharedArrayBufferEnabled) { + ok(content.crossOriginIsolated); + } + // When store_header.sjs receives this request, it will store + // whether it has received the cookie as a shared state. + await content.fetch(fetchRequestURL, { + mode: fetchRequestMode, + credentials: fetchRequestCrendentials, + }); + + // This request is used to get the saved state from the + // previous fetch request. + const response = await content.fetch(getStateURL, { + mode: "cors", + }); + const text = await response.text(); + is(text, expectedCookieResult); + } + ); + + await BrowserTestUtils.removeTab(noCredentiallessTab); +} + +async function doTest( + origin, + fetchRequestMode, + fetchRequestCrendentials, + expectedCookieResultForNoCredentialless, + expectedCookieResultForCredentialless +) { + for (let credentialless of [true, false]) { + for (let meta of [true, false]) { + await testOrigin( + origin, + credentialless, + meta, + fetchRequestMode, + fetchRequestCrendentials, + credentialless + ? expectedCookieResultForCredentialless + : expectedCookieResultForNoCredentialless + ); + } + } +} + +add_task(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.tabs.remote.coep.credentialless", false], + ["dom.origin-trials.enabled", true], + ["dom.origin-trials.test-key.enabled", true], + ], + }); + + await addCookieToOrigin(SAME_ORIGIN); + await addCookieToOrigin(CROSS_ORIGIN); + + // Cookies never sent with omit + await doTest(SAME_ORIGIN, "no-cors", "omit", "noCookie", "noCookie"); + await doTest(SAME_ORIGIN, "cors", "omit", "noCookie", "noCookie"); + await doTest(CROSS_ORIGIN, "no-cors", "omit", "noCookie", "noCookie"); + await doTest(CROSS_ORIGIN, "cors", "omit", "noCookie", "noCookie"); +}); diff --git a/dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_2.js b/dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_2.js new file mode 100644 index 0000000000..7a1e6879ac --- /dev/null +++ b/dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_2.js @@ -0,0 +1,145 @@ +const TOP_LEVEL_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "open_credentialless_document.sjs"; + +const SAME_ORIGIN = "https://example.com"; +const CROSS_ORIGIN = "https://test1.example.com"; + +const GET_STATE_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "store_header.sjs?getstate"; + +async function addCookieToOrigin(origin) { + const fetchRequestURL = + getRootDirectory(gTestPath).replace("chrome://mochitests/content", origin) + + "store_header.sjs?addcookie"; + + const addcookieTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + fetchRequestURL + ); + + await SpecialPowers.spawn(addcookieTab.linkedBrowser, [], async function () { + content.document.cookie = "coep=credentialless; SameSite=None; Secure"; + }); + await BrowserTestUtils.removeTab(addcookieTab); +} + +async function testOrigin( + fetchOrigin, + isCredentialless, + useMetaTag, + fetchRequestMode, + fetchRequestCrendentials, + expectedCookieResult +) { + let params = []; + if (isCredentialless) { + params.push("credentialless"); + } + if (useMetaTag) { + params.push("meta"); + } + + let topLevelUrl = TOP_LEVEL_URL; + if (params.length) { + topLevelUrl += "?" + params.join("&"); + } + + const noCredentiallessTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + topLevelUrl + ); + + const fetchRequestURL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + fetchOrigin + ) + "store_header.sjs?checkheader"; + + await SpecialPowers.spawn( + noCredentiallessTab.linkedBrowser, + [ + !useMetaTag && isCredentialless, + fetchRequestURL, + fetchRequestMode, + fetchRequestCrendentials, + GET_STATE_URL, + expectedCookieResult, + ], + async function ( + sharedArrayBufferEnabled, + fetchRequestURL, + fetchRequestMode, + fetchRequestCrendentials, + getStateURL, + expectedCookieResult + ) { + if (sharedArrayBufferEnabled) { + ok(content.crossOriginIsolated); + } + // When store_header.sjs receives this request, it will store + // whether it has received the cookie as a shared state. + await content.fetch(fetchRequestURL, { + mode: fetchRequestMode, + credentials: fetchRequestCrendentials, + }); + + // This request is used to get the saved state from the + // previous fetch request. + const response = await content.fetch(getStateURL, { + mode: "cors", + }); + const text = await response.text(); + is(text, expectedCookieResult); + } + ); + + await BrowserTestUtils.removeTab(noCredentiallessTab); +} + +async function doTest( + origin, + fetchRequestMode, + fetchRequestCrendentials, + expectedCookieResultForNoCredentialless, + expectedCookieResultForCredentialless +) { + for (let credentialless of [true, false]) { + for (let meta of [true, false]) { + await testOrigin( + origin, + credentialless, + meta, + fetchRequestMode, + fetchRequestCrendentials, + credentialless + ? expectedCookieResultForCredentialless + : expectedCookieResultForNoCredentialless + ); + } + } +} + +add_task(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.tabs.remote.coep.credentialless", false], + ["dom.origin-trials.enabled", true], + ["dom.origin-trials.test-key.enabled", true], + ], + }); + + await addCookieToOrigin(SAME_ORIGIN); + await addCookieToOrigin(CROSS_ORIGIN); + + // Same-origin request contains Cookies. + await doTest(SAME_ORIGIN, "no-cors", "include", "hasCookie", "hasCookie"); + await doTest(SAME_ORIGIN, "cors", "include", "hasCookie", "hasCookie"); + await doTest(SAME_ORIGIN, "no-cors", "same-origin", "hasCookie", "hasCookie"); + await doTest(SAME_ORIGIN, "cors", "same-origin", "hasCookie", "hasCookie"); +}); diff --git a/dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_3.js b/dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_3.js new file mode 100644 index 0000000000..a1a1edb2ff --- /dev/null +++ b/dom/fetch/tests/browser_origin_trial_coep_credentialless_fetch_3.js @@ -0,0 +1,150 @@ +const TOP_LEVEL_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "open_credentialless_document.sjs"; + +const SAME_ORIGIN = "https://example.com"; +const CROSS_ORIGIN = "https://test1.example.com"; + +const GET_STATE_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "store_header.sjs?getstate"; + +async function addCookieToOrigin(origin) { + const fetchRequestURL = + getRootDirectory(gTestPath).replace("chrome://mochitests/content", origin) + + "store_header.sjs?addcookie"; + + const addcookieTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + fetchRequestURL + ); + + await SpecialPowers.spawn(addcookieTab.linkedBrowser, [], async function () { + content.document.cookie = "coep=credentialless; SameSite=None; Secure"; + }); + await BrowserTestUtils.removeTab(addcookieTab); +} + +async function testOrigin( + fetchOrigin, + isCredentialless, + useMetaTag, + fetchRequestMode, + fetchRequestCrendentials, + expectedCookieResult +) { + let params = []; + if (isCredentialless) { + params.push("credentialless"); + } + if (useMetaTag) { + params.push("meta"); + } + + let topLevelUrl = TOP_LEVEL_URL; + if (params.length) { + topLevelUrl += "?" + params.join("&"); + } + + const noCredentiallessTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + topLevelUrl + ); + + const fetchRequestURL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + fetchOrigin + ) + "store_header.sjs?checkheader"; + + await SpecialPowers.spawn( + noCredentiallessTab.linkedBrowser, + [ + !useMetaTag && isCredentialless, + fetchRequestURL, + fetchRequestMode, + fetchRequestCrendentials, + GET_STATE_URL, + expectedCookieResult, + ], + async function ( + sharedArrayBufferEnabled, + fetchRequestURL, + fetchRequestMode, + fetchRequestCrendentials, + getStateURL, + expectedCookieResult + ) { + if (sharedArrayBufferEnabled) { + ok(content.crossOriginIsolated); + } + // When store_header.sjs receives this request, it will store + // whether it has received the cookie as a shared state. + await content.fetch(fetchRequestURL, { + mode: fetchRequestMode, + credentials: fetchRequestCrendentials, + }); + + // This request is used to get the saved state from the + // previous fetch request. + const response = await content.fetch(getStateURL, { + mode: "cors", + }); + const text = await response.text(); + is(text, expectedCookieResult); + } + ); + + await BrowserTestUtils.removeTab(noCredentiallessTab); +} + +async function doTest( + origin, + fetchRequestMode, + fetchRequestCrendentials, + expectedCookieResultForNoCredentialless, + expectedCookieResultForCredentialless +) { + for (let credentialless of [true, false]) { + for (let meta of [true, false]) { + await testOrigin( + origin, + credentialless, + meta, + fetchRequestMode, + fetchRequestCrendentials, + credentialless + ? expectedCookieResultForCredentialless + : expectedCookieResultForNoCredentialless + ); + } + } +} + +add_task(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.tabs.remote.coep.credentialless", false], + ["dom.origin-trials.enabled", true], + ["dom.origin-trials.test-key.enabled", true], + ], + }); + + await addCookieToOrigin(SAME_ORIGIN); + await addCookieToOrigin(CROSS_ORIGIN); + + // Cross-origin CORS requests contains Cookies, if credentials mode is set to + // 'include'. This does not depends on COEP. + await doTest(CROSS_ORIGIN, "cors", "include", "hasCookie", "hasCookie"); + await doTest(CROSS_ORIGIN, "cors", "same-origin", "noCookie", "noCookie"); + + // Cross-origin no-CORS requests includes Cookies when: + // 1. credentials mode is 'include' + // 2. COEP: is not credentialless. + await doTest(CROSS_ORIGIN, "no-cors", "include", "hasCookie", "noCookie"); + await doTest(CROSS_ORIGIN, "no-cors", "same-origin", "noCookie", "noCookie"); +}); diff --git a/dom/fetch/tests/browser_origin_trial_coep_credentialless_worker.js b/dom/fetch/tests/browser_origin_trial_coep_credentialless_worker.js new file mode 100644 index 0000000000..be77add88e --- /dev/null +++ b/dom/fetch/tests/browser_origin_trial_coep_credentialless_worker.js @@ -0,0 +1,164 @@ +const TOP_LEVEL_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "open_credentialless_document.sjs"; + +const WORKER_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "credentialless_worker.sjs"; + +const GET_STATE_URL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" + ) + "store_header.sjs?getstate"; + +const SAME_ORIGIN = "https://example.com"; +const CROSS_ORIGIN = "https://test1.example.com"; + +const WORKER_USES_CREDENTIALLESS = "credentialless"; +const WORKER_NOT_USE_CREDENTIALLESS = ""; + +async function addCookieToOrigin(origin) { + const fetchRequestURL = + getRootDirectory(gTestPath).replace("chrome://mochitests/content", origin) + + "store_header.sjs?addcookie"; + + const addcookieTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + fetchRequestURL + ); + + await SpecialPowers.spawn(addcookieTab.linkedBrowser, [], async function () { + content.document.cookie = "coep=credentialless; SameSite=None; Secure"; + }); + await BrowserTestUtils.removeTab(addcookieTab); +} + +async function testOrigin( + fetchOrigin, + isCredentialless, + workerUsesCredentialless, + expectedCookieResult +) { + let topLevelUrl = TOP_LEVEL_URL; + if (isCredentialless) { + topLevelUrl += "?credentialless"; + } + const noCredentiallessTab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + topLevelUrl + ); + + const fetchRequestURL = + getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + fetchOrigin + ) + "store_header.sjs?checkheader"; + + let workerScriptURL = WORKER_URL + "?" + workerUsesCredentialless; + + await SpecialPowers.spawn( + noCredentiallessTab.linkedBrowser, + [fetchRequestURL, GET_STATE_URL, workerScriptURL, expectedCookieResult], + async function ( + fetchRequestURL, + getStateURL, + workerScriptURL, + expectedCookieResult + ) { + const worker = new content.Worker(workerScriptURL, {}); + + // When the worker receives this message, it'll send + // a fetch request to fetchRequestURL, and fetchRequestURL + // will store whether it has received the cookie as a + // shared state. + worker.postMessage(fetchRequestURL); + + if (expectedCookieResult == "error") { + await new Promise(r => { + worker.onerror = function () { + ok(true, "worker has error"); + r(); + }; + }); + } else { + await new Promise(r => { + worker.addEventListener("message", async function () { + // This request is used to get the saved state from the + // previous fetch request. + const response = await content.fetch(getStateURL, { + mode: "cors", + }); + const text = await response.text(); + is(text, expectedCookieResult); + r(); + }); + }); + } + } + ); + await BrowserTestUtils.removeTab(noCredentiallessTab); +} + +async function dedicatedWorkerTest( + origin, + workerCOEP, + expectedCookieResultForNoCredentialless, + expectedCookieResultForCredentialless +) { + await testOrigin( + origin, + false, + workerCOEP, + expectedCookieResultForNoCredentialless + ); + await testOrigin( + origin, + true, + workerCOEP, + expectedCookieResultForCredentialless + ); +} + +add_task(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.tabs.remote.coep.credentialless", false], // Explicitly set credentialless to false because we want to test origin trial + ["dom.origin-trials.enabled", true], + ["dom.origin-trials.test-key.enabled", true], + ], + }); + + await addCookieToOrigin(SAME_ORIGIN); + await addCookieToOrigin(CROSS_ORIGIN); + + await dedicatedWorkerTest( + SAME_ORIGIN, + WORKER_NOT_USE_CREDENTIALLESS, + "hasCookie", + "error" + ); + await dedicatedWorkerTest( + SAME_ORIGIN, + WORKER_USES_CREDENTIALLESS, + "hasCookie", + "hasCookie" + ); + + await dedicatedWorkerTest( + CROSS_ORIGIN, + WORKER_NOT_USE_CREDENTIALLESS, + "hasCookie", + "error" + ); + await dedicatedWorkerTest( + CROSS_ORIGIN, + WORKER_USES_CREDENTIALLESS, + "noCookie", + "noCookie" + ); +}); diff --git a/dom/fetch/tests/crashtests/1577196.html b/dom/fetch/tests/crashtests/1577196.html new file mode 100644 index 0000000000..a2cdae06d0 --- /dev/null +++ b/dom/fetch/tests/crashtests/1577196.html @@ -0,0 +1,26 @@ + + + + + + diff --git a/dom/fetch/tests/crashtests/1664514.html b/dom/fetch/tests/crashtests/1664514.html new file mode 100644 index 0000000000..b033d842fa --- /dev/null +++ b/dom/fetch/tests/crashtests/1664514.html @@ -0,0 +1,5 @@ + + + diff --git a/dom/fetch/tests/crashtests/crashtests.list b/dom/fetch/tests/crashtests/crashtests.list new file mode 100644 index 0000000000..f79a122734 --- /dev/null +++ b/dom/fetch/tests/crashtests/crashtests.list @@ -0,0 +1,2 @@ +load 1577196.html +load 1664514.html diff --git a/dom/fetch/tests/crashtests/url.url b/dom/fetch/tests/crashtests/url.url new file mode 100644 index 0000000000..95e9cf8db0 --- /dev/null +++ b/dom/fetch/tests/crashtests/url.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=http://localhost:8000/ diff --git a/dom/fetch/tests/credentialless_resource.sjs b/dom/fetch/tests/credentialless_resource.sjs new file mode 100644 index 0000000000..72d0d738ec --- /dev/null +++ b/dom/fetch/tests/credentialless_resource.sjs @@ -0,0 +1,21 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; +// small red image +const IMG_BYTES = atob( + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" + + "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" +); + +function handleRequest(request, response) { + response.seizePower(); + response.write("HTTP/1.1 200 OK\r\n"); + response.write("Content-Type: image/png\r\n"); + if (request.queryString === "corp_cross_origin") { + response.write("Cross-Origin-Resource-Policy: cross-origin\r\n"); + } + response.write("\r\n"); + response.write(IMG_BYTES); + response.finish(); +} diff --git a/dom/fetch/tests/credentialless_worker.sjs b/dom/fetch/tests/credentialless_worker.sjs new file mode 100644 index 0000000000..a9e2197d18 --- /dev/null +++ b/dom/fetch/tests/credentialless_worker.sjs @@ -0,0 +1,25 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const WORKER = ` + onmessage = function(event) { + fetch(event.data, { + mode: "no-cors", + credentials: "include" + }).then(function() { + postMessage("fetch done"); + }); + } +`; + +function handleRequest(request, response) { + if (request.queryString === "credentialless") { + response.setHeader("Cross-Origin-Embedder-Policy", "credentialless", true); + } + + response.setHeader("Content-Type", "application/javascript", false); + response.setStatusLine(request.httpVersion, "200", "Found"); + response.write(WORKER); +} diff --git a/dom/fetch/tests/mochitest.ini b/dom/fetch/tests/mochitest.ini new file mode 100644 index 0000000000..32eb841faf --- /dev/null +++ b/dom/fetch/tests/mochitest.ini @@ -0,0 +1,2 @@ +[test_ext_response_constructor.html] +[test_invalid_header_exception.html] diff --git a/dom/fetch/tests/open_credentialless_document.sjs b/dom/fetch/tests/open_credentialless_document.sjs new file mode 100644 index 0000000000..6269e73d78 --- /dev/null +++ b/dom/fetch/tests/open_credentialless_document.sjs @@ -0,0 +1,28 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +// Created with: mktoken --origin 'https://example.com' --feature CoepCredentialless --expiry 'Wed, 01 Jan 3000 01:00:00 +0100' --sign test-keys/test-ecdsa.pkcs8 +const TOKEN = + "Az+DK2Kczk8Xz1cAlD+TkvPZmuM2uJZ2CFefbp2hLuCU9FbUqxWTyQ2tEYr50r0syKELcOZLAPaABw8aYTLHn5YAAABUeyJvcmlnaW4iOiJodHRwczovL2V4YW1wbGUuY29tIiwiZmVhdHVyZSI6IkNvZXBDcmVkZW50aWFsbGVzcyIsImV4cGlyeSI6MzI1MDM2ODAwMDB9"; + +function handleRequest(request, response) { + let params = (request.queryString || "").split("&"); + if (params.includes("credentialless")) { + response.setHeader("Cross-Origin-Embedder-Policy", "credentialless"); + // Enables the SharedArrayBuffer feature + response.setHeader("Cross-Origin-Opener-Policy", "same-origin"); + } else if (params.includes("requirecorp")) { + response.setHeader("Cross-Origin-Embedder-Policy", "require-corp"); + } + let html = ""; + if (!params.includes("meta")) { + response.setHeader("Origin-Trial", TOKEN); + } else { + html += ``; + } + html += "Hello, world!"; + response.setHeader("Content-Type", "text/html;charset=utf-8", false); + response.setStatusLine(request.httpVersion, "200", "Found"); + response.write(html); +} diff --git a/dom/fetch/tests/store_header.sjs b/dom/fetch/tests/store_header.sjs new file mode 100644 index 0000000000..3290a09995 --- /dev/null +++ b/dom/fetch/tests/store_header.sjs @@ -0,0 +1,23 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const key = "store_header"; +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/plain"); + response.setHeader("Access-Control-Allow-Origin", "https://example.com"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + + if (request.queryString === "getstate") { + response.write(getSharedState(key)); + } else if (request.queryString === "checkheader") { + if (request.hasHeader("Cookie")) { + setSharedState(key, "hasCookie"); + } else { + setSharedState(key, "noCookie"); + } + } else { + // This is the first request which sets the cookie + } +} diff --git a/dom/fetch/tests/test_ext_response_constructor.html b/dom/fetch/tests/test_ext_response_constructor.html new file mode 100644 index 0000000000..e4b6cf4eb2 --- /dev/null +++ b/dom/fetch/tests/test_ext_response_constructor.html @@ -0,0 +1,47 @@ + + + + + Test `Response` constructor in a WebExtension + + + + + + +

+ +

+
+
diff --git a/dom/fetch/tests/test_invalid_header_exception.html b/dom/fetch/tests/test_invalid_header_exception.html
new file mode 100644
index 0000000000..710afffcc6
--- /dev/null
+++ b/dom/fetch/tests/test_invalid_header_exception.html
@@ -0,0 +1,39 @@
+
+
+
+
+  Test for Bug 1629390
+  
+  
+  
+  
+
+
+Mozilla Bug 1629390
+

+ +
+
+
+ + -- cgit v1.2.3