|
| 1 | +// Configures `url` such that the response carries a `COEP: ${value}` header. |
| 2 | +// |
| 3 | +// `url` must be a `URL` instance. |
| 4 | +function setDip(url, value) { |
| 5 | + url.searchParams |
| 6 | + .set("pipe", `header(document-isolation-policy,${value})`); |
| 7 | +} |
| 8 | + |
| 9 | +// Resolves the given `relativeUrl` relative to the current window's location. |
| 10 | +// |
| 11 | +// `options` can contain the following keys: |
| 12 | +// |
| 13 | +// - `dip`: value passed to `setDip()`, if present. |
| 14 | +// - `host`: overrides the host of the returned URL. |
| 15 | +// |
| 16 | +// Returns a `URL` instance. |
| 17 | +function resolveUrl(relativeUrl, options) { |
| 18 | + const url = new URL(relativeUrl, window.location); |
| 19 | + |
| 20 | + if (options !== undefined) { |
| 21 | + const { dip, host } = options; |
| 22 | + if (dip !== undefined) { |
| 23 | + setDip(url, dip); |
| 24 | + } |
| 25 | + if (host !== undefined) { |
| 26 | + url.host = host; |
| 27 | + } |
| 28 | + } |
| 29 | + |
| 30 | + return url; |
| 31 | +} |
| 32 | + |
| 33 | +// Adds an iframe loaded from `url` to the current document, waiting for it to |
| 34 | +// load before returning. |
| 35 | +// |
| 36 | +// The returned iframe is removed from the document at the end of the test `t`. |
| 37 | +async function withIframe(t, url) { |
| 38 | + const frame = document.createElement("iframe"); |
| 39 | + frame.src = url; |
| 40 | + |
| 41 | + t.add_cleanup(() => frame.remove()); |
| 42 | + |
| 43 | + const loadedPromise = new Promise(resolve => { |
| 44 | + frame.addEventListener('load', resolve, {once: true}); |
| 45 | + }); |
| 46 | + document.body.append(frame); |
| 47 | + await loadedPromise; |
| 48 | + |
| 49 | + return frame; |
| 50 | +} |
| 51 | + |
| 52 | +// Asynchronously waits for a single "message" event on the given `target`. |
| 53 | +function waitForMessage(target) { |
| 54 | + return new Promise(resolve => { |
| 55 | + target.addEventListener('message', resolve, {once: true}); |
| 56 | + }); |
| 57 | +} |
| 58 | + |
| 59 | +// Fetches `url` from a document with DIP `creatorDip`, then serializes it |
| 60 | +// and returns a URL pointing to the fetched body with the given `scheme`. |
| 61 | +// |
| 62 | +// - `creatorDip` is passed to `setDip()`. |
| 63 | +// - `scheme` may be one of: "blob", "data" or "filesystem". |
| 64 | +// |
| 65 | +// The returned URL is valid until the end of the test `t`. |
| 66 | +async function createLocalUrl(t, { url, creatorDip, scheme }) { |
| 67 | + const frameUrl = resolveUrl("resources/fetch-and-create-url.html", { |
| 68 | + dip: creatorDip, |
| 69 | + }); |
| 70 | + frameUrl.searchParams.set("url", url); |
| 71 | + frameUrl.searchParams.set("scheme", scheme); |
| 72 | + |
| 73 | + const messagePromise = waitForMessage(window); |
| 74 | + const frame = await withIframe(t, frameUrl); |
| 75 | + |
| 76 | + const evt = await messagePromise; |
| 77 | + const message = evt.data; |
| 78 | + assert_equals(message.error, undefined, "url creation error"); |
| 79 | + |
| 80 | + return message.url; |
| 81 | +} |
0 commit comments