<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test for Grandfathering</title>
    <script src="/js-test-resources/js-test.js"></script>
    <script src="resources/util.js"></script>
</head>
<body>
<script>
    const firstPartyOrigin = "http://localhost:8000";
    const firstPartyBaseUrl = firstPartyOrigin + "/resourceLoadStatistics/resources";
    const firstPartyCookieName = "firstPartyCookie";
    const thirdPartyCookieName = "thirdPartyCookie";
    const cookieValue = "value";
    const subPathToSetFirstPartyCookie = "/set-cookie.php?name=" + firstPartyCookieName + "&value=" + cookieValue;
    const returnUrl = firstPartyOrigin + "/resourceLoadStatistics/grandfathering.html";
    const thirdPartyOrigin = "http://127.0.0.1:8000";
    const thirdPartyBaseUrl = thirdPartyOrigin + "/resourceLoadStatistics/resources";
    const subPathToSetThirdPartyCookie = "/set-cookie.php?name=" + thirdPartyCookieName + "&value=" + cookieValue;

    function finishTest() {
        setEnableFeature(false, function() {
            testRunner.notifyDone();
        });
    }

    function fireDataModificationHandlerAndContinue() {
        testRunner.installStatisticsDidScanDataRecordsCallback(function() {
            runTest();
        });
        testRunner.statisticsProcessStatisticsAndDataRecords();
    }

    function clearInMemoryAndPersistentStoreAndContinue() {
        testRunner.statisticsClearInMemoryAndPersistentStore(function() {
            runTest();
        });
    }

    function runTest() {
        switch (document.location.hash) {
            case "#step1":
                // Set a first-party cookie for localhost.
                document.location.href = firstPartyBaseUrl + subPathToSetFirstPartyCookie + "#" + returnUrl + "#step2";
                break;
            case "#step2":
                document.location.hash = "step3";
                // Check that localhost's cookie is there.
                if (document.cookie !== firstPartyCookieName + "=" + cookieValue)
                    testFailed("First-party cookie not set.");
                runTest();
                break;
            case "#step3":
                document.location.hash = "step4";
                // Clear store to trigger grandfathering.
                clearInMemoryAndPersistentStoreAndContinue();
                break;
            case "#step4":
                document.location.hash = "step5";
                // Set localhost as prevalent resource.
                testRunner.setStatisticsPrevalentResource("http://localhost", true, function() {
                    if (!testRunner.isStatisticsPrevalentResource("http://localhost"))
                        testFailed("Localhost did not get set as prevalent resource.");
                    runTest();
                });
                break;
            case "#step5":
                // Set a first-party cookie for 127.0.0.1.
                document.location.href = thirdPartyBaseUrl + subPathToSetThirdPartyCookie + "#" + returnUrl + "#step6";
                break;
            case "#step6":
                document.location.hash = "step7";
                // Set 127.0.0.1 as prevalent resource
                testRunner.setStatisticsPrevalentResource("http://127.0.0.1", true, function() {
                    if (!testRunner.isStatisticsPrevalentResource("http://127.0.0.1"))
                        testFailed("127.0.0.1 did not get set as prevalent resource.");
                    runTest();
                });
                break;
            case "#step7":
                document.location.hash = "step8";
                // Trigger a purge.
                fireDataModificationHandlerAndContinue();
                break;
            case "#step8":
                // Check that localhost's cookie is still there.
                if (document.cookie !== firstPartyCookieName + "=" + cookieValue)
                    testFailed("First-party cookie purged.");
                else
                    testPassed("Grandfathered cookie was not purged.");
                finishTest();
                break;
            default:
                testFailed("Should not be reached.");
                finishTest();
        }
    }

    if (document.location.hash === "" && window.testRunner && window.internals) {
        setEnableFeature(true, function() {
            testRunner.setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(false);
            testRunner.setStatisticsMinimumTimeBetweenDataRecordsRemoval(0);

            testRunner.waitUntilDone();
            testRunner.dumpChildFramesAsText();
            document.location.hash = "step1";
            runTest();
        });
    } else
        runTest();
</script>
</body>
</html>
