<!DOCTYPE html>
<html>
<head>
    <script src="/js-test-resources/js-test.js"></script>
    <script src="/cookies/resources/cookie-utilities.js"></script>
    <script src="resources/util.js"></script>
</head>
<body onload="setTimeout('runTest()', 0)">
<script>
    description("Check that cookies created by JavaScript after a cross-site navigation with link query get capped to 24 hours.");
    jsTestIsAsync = true;

    function testCookies() {
        let passedTests = 0;
        function checkThatCookieDoesNotExpireAfter(cookieData, maxAgeInSeconds) {
            let now = new Date();
            let maxExpiryDateInMilliseconds = now.getTime() + (maxAgeInSeconds * 1000);

            if (maxExpiryDateInMilliseconds > cookieData["expires"])
                ++passedTests;
            else
                testFailed("Cookie named " + cookieData["name"] + " expires in more than " + maxAgeInSeconds + " seconds.");
        }

        const twelveHoursInSeconds = 12 * 60 * 60;
        const shortLivedCookieMaxAge = { name : "shortLivedCookieMaxAge", lifetime : "Max-Age=" + twelveHoursInSeconds + ";" };
        document.cookie = shortLivedCookieMaxAge.name + "=foobar; " + shortLivedCookieMaxAge.lifetime + " path=/";

        const twelveHoursAsExpiresDate = createExpiresDateFromMaxAge(twelveHoursInSeconds);
        const shortLivedCookieExpires = { name : "shortLivedCookieExpires", lifetime : "Expires=" + twelveHoursAsExpiresDate + ";" };
        document.cookie = shortLivedCookieExpires.name + "=foobar; " + shortLivedCookieExpires.lifetime + " path=/";

        const oneDayInSeconds = 2 * twelveHoursInSeconds;
        const twoDaysInSeconds = 2 * oneDayInSeconds;
        const longLivedCookieMaxAge = { name : "longLivedCookieMaxAge", lifetime : "Max-Age=" + twoDaysInSeconds + ";" };
        document.cookie = longLivedCookieMaxAge.name + "=foobar; " + longLivedCookieMaxAge.lifetime + " path=/";

        const twoDaysAsExpiresDate = createExpiresDateFromMaxAge(twoDaysInSeconds);
        const longLivedCookieExpires = { name : "longLivedCookieExpires", lifetime : "Expires=" + twoDaysAsExpiresDate + ";" };
        document.cookie = longLivedCookieExpires.name + "=foobar; " + longLivedCookieExpires.lifetime + " path=/";

        const overTwelveHoursInSeconds = twelveHoursInSeconds + 30;
        const overOneDayInSeconds = oneDayInSeconds + 30;
        if (internals) {
            let cookies = internals.getCookies();
            if (!cookies.length)
                testFailed("No cookies found.");
            for (let cookie of cookies) {
                switch (cookie.name) {
                    case shortLivedCookieMaxAge.name:
                        checkThatCookieDoesNotExpireAfter(cookie, overTwelveHoursInSeconds);
                        break;
                    case shortLivedCookieExpires.name:
                        checkThatCookieDoesNotExpireAfter(cookie, overTwelveHoursInSeconds);
                        break;
                    case longLivedCookieMaxAge.name:
                        checkThatCookieDoesNotExpireAfter(cookie, overOneDayInSeconds);
                        break;
                    case longLivedCookieExpires.name:
                        checkThatCookieDoesNotExpireAfter(cookie, overOneDayInSeconds);
                        break;
                }
            }

            resetCookiesForCurrentOrigin();

            if (passedTests === 4) {
                testPassed("The two short-lived cookies don't expire after more than " + overTwelveHoursInSeconds + " seconds.");
                testPassed("The two long-lived cookies don't expire after more than " + overOneDayInSeconds + " seconds.");
            } else
                testFailed("At least one cookie's expiry attribute was beyond the test thresholds.");
        } else
            testFailed("No internals object.");

        setEnableFeature(false, finishJSTest);
    }

    function navigateCrossOrigin() {
        document.location.href = destinationOrigin + "/resourceLoadStatistics/capped-lifetime-for-cookie-set-in-js-with-link-query-from-prevalent-resource.html?link=query";
    }

    const destinationOrigin = "http://localhost:8000";
    const prevalentResourceOrigin = "http://127.0.0.1:8000";
    function runTest() {
        if (document.location.origin === prevalentResourceOrigin) {
            setEnableFeature(true, function () {
                testRunner.setStatisticsPrevalentResource(prevalentResourceOrigin, true, function() {
                    if (!testRunner.isStatisticsPrevalentResource(prevalentResourceOrigin))
                        testFailed("Host did not get set as prevalent resource.");
                    testRunner.statisticsUpdateCookieBlocking(navigateCrossOrigin);
                });

            });
        } else {
            testCookies();
        }
    }
</script>
</body>
</html>
