summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fetch/api/resources/keepalive-helper.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/fetch/api/resources/keepalive-helper.js')
-rw-r--r--testing/web-platform/tests/fetch/api/resources/keepalive-helper.js176
1 files changed, 176 insertions, 0 deletions
diff --git a/testing/web-platform/tests/fetch/api/resources/keepalive-helper.js b/testing/web-platform/tests/fetch/api/resources/keepalive-helper.js
new file mode 100644
index 0000000000..f6f511631e
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/keepalive-helper.js
@@ -0,0 +1,176 @@
+// Utility functions to help testing keepalive requests.
+
+// Returns a URL to an iframe that loads a keepalive URL on iframe loaded.
+//
+// The keepalive URL points to a target that stores `token`. The token will then
+// be posted back on iframe loaded to the parent document.
+// `method` defaults to GET.
+// `frameOrigin` to specify the origin of the iframe to load. If not set,
+// default to a different site origin.
+// `requestOrigin` to specify the origin of the fetch request target.
+// `sendOn` to specify the name of the event when the keepalive request should
+// be sent instead of the default 'load'.
+// `mode` to specify the fetch request's CORS mode.
+// `disallowCrossOrigin` to ask the iframe to set up a server that disallows
+// cross origin requests.
+function getKeepAliveIframeUrl(token, method, {
+ frameOrigin = 'DEFAULT',
+ requestOrigin = '',
+ sendOn = 'load',
+ mode = 'cors',
+ disallowCrossOrigin = false
+} = {}) {
+ const https = location.protocol.startsWith('https');
+ frameOrigin = frameOrigin === 'DEFAULT' ?
+ get_host_info()[https ? 'HTTPS_NOTSAMESITE_ORIGIN' : 'HTTP_NOTSAMESITE_ORIGIN'] :
+ frameOrigin;
+ return `${frameOrigin}/fetch/api/resources/keepalive-iframe.html?` +
+ `token=${token}&` +
+ `method=${method}&` +
+ `sendOn=${sendOn}&` +
+ `mode=${mode}&` + (disallowCrossOrigin ? `disallowCrossOrigin=1&` : ``) +
+ `origin=${requestOrigin}`;
+}
+
+// Returns a different-site URL to an iframe that loads a keepalive URL.
+//
+// By default, the keepalive URL points to a target that redirects to another
+// same-origin destination storing `token`. The token will then be posted back
+// to parent document.
+//
+// The URL redirects can be customized from `origin1` to `origin2` if provided.
+// Sets `withPreflight` to true to get URL enabling preflight.
+function getKeepAliveAndRedirectIframeUrl(
+ token, origin1, origin2, withPreflight) {
+ const https = location.protocol.startsWith('https');
+ const frameOrigin =
+ get_host_info()[https ? 'HTTPS_NOTSAMESITE_ORIGIN' : 'HTTP_NOTSAMESITE_ORIGIN'];
+ return `${frameOrigin}/fetch/api/resources/keepalive-redirect-iframe.html?` +
+ `token=${token}&` +
+ `origin1=${origin1}&` +
+ `origin2=${origin2}&` + (withPreflight ? `with-headers` : ``);
+}
+
+async function iframeLoaded(iframe) {
+ return new Promise((resolve) => iframe.addEventListener('load', resolve));
+}
+
+// Obtains the token from the message posted by iframe after loading
+// `getKeepAliveAndRedirectIframeUrl()`.
+async function getTokenFromMessage() {
+ return new Promise((resolve) => {
+ window.addEventListener('message', (event) => {
+ resolve(event.data);
+ }, {once: true});
+ });
+}
+
+// Tells if `token` has been stored in the server.
+async function queryToken(token) {
+ const response = await fetch(`../resources/stash-take.py?key=${token}`);
+ const json = await response.json();
+ return json;
+}
+
+// A helper to assert the existence of `token` that should have been stored in
+// the server by fetching ../resources/stash-put.py.
+//
+// This function simply wait for a custom amount of time before trying to
+// retrieve `token` from the server.
+// `expectTokenExist` tells if `token` should be present or not.
+//
+// NOTE:
+// In order to parallelize the work, we are going to have an async_test
+// for the rest of the work. Note that we want the serialized behavior
+// for the steps so far, so we don't want to make the entire test case
+// an async_test.
+function assertStashedTokenAsync(
+ testName, token, {expectTokenExist = true} = {}) {
+ async_test(test => {
+ new Promise(resolve => test.step_timeout(resolve, 3000 /*ms*/))
+ .then(test.step_func(() => {
+ return queryToken(token);
+ }))
+ .then(test.step_func(result => {
+ if (expectTokenExist) {
+ assert_equals(result, 'on', `token should be on (stashed).`);
+ test.done();
+ } else {
+ assert_not_equals(
+ result, 'on', `token should not be on (stashed).`);
+ return Promise.reject(`Failed to retrieve token from server`);
+ }
+ }))
+ .catch(test.step_func(e => {
+ if (expectTokenExist) {
+ test.unreached_func(e);
+ } else {
+ test.done();
+ }
+ }));
+ }, testName);
+}
+
+/**
+ * In an iframe, and in `load` event handler, test to fetch a keepalive URL that
+ * involves in redirect to another URL.
+ *
+ * `unloadIframe` to unload the iframe before verifying stashed token to
+ * simulate the situation that unloads after fetching. Note that this test is
+ * different from `keepaliveRedirectInUnloadTest()` in that the the latter
+ * performs fetch() call directly in `unload` event handler, while this test
+ * does it in `load`.
+ */
+function keepaliveRedirectTest(desc, {
+ origin1 = '',
+ origin2 = '',
+ withPreflight = false,
+ unloadIframe = false,
+ expectFetchSucceed = true,
+} = {}) {
+ desc = `[keepalive][iframe][load] ${desc}` +
+ (unloadIframe ? ' [unload at end]' : '');
+ promise_test(async (test) => {
+ const tokenToStash = token();
+ const iframe = document.createElement('iframe');
+ iframe.src = getKeepAliveAndRedirectIframeUrl(
+ tokenToStash, origin1, origin2, withPreflight);
+ document.body.appendChild(iframe);
+ await iframeLoaded(iframe);
+ assert_equals(await getTokenFromMessage(), tokenToStash);
+ if (unloadIframe) {
+ iframe.remove();
+ }
+
+ assertStashedTokenAsync(
+ desc, tokenToStash, {expectTokenExist: expectFetchSucceed});
+ }, `${desc}; setting up`);
+}
+
+/**
+ * Opens a different site window, and in `unload` event handler, test to fetch
+ * a keepalive URL that involves in redirect to another URL.
+ */
+function keepaliveRedirectInUnloadTest(desc, {
+ origin1 = '',
+ origin2 = '',
+ url2 = '',
+ withPreflight = false,
+ expectFetchSucceed = true
+} = {}) {
+ desc = `[keepalive][new window][unload] ${desc}`;
+
+ promise_test(async (test) => {
+ const targetUrl =
+ `${HTTP_NOTSAMESITE_ORIGIN}/fetch/api/resources/keepalive-redirect-window.html?` +
+ `origin1=${origin1}&` +
+ `origin2=${origin2}&` +
+ `url2=${url2}&` + (withPreflight ? `with-headers` : ``);
+ const w = window.open(targetUrl);
+ const token = await getTokenFromMessage();
+ w.close();
+
+ assertStashedTokenAsync(
+ desc, token, {expectTokenExist: expectFetchSucceed});
+ }, `${desc}; setting up`);
+}