diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
commit | d8bbc7858622b6d9c278469aab701ca0b609cddf (patch) | |
tree | eff41dc61d9f714852212739e6b3738b82a2af87 /testing/web-platform/tests/fetch/fetch-later | |
parent | Releasing progress-linux version 125.0.3-1~progress7.99u1. (diff) | |
download | firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip |
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/fetch/fetch-later')
14 files changed, 330 insertions, 11 deletions
diff --git a/testing/web-platform/tests/fetch/fetch-later/activate-after.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/activate-after.tentative.https.window.js index 18b368066b..e62da0508a 100644 --- a/testing/web-platform/tests/fetch/fetch-later/activate-after.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/activate-after.tentative.https.window.js @@ -3,7 +3,7 @@ // META: script=/common/utils.js // META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js // META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js 'use strict'; diff --git a/testing/web-platform/tests/fetch/fetch-later/iframe.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/iframe.tentative.https.window.js index 1e9fed1117..305272af41 100644 --- a/testing/web-platform/tests/fetch/fetch-later/iframe.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/iframe.tentative.https.window.js @@ -1,6 +1,6 @@ // META: script=/common/utils.js // META: script=/common/get-host-info.sub.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js 'use strict'; diff --git a/testing/web-platform/tests/fetch/fetch-later/new-window.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/new-window.tentative.https.window.js index 93705418f2..27922f4626 100644 --- a/testing/web-platform/tests/fetch/fetch-later/new-window.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/new-window.tentative.https.window.js @@ -1,6 +1,6 @@ // META: script=/common/utils.js // META: script=/common/get-host-info.sub.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js 'use strict'; diff --git a/testing/web-platform/tests/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js index 60730e0242..32a3e106a0 100644 --- a/testing/web-platform/tests/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/policies/csp-allowed.tentative.https.window.js @@ -1,7 +1,7 @@ // META: title=FetchLater: allowed by CSP // META: script=/common/utils.js // META: script=/common/get-host-info.sub.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js 'use strict'; const { diff --git a/testing/web-platform/tests/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js index b32ddaecfc..ca9d881e8c 100644 --- a/testing/web-platform/tests/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/policies/csp-blocked.tentative.https.window.js @@ -1,7 +1,7 @@ // META: title=FetchLater: blocked by CSP // META: script=/common/utils.js // META: script=/common/get-host-info.sub.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js 'use strict'; const { diff --git a/testing/web-platform/tests/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js index 3c18727156..584f476b45 100644 --- a/testing/web-platform/tests/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/policies/csp-redirect-to-blocked.tentative.https.window.js @@ -1,7 +1,7 @@ // META: title=FetchLater: redirect blocked by CSP // META: script=/common/utils.js // META: script=/common/get-host-info.sub.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js // META: timeout=long 'use strict'; diff --git a/testing/web-platform/tests/fetch/fetch-later/quota.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/quota.tentative.https.window.js index 1b5b85563d..9d0ae4287d 100644 --- a/testing/web-platform/tests/fetch/fetch-later/quota.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/quota.tentative.https.window.js @@ -1,6 +1,6 @@ // META: script=/common/get-host-info.sub.js // META: script=/common/utils.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js 'use strict'; diff --git a/testing/web-platform/tests/fetch/fetch-later/resources/fetch-later-helper.js b/testing/web-platform/tests/fetch/fetch-later/resources/fetch-later-helper.js new file mode 100644 index 0000000000..566b3e0a1a --- /dev/null +++ b/testing/web-platform/tests/fetch/fetch-later/resources/fetch-later-helper.js @@ -0,0 +1,206 @@ +'use strict'; + +const ROOT_NAME = 'fetch/fetch-later'; + +function parallelPromiseTest(func, description) { + async_test((t) => { + Promise.resolve(func(t)).then(() => t.done()).catch(t.step_func((e) => { + throw e; + })); + }, description); +} + +/** @enum {string} */ +const BeaconDataType = { + String: 'String', + ArrayBuffer: 'ArrayBuffer', + FormData: 'FormData', + URLSearchParams: 'URLSearchParams', + Blob: 'Blob', + File: 'File', +}; + +/** @enum {string} */ +const BeaconDataTypeToSkipCharset = { + String: '', + ArrayBuffer: '', + FormData: '\n\r', // CRLF characters will be normalized by FormData + URLSearchParams: ';,/?:@&=+$', // reserved URI characters + Blob: '', + File: '', +}; + +const BEACON_PAYLOAD_KEY = 'payload'; + +// Creates beacon data of the given `dataType` from `data`. +// @param {string} data - A string representation of the beacon data. Note that +// it cannot contain UTF-16 surrogates for all `BeaconDataType` except BLOB. +// @param {BeaconDataType} dataType - must be one of `BeaconDataType`. +// @param {string} contentType - Request Content-Type. +function makeBeaconData(data, dataType, contentType) { + switch (dataType) { + case BeaconDataType.String: + return data; + case BeaconDataType.ArrayBuffer: + return new TextEncoder().encode(data).buffer; + case BeaconDataType.FormData: + const formData = new FormData(); + if (data.length > 0) { + formData.append(BEACON_PAYLOAD_KEY, data); + } + return formData; + case BeaconDataType.URLSearchParams: + if (data.length > 0) { + return new URLSearchParams(`${BEACON_PAYLOAD_KEY}=${data}`); + } + return new URLSearchParams(); + case BeaconDataType.Blob: { + const options = {type: contentType || undefined}; + return new Blob([data], options); + } + case BeaconDataType.File: { + const options = {type: contentType || 'text/plain'}; + return new File([data], 'file.txt', options); + } + default: + throw Error(`Unsupported beacon dataType: ${dataType}`); + } +} + +// Create a string of `end`-`begin` characters, with characters starting from +// UTF-16 code unit `begin` to `end`-1. +function generateSequentialData(begin, end, skip) { + const codeUnits = Array(end - begin).fill().map((el, i) => i + begin); + if (skip) { + return String.fromCharCode( + ...codeUnits.filter(c => !skip.includes(String.fromCharCode(c)))); + } + return String.fromCharCode(...codeUnits); +} + +function generatePayload(size) { + if (size == 0) { + return ''; + } + const prefix = String(size) + ':'; + if (size < prefix.length) { + return Array(size).fill('*').join(''); + } + if (size == prefix.length) { + return prefix; + } + + return prefix + Array(size - prefix.length).fill('*').join(''); +} + +function generateSetBeaconURL(uuid, options) { + const host = (options && options.host) || ''; + let url = `${host}/${ROOT_NAME}/resources/set_beacon.py?uuid=${uuid}`; + if (options) { + if (options.expectOrigin !== undefined) { + url = `${url}&expectOrigin=${options.expectOrigin}`; + } + if (options.expectPreflight !== undefined) { + url = `${url}&expectPreflight=${options.expectPreflight}`; + } + if (options.expectCredentials !== undefined) { + url = `${url}&expectCredentials=${options.expectCredentials}`; + } + + if (options.useRedirectHandler) { + const redirect = `${host}/common/redirect.py` + + `?location=${encodeURIComponent(url)}`; + url = redirect; + } + } + return url; +} + +async function poll(asyncFunc, expected) { + const maxRetries = 30; + const waitInterval = 100; // milliseconds. + const delay = ms => new Promise(res => setTimeout(res, ms)); + + let result = {data: []}; + for (let i = 0; i < maxRetries; i++) { + result = await asyncFunc(); + if (!expected(result)) { + await delay(waitInterval); + continue; + } + return result; + } + return result; +} + +// Waits until the `options.count` number of beacon data available from the +// server. Defaults to 1. +// If `options.data` is set, it will be used to compare with the data from the +// response. +async function expectBeacon(uuid, options) { + const expectedCount = + (options && options.count !== undefined) ? options.count : 1; + + const res = await poll( + async () => { + const res = await fetch( + `/${ROOT_NAME}/resources/get_beacon.py?uuid=${uuid}`, + {cache: 'no-store'}); + return await res.json(); + }, + (res) => { + if (expectedCount == 0) { + // If expecting no beacon, we should try to wait as long as possible. + // So always returning false here until `poll()` decides to terminate + // itself. + return false; + } + return res.data.length == expectedCount; + }); + if (!options || !options.data) { + assert_equals( + res.data.length, expectedCount, + 'Number of sent beacons does not match expected count:'); + return; + } + + if (expectedCount == 0) { + assert_equals( + res.data.length, 0, + 'Number of sent beacons does not match expected count:'); + return; + } + + const decoder = options && options.percentDecoded ? (s) => { + // application/x-www-form-urlencoded serializer encodes space as '+' + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent + s = s.replace(/\+/g, '%20'); + return decodeURIComponent(s); + } : (s) => s; + + assert_equals( + res.data.length, options.data.length, + `The size of beacon data ${ + res.data.length} from server does not match expected value ${ + options.data.length}.`); + for (let i = 0; i < options.data.length; i++) { + assert_equals( + decoder(res.data[i]), options.data[i], + 'The beacon data does not match expected value.'); + } +} + +function generateHTML(script) { + return `<!DOCTYPE html><body><script>${script}</script></body>`; +} + +// Loads `script` into an iframe and appends it to the current document. +// Returns the loaded iframe element. +async function loadScriptAsIframe(script) { + const iframe = document.createElement('iframe'); + iframe.srcdoc = generateHTML(script); + const iframeLoaded = new Promise(resolve => iframe.onload = resolve); + document.body.appendChild(iframe); + await iframeLoaded; + return iframe; +} diff --git a/testing/web-platform/tests/fetch/fetch-later/resources/get_beacon.py b/testing/web-platform/tests/fetch/fetch-later/resources/get_beacon.py new file mode 100644 index 0000000000..32cb9a9ba3 --- /dev/null +++ b/testing/web-platform/tests/fetch/fetch-later/resources/get_beacon.py @@ -0,0 +1,30 @@ +"""An HTTP request handler for WPT that handles /get_beacon.py requests.""" + +import json + +_BEACON_ID_KEY = b"uuid" +_BEACON_DATA_PATH = "beacon_data" + + +def main(request, response): + """Retrieves the beacon data keyed by the given uuid from server storage. + + The response content is a JSON string in one of the following formats: + - "{'data': ['abc', null, '123',...]}" + - "{'data': []}" indicates that no data has been set for this uuid. + """ + if _BEACON_ID_KEY not in request.GET: + response.status = 400 + return "Must provide a UUID to store beacon data" + uuid = request.GET.first(_BEACON_ID_KEY) + + with request.server.stash.lock: + body = {'data': []} + data = request.server.stash.take(key=uuid, path=_BEACON_DATA_PATH) + if data: + body['data'] = data + # The stash is read-once/write-once, so it has to be put back after + # reading if `data` is not None. + request.server.stash.put( + key=uuid, value=data, path=_BEACON_DATA_PATH) + return [(b'Content-Type', b'text/plain')], json.dumps(body) diff --git a/testing/web-platform/tests/fetch/fetch-later/resources/set_beacon.py b/testing/web-platform/tests/fetch/fetch-later/resources/set_beacon.py new file mode 100644 index 0000000000..1c71f23e57 --- /dev/null +++ b/testing/web-platform/tests/fetch/fetch-later/resources/set_beacon.py @@ -0,0 +1,83 @@ +"""An HTTP request handler for WPT that handles /set_beacon.py requests.""" + +_BEACON_ID_KEY = b"uuid" +_BEACON_DATA_PATH = "beacon_data" +_BEACON_FORM_PAYLOAD_KEY = b"payload" +_BEACON_BODY_PAYLOAD_KEY = "payload=" +_BEACON_EXPECT_ORIGIN_KEY = b"expectOrigin" +_BEACON_EXPECT_PREFLIGHT_KEY = b"expectPreflight" +_BEACON_EXPECT_CREDS_KEY = b"expectCredentials" + + +def main(request, response): + """Stores the given beacon's data keyed by uuid in the server. + + For GET request, this handler assumes no data. + For POST request, this handler extracts data from request body: + - Content-Type=multipart/form-data: data keyed by 'payload'. + - the entire request body. + + Multiple data can be added for the same uuid. + + The data is stored as UTF-8 format. + """ + if _BEACON_ID_KEY not in request.GET: + response.status = 400 + return "Must provide a UUID to store beacon data" + uuid = request.GET.first(_BEACON_ID_KEY) + + expected_origin = request.GET.get(_BEACON_EXPECT_ORIGIN_KEY) + if b"origin" in request.headers: + origin = request.headers.get(b"origin") + if expected_origin: + assert origin == expected_origin, f"expected {expected_origin}, got {origin}" + response.headers.set(b"Access-Control-Allow-Origin", origin) + else: + assert expected_origin is None, f"expected None, got {expected_origin}" + + # Handles preflight request first. + if request.method == u"OPTIONS": + assert request.GET.get( + _BEACON_EXPECT_PREFLIGHT_KEY) == b"true", "Preflight not expected." + + # preflight must not have cookies. + assert b"Cookie" not in request.headers + + requested_headers = request.headers.get( + b"Access-Control-Request-Headers") + assert b"content-type" in requested_headers, f"expected content-type, got {requested_headers}" + response.headers.set(b"Access-Control-Allow-Headers", b"content-type") + + requested_method = request.headers.get(b"Access-Control-Request-Method") + assert requested_method == b"POST", f"expected POST, got {requested_method}" + response.headers.set(b"Access-Control-Allow-Methods", b"POST") + + return response + + expect_creds = request.GET.get(_BEACON_EXPECT_CREDS_KEY) == b"true" + if expect_creds: + assert b"Cookie" in request.headers + else: + assert b"Cookie" not in request.headers + + data = None + if request.method == u"POST": + if b"multipart/form-data" in request.headers.get(b"Content-Type", b""): + if _BEACON_FORM_PAYLOAD_KEY in request.POST: + data = request.POST.first(_BEACON_FORM_PAYLOAD_KEY).decode( + 'utf-8') + elif request.body: + data = request.body.decode('utf-8') + if data.startswith(_BEACON_BODY_PAYLOAD_KEY): + data = data.split(_BEACON_BODY_PAYLOAD_KEY)[1] + + with request.server.stash.lock: + saved_data = request.server.stash.take(key=uuid, path=_BEACON_DATA_PATH) + if not saved_data: + saved_data = [data] + else: + saved_data.append(data) + request.server.stash.put( + key=uuid, value=saved_data, path=_BEACON_DATA_PATH) + + response.status = 200 diff --git a/testing/web-platform/tests/fetch/fetch-later/send-on-deactivate.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/send-on-deactivate.tentative.https.window.js index d91c73580a..3bcf07483a 100644 --- a/testing/web-platform/tests/fetch/fetch-later/send-on-deactivate.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/send-on-deactivate.tentative.https.window.js @@ -3,7 +3,7 @@ // META: script=/common/utils.js // META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js // META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js 'use strict'; diff --git a/testing/web-platform/tests/fetch/fetch-later/send-on-discard/not-send-after-abort.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/send-on-discard/not-send-after-abort.tentative.https.window.js index ff8d9520e0..6ddafd7813 100644 --- a/testing/web-platform/tests/fetch/fetch-later/send-on-discard/not-send-after-abort.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/send-on-discard/not-send-after-abort.tentative.https.window.js @@ -1,5 +1,5 @@ // META: script=/common/utils.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js 'use strict'; diff --git a/testing/web-platform/tests/fetch/fetch-later/send-on-discard/send-multiple-with-activate-after.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/send-on-discard/send-multiple-with-activate-after.tentative.https.window.js index 11e85b31a7..0bbe94c39f 100644 --- a/testing/web-platform/tests/fetch/fetch-later/send-on-discard/send-multiple-with-activate-after.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/send-on-discard/send-multiple-with-activate-after.tentative.https.window.js @@ -1,5 +1,5 @@ // META: script=/common/utils.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js // META: timeout=long 'use strict'; diff --git a/testing/web-platform/tests/fetch/fetch-later/send-on-discard/send-multiple.tentative.https.window.js b/testing/web-platform/tests/fetch/fetch-later/send-on-discard/send-multiple.tentative.https.window.js index df34ec9ac0..05bb2dc114 100644 --- a/testing/web-platform/tests/fetch/fetch-later/send-on-discard/send-multiple.tentative.https.window.js +++ b/testing/web-platform/tests/fetch/fetch-later/send-on-discard/send-multiple.tentative.https.window.js @@ -1,5 +1,5 @@ // META: script=/common/utils.js -// META: script=/pending-beacon/resources/pending_beacon-helper.js +// META: script=/fetch/fetch-later/resources/fetch-later-helper.js // META: timeout=long 'use strict'; |