Skip to content

Commit

Permalink
chore: update WPT (#4028)
Browse files Browse the repository at this point in the history
Co-authored-by: Uzlopak <[email protected]>
  • Loading branch information
github-actions[bot] and Uzlopak authored Feb 16, 2025
1 parent 4269dab commit 608d5f6
Show file tree
Hide file tree
Showing 55 changed files with 1,489 additions and 228 deletions.
5 changes: 5 additions & 0 deletions test/fixtures/wpt/common/dispatcher/remote-executor-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
importScripts('./dispatcher.js');

const params = new URLSearchParams(location.search);
const uuid = params.get('uuid');
const executor = new Executor(uuid); // `execute()` is called in constructor.
5 changes: 4 additions & 1 deletion test/fixtures/wpt/common/dispatcher/remote-executor.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
<meta charset="utf-8">
<body>
</body>
<script src="./dispatcher.js"></script>
<script src="./dispatcher.js"
crossorigin
integrity="sha256-daCATx8B9i1s6ixqZvCGcGQOv3a+VMoor6aS9UNUoiY=">
</script>
<script>
const params = new URLSearchParams(window.location.search);
const uuid = params.get('uuid');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,6 @@ async function loadElement(el) {
await loaded;
}

// `host` may be cross-origin
async function loadFetchLaterIframe(host, targetUrl) {
const url = `${host}/fetch/fetch-later/resources/fetch-later.html?url=${
encodeURIComponent(targetUrl)}`;
const iframe = document.createElement('iframe');
iframe.src = url;
await loadElement(iframe);
return iframe;
}

parallelPromiseTest(async t => {
const uuid = token();
const url = generateSetBeaconURL(uuid);
Expand All @@ -39,17 +29,3 @@ parallelPromiseTest(async t => {
// The iframe should have sent the request.
await expectBeacon(uuid, {count: 1});
}, 'A blank iframe can trigger fetchLater.');

parallelPromiseTest(async t => {
const uuid = token();
const url = generateSetBeaconURL(uuid);

// Loads a same-origin iframe that fires a fetchLater request.
await loadFetchLaterIframe(HTTPS_ORIGIN, url);

// The iframe should have sent the request.
await expectBeacon(uuid, {count: 1});
}, 'A same-origin iframe can trigger fetchLater.');

// The test to load a cross-origin iframe that fires a fetchLater request is in
// /fetch/fetch-later/permissions-policy/deferred-fetch-default-permissions-policy.tentative.https.window.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,32 @@ const {

function fetchLaterPopupUrl(host, targetUrl) {
return `${host}/fetch/fetch-later/resources/fetch-later.html?url=${
encodeURIComponent(targetUrl)}`;
encodeURIComponent(targetUrl)}&activateAfter=0`;
}

async function receiveMessageFromPopup(url) {
const expect =
new FetchLaterIframeExpectation(FetchLaterExpectationType.DONE);
const messageType = await new Promise((resolve, reject) => {
window.addEventListener('message', function handler(e) {
try {
if (expect.run(e, url)) {
window.removeEventListener('message', handler);
resolve(e.data.type);
}
} catch (err) {
reject(err);
}
});
});

assert_equals(messageType, FetchLaterIframeMessageType.DONE);
}

for (const target of ['', '_blank']) {
for (const features in ['', 'popup', 'popup,noopener']) {
// NOTE: noopener popup window cannot communicate back. It will be too
// unreliable to only use `expectBeacon()` to test such window.
for (const features of ['', 'popup']) {
parallelPromiseTest(
async t => {
const uuid = token();
Expand Down Expand Up @@ -43,7 +64,7 @@ for (const target of ['', '_blank']) {

// Opens a same-origin popup that fires a fetchLater request.
const w = window.open(popupUrl, target, features);
await new Promise(resolve => w.addEventListener('load', resolve));
await receiveMessageFromPopup(popupUrl);

// The popup should have sent the request.
await expectBeacon(uuid, {count: 1});
Expand All @@ -60,10 +81,7 @@ for (const target of ['', '_blank']) {

// Opens a cross-origin popup that fires a fetchLater request.
const w = window.open(popupUrl, target, features);
// As events from cross-origin window is not accessible, waiting for
// its message instead.
await new Promise(
resolve => window.addEventListener('message', resolve));
await receiveMessageFromPopup(popupUrl);

// The popup should have sent the request.
await expectBeacon(uuid, {count: 1});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@ const {
} = get_host_info();

const baseUrl = '/permissions-policy/resources/redirect-on-load.html#';
// https://whatpr.org/fetch/1647.html#dom-permissionspolicy-deferred-fetch-minimal
const description = 'Permissions policy allow="deferred-fetch"';

async_test(t => {
test_feature_availability(
'fetchLater()', t,
getDeferredFetchPolicyInIframeHelperUrl(`${baseUrl}${HTTPS_ORIGIN}`),
expect_feature_available_default, /*feature_name=*/ 'deferred-fetch');
}, `${description} allows same-origin navigation in an iframe.`);
}, `${description} allows fetchLater() from a redirected same-origin iframe.`);

// By default, "deferred-fetch" is off for cross-origin iframe.
// It requires a Permissions-Policy header in addition to the allow attribute.
async_test(t => {
test_feature_availability(
'fetchLater()', t,
getDeferredFetchPolicyInIframeHelperUrl(
`${baseUrl}${HTTPS_NOTSAMESITE_ORIGIN}`),
expect_feature_available_default, /*feature_name=*/ 'deferred-fetch');
}, `${description} allows cross-origin navigation in an iframe.`);
expect_feature_unavailable_default, /*feature_name=*/ 'deferred-fetch');
}, `${description} disallows fetchLater() from a redirected cross-origin iframe.`);
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ const {
HTTPS_NOTSAMESITE_ORIGIN,
} = get_host_info();

const description = 'Default "deferred-fetch" permissions policy ["self"]';
// https://whatpr.org/fetch/1647.html#dom-permissionspolicy-deferred-fetch
const deferredFetchPolicy =
'Default "deferred-fetch" permissions policy ["self"]';
// https://whatpr.org/fetch/1647.html#dom-permissionspolicy-deferred-fetch-minimal
const deferredFetchMinimalPolicy =
'Default "deferred-fetch-minimal" permissions policy ["*"]';

parallelPromiseTest(async _ => {
const uuid = token();
Expand All @@ -22,17 +27,17 @@ parallelPromiseTest(async _ => {
fetchLater(url, {activateAfter: 0});

await expectBeacon(uuid, {count: 1});
}, `${description} allows fetchLater() in the top-level document.`);
}, `${deferredFetchPolicy} allows fetchLater() in the top-level document.`);

async_test(t => {
test_feature_availability(
'fetchLater()', t, getDeferredFetchPolicyInIframeHelperUrl(HTTPS_ORIGIN),
expect_feature_available_default);
}, `${description} allows fetchLater() in the same-origin iframe.`);
}, `${deferredFetchPolicy} allows fetchLater() in the same-origin iframe.`);

async_test(t => {
test_feature_availability(
'fetchLater()', t,
getDeferredFetchPolicyInIframeHelperUrl(HTTPS_NOTSAMESITE_ORIGIN),
expect_feature_available_default);
}, `${description} allows fetchLater() in the cross-origin iframe.`);
}, `${deferredFetchMinimalPolicy} allows fetchLater() in the cross-origin iframe.`);
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
// https://wicg.github.io/local-fonts/#permissions-policy
test(() => {
assert_in_array('deferred-fetch', document.featurePolicy.features());
assert_in_array('deferred-fetch-minimal', document.featurePolicy.features());
}, 'document.featurePolicy.features should advertise deferred-fetch.');
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use strict';

/**
* Returns an URL to a document that can be used to initialize an iframe to test
* whether the "deferred-fetch"policy is enabled.
* Returns a URL to a document that can be used to initialize an iframe to test
* whether the Permissions Policy "deferred-fetch" or "deferred-fetch-minimal"
* is enabled.
*/
function getDeferredFetchPolicyInIframeHelperUrl(iframeOrigin) {
if (!iframeOrigin.endsWith('/')) {
Expand Down
134 changes: 0 additions & 134 deletions test/fixtures/wpt/fetch/fetch-later/quota.tentative.https.window.js

This file was deleted.

10 changes: 10 additions & 0 deletions test/fixtures/wpt/fetch/fetch-later/quota/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Quota Tests

This folder contains tests to cover the `fetchLater()` API's
per-reporting-origin quota.

See the following links:

- Initial Proposal: https://github.com/WICG/pending-beacon/issues/87#issuecomment-1985358609.
- fetch PR: https://github.com/whatwg/fetch/pull/1647
- html PR: https://github.com/whatwg/html/pull/10903
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// META: script=/common/get-host-info.sub.js
// META: script=/common/utils.js
// META: script=/fetch/fetch-later/resources/fetch-later-helper.js
// META: script=/fetch/fetch-later/quota/resources/helper.js
'use strict';

const {HTTPS_ORIGIN, HTTPS_NOTSAMESITE_ORIGIN} = get_host_info();

// Skips FormData & URLSearchParams, as browser adds extra bytes to them
// in addition to the user-provided content. It is difficult to test a
// request right at the quota limit.
// Skips File & Blob as it's difficult to estimate what additional data are
// added into them.
const dataType = BeaconDataType.String;

// Request headers are counted into total request size.
const headers = new Headers({'Content-Type': 'text/plain;charset=UTF-8'});

const requestUrl = `${HTTPS_ORIGIN}/`;
const quota = getRemainingQuota(QUOTA_PER_ORIGIN, requestUrl, headers);
const halfQuota = Math.ceil(quota / 2);


// Tests that a reporting origin only allow queuing requests within its quota.
test(
() => {
const controller = new AbortController();

// Queues with the 1st call (POST) that sends max/2 quota.
fetchLater(requestUrl, {
method: 'POST',
signal: controller.signal,
body: makeBeaconData(generatePayload(halfQuota), dataType),
// Required, as the size of referrer also take up quota.
referrer: '',
});

// Makes the 2nd call (POST) to the same reporting origin that sends
// max bytes, which should be rejected.
assert_throws_dom('QuotaExceededError', () => {
fetchLater(requestUrl, {
method: 'POST',
signal: controller.signal,
body: makeBeaconData(generatePayload(quota), dataType),
// Required, as the size of referrer also take up quota.
referrer: '',
});
});

// Makes the 3rd call (GET) to the same reporting origin, where its
// request size is len(requestUrl) + headers, which should be accepted.
fetchLater(requestUrl, {
method: 'GET',
signal: controller.signal,
// Required, as the size of referrer also take up quota.
referrer: '',
});

// Release quota taken by the pending requests for subsequent tests.
controller.abort();
},
`The 2nd fetchLater(same-origin) call in the top-level document is not allowed to exceed per-origin quota for its POST body of ${
dataType}.`);
Loading

0 comments on commit 608d5f6

Please sign in to comment.