Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
            - /fetch/api/request/request-keepalive-quota.html?include=keepalive-request-different-origins-1 - WPT Dashboard Interop Dashboard
- /fetch/api/request/request-keepalive-quota.html?include=keepalive-request-limit-per-origin-1 - WPT Dashboard Interop Dashboard
- /fetch/api/request/request-keepalive-quota.html?include=keepalive-request-limit-per-origin-2 - WPT Dashboard Interop Dashboard
 
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>Request Keepalive Quota Per Origin Tests</title>
    <meta name="timeout" content="long">
    <meta name="author" title="Sunil Mayya" href="mailto:smayya@mozilla.com">
    <meta name="variant" content="?include=keepalive-request-limit-per-origin-1">
    <meta name="variant" content="?include=keepalive-request-limit-per-origin-2">
    <meta name="variant" content="?include=keepalive-request-different-origins-1">
    <meta name=" variant" content="?include=keepalive-request-different-origins-2">
    <script src="/common/get-host-info.sub.js"></script>
    <script src="/resources/testharness.js"></script>
    <script src="/resources/testharnessreport.js"></script>
    <script src="/common/subset-tests-by-key.js"></script>
    <script src="/fetch/api/resources/keepalive-helper.js"></script>
    <script>
        // These tests verify resource limits specific to firefox
        // We verify the following:
        // 1. Blocking New Keep-Alive Requests (keepalive-request-limit-per-origin-1):
        //       Firefox should block sending new keep-alive requests if the pending keep-alive request
        //       quota per origin is reached.
        // 2. Releasing Quota (keepalive-request-limit-per-origin-2):
        //       Firefox should be able to send new keep-alive requests once the quota per origin
        //       becomes available (i.e., all pending keep-alive requests are resolved).
        // 3. Different Origin Requests (keepalive-request-different-origins-1):
        //      If the keep-alive quota of one origin is full, Firefox should allow new keep-alive
        //      requests from a different origin.
        // 4. Total Requests Per Browser Instance (keepalive-request-different-origins-2):
        //      Verify that the total number of keep-alive requests per browser instance is limited
        //      by sending keep-alive requests from different origins.
        // The remote origin URL is used to create keep-alive requests from a different origin.
        // keepalive-requests.html'creates 5 keepalive pending requests from a remote origin.
        const trickleRemoteURL = get_host_info().HTTPS_REMOTE_ORIGIN + '/_mozilla/fetch/api/request/resources/keepalive-requests.html';
        const noDelay = 0;
        const standardDelay = 1000;
        // Starts a request from a different origin, a new tab is opened  and
        // we load the page hosted on a different origin than request-keepalive-quota.html.
        function fetchKeepAliveRequestRemoteUrl(url) {
            return new Promise((resolve, reject) => {
                try {
                    var w = window.open(url, '_blank');
                    if (!w) {
                        reject(new Error('Failed to open the new window'));
                    }
                    window.addEventListener('message', function listener() {
                        if (event.data === "REQUEST SENT") {
                            // we have successfully created 5 keepalive requests in the new tab
                            window.removeEventListener('message', listener);
                            resolve();
                        } else if (event.data === "FAIL") {
                            window.removeEventListener('message', listener);
                            reject(new Error('Fetch request failed'));
                        }
                    });
                } catch (error) {
                    reject(error);
                }
            });
        }
    </script>
</head>
<body>
    <script>
        'use strict';
        // Ensure we restrict the number of pending requests per origin.
        subsetTestByKey("keepalive-request-limit-per-origin-1", promise_test, function (test) {
            SpecialPowers.setIntPref("dom.fetchKeepalive.request_limit_per_origin", 4);
            const first = createPendingKeepAliveRequest(standardDelay * 2);
            const second = createPendingKeepAliveRequest(standardDelay * 2);
            const third = createPendingKeepAliveRequest(standardDelay * 2);
            const fourth = createPendingKeepAliveRequest(standardDelay * 2);
            const fifth = createPendingKeepAliveRequest(noDelay).then(
                () => {
                    return Promise.reject("A Keepalive fetch() should be rejected when per origin pending requests exceed the limit.");
                },
                () => {
                    return Promise.resolve();
                });
            return Promise.all([first, second, third, fourth, fifth]);
        }, 'Restrict the number of pending requests per origin to dom.fetchKeepalive.request_limit_per_origin');
        // Ensure keepalive requests per origin quota becomes available after pending requests are completed.
        subsetTestByKey("keepalive-request-limit-per-origin-2", promise_test, function (test) {
            SpecialPowers.setIntPref("dom.fetchKeepalive.request_limit_per_origin", 2);
            const first = createPendingKeepAliveRequest(standardDelay * 2);
            const second = createPendingKeepAliveRequest(standardDelay * 2).then(() => {
                // ensure that we can send another Keep-Alive fetch after pending requests are completed.
                return createPendingKeepAliveRequest(noDelay);
            });
            const third = createPendingKeepAliveRequest(noDelay).then(() => {
                return Promise.reject("A Keep-Alive fetch() request exceeding per origin limit should reject.");
            }, () => {
                return Promise.resolve();
            });
            return Promise.all([first, second, third]);
        }, 'A Keep-Alive fetch() per origin quota should become available after pending requests are completed.');
        // Ensure keepalive limits of different origins do not affect each other.
        subsetTestByKey("keepalive-request-different-origins-1", promise_test, function (test) {
            SpecialPowers.setIntPref("dom.fetchKeepalive.request_limit_per_origin", 5);
            SpecialPowers.setIntPref("dom.fetchKeepalive.total_request_limit", 7);
            // fetchKeepAliveRequestRemoteUrl creates 5 pending keepalive requests from a remote origin
            const first = fetchKeepAliveRequestRemoteUrl(trickleRemoteURL).then(() => {
                // ensure that when remote origin has reached full quota,
                // we are still able to send keepalive requests from the current window.
                const second = createPendingKeepAliveRequest(standardDelay);
                const third = createPendingKeepAliveRequest(noDelay).then(() => {
                    return new Promise((resolve, reject) => {
                        try {
                            // By now we have 5 pending requests from the remote origin.
                            // Add event listener to ensure these pending requests are completed
                            window.addEventListener('message', function listener() {
                                // remote origin has successfully completed keepalive requests
                                if (event.data === "REQUEST COMPLETED") {
                                    resolve();
                                    window.removeEventListener('message', listener);
                                } else if (event.data === "FAIL") {
                                    reject(new Error('Fetch request failed'));
                                    window.removeEventListener('message', listener);
                                }
                            });
                        } catch (error) {
                            send
                            reject(error);
                        }
                    });
                });
                return Promise.all([second, third]);
            }).catch((error) => {
                return Promise.reject(error);
            });
            return first;
        }, 'keepalive limits of different origins should not affect each other');
        // Ensure that total keepalive request limits are respected
        subsetTestByKey("keepalive-request-different-origins-2", promise_test, function (test) {
            SpecialPowers.setIntPref("dom.fetchKeepalive.request_limit_per_origin", 5);
            SpecialPowers.setIntPref("dom.fetchKeepalive.total_request_limit", 6);
            // creates 5 pending keepalive requests for a different origin
            const first = fetchKeepAliveRequestRemoteUrl(trickleRemoteURL).then(() => {
                // ensure that when remote origin has reached full quota,
                // we are still able to send exactly 1 keepalive request for the current origin.
                const second = createPendingKeepAliveRequest(standardDelay);
                const third = createPendingKeepAliveRequest(noDelay).then(
                    () => {
                        return Promise.reject("A Keep-Alive fetch() request exceeding total limit should be rejected.");
                    },
                    () => {
                        return new Promise((resolve, reject) => {
                            try {
                                window.addEventListener('message', function listener() {
                                    // remote origin has successfully completed keepalive requests
                                    if (event.data === "REQUEST COMPLETED") {
                                        resolve();
                                        window.removeEventListener('message', listener);
                                    } else if (event.data === "FAIL") {
                                        reject(new Error('Fetch request failed'));
                                        window.removeEventListener('message', listener);
                                    }
                                });
                            } catch (error) {
                                reject(error);
                            }
                        });
                    });
                return Promise.all([second, third]);
            }).catch((error) => {
                return Promise.reject(error);
            });
            return first;
        }, 'total keepalive request limits should be respected');
    </script>
</body>
</html>