<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/utils.js"></script>
<script src="/preload/resources/preload_helper.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script>

const {HTTPS_REMOTE_ORIGIN} = get_host_info();

function createEchoURL(text, type) {
    return `/preload/resources/echo-with-cors.py?type=${
        encodeURIComponent(type)}&content=${
        encodeURIComponent(text)}`
}
const urls = {
    image: createEchoURL('<svg xmlns="http://www.w3.org/2000/svg" width="2" height="2" />', 'image/svg+xml'),
    font: '/preload/resources/font.ttf?x',
    text: createEchoURL('hello', 'text/plain'),
    script: createEchoURL('function dummy() { }', 'application/javascript'),
    style: createEchoURL('.cls { }', 'text/css'),
}

const resourceTypes = {
    image: {url: urls.image, as: 'image'},
    font: {url: urls.font, as: 'font', config: 'anonymous'},
    backgroundImage: {url: urls.image, as: 'image', config: 'no-cors'},
    fetch: {url: urls.text, as: 'fetch'},
    script: {url: urls.script, as: 'script'},
    module: {url: urls.script, as: 'script'},
    style: {url: urls.style, as: 'style'}
}

const configs = {
    // The requested URL is from the same origin
    'same-origin': {crossOrigin: false, attributes: {}},

    // The requested URL is from a remote origin, without CORS
    'no-cors': {crossOrigin: true, attributes: {}},

    // The requested URL is from a remote origin, with CORS (anonymous)
    'anonymous': {crossOrigin: true, attributes: {crossOrigin: 'anonymous'}},

    // The requested URL is from a remote origin, with CORS (including credentials)
    'use-credentials': {crossOrigin: true, attributes: {crossOrigin: 'use-credentials'}},
}

function preload(attributes, t) {
    const link = document.createElement('link');
    link.rel = "preload";
    Object.entries(attributes).forEach(([key, value]) => {
        if (value)
            link[key] = value;
    });

    document.head.appendChild(link);
    t.add_cleanup(() => link.remove());
    return new Promise(resolve => link.addEventListener('load', resolve));
}

const loaders = {
    image: (href, attr, t) => {
        const img = document.createElement('img');
        Object.entries(attr).forEach(([key, value]) => {
            img[key] = value;
        });

        img.src = href

        document.body.appendChild(img);
        t.add_cleanup(() => img.remove());
        return new Promise(resolve => {
            img.addEventListener('load', resolve);
            img.addEventListener('error', resolve);
        });
    },
    font: (href, attr, t) => {
        const style = document.createElement('style');
        style.innerHTML = `@font-face {
            font-family: 'MyFont';
            src: url('${href}');
        }`;

        document.head.appendChild(style);
        t.add_cleanup(() => style.remove());
        const p = document.createElement('p');
        p.style.fontFamily = 'MyFont';
        document.body.appendChild(p);
        t.add_cleanup(() => p.remove());
    },
    shape: (href, attr, t) => {
        const div = document.createElement('div');
        div.style.shapeOutside = `url(${href})`;
        document.body.appendChild(div);
        t.add_cleanup(() => div.remove());
    },
    backgroundImage: (href, attr, t) => {
        const div = document.createElement('div');
        div.style.background = `url(${href})`;
        document.body.appendChild(div);
        t.add_cleanup(() => div.remove());
    },
    fetch: async (href, attr, t) => {
        const options = {mode: attr.crossOrigin ? 'cors' : 'no-cors',
             credentials: !attr.crossOrigin || attr.crossOrigin === 'anonymous' ? 'omit' : 'include'}

        const response = await fetch(href, options)
        await response.text();
    },
    script: async (href, attr, t) => {
        const script = document.createElement('script');
        t.add_cleanup(() => script.remove());
        if (attr.crossOrigin)
            script.setAttribute('crossorigin', attr.crossOrigin);
        script.src = href;
        document.body.appendChild(script);
        await new Promise(resolve => { script.onload = resolve });
    },
    module: async (href, attr, t) => {
        const script = document.createElement('script');
        script.type = 'module';
        t.add_cleanup(() => script.remove());
        if (attr.crossOrigin)
            script.setAttribute('crossorigin', attr.crossOrigin);
        script.src = href;
        document.body.appendChild(script);
        await new Promise(resolve => { script.onload = resolve });
    },
    style: (href, attr, t) => {
        const style = document.createElement('link');
        style.rel = 'stylesheet';
        t.add_cleanup(() => style.remove());
        if (attr.crossOrigin)
            style.setAttribute('crossorigin', attr.crossOrigin);
        document.body.appendChild(style);
    }
}

function preload_reuse_test(type, as, url, preloadConfig, resourceConfig) {
    const expected = (preloadConfig === resourceConfig) ? "reuse" : "discard";
    const key = token();
    const href = getAbsoluteURL(`${
        (configs[resourceConfig].crossOrigin ? HTTPS_REMOTE_ORIGIN : '') + url
    }&${token()}`)
    promise_test(async t => {
        await preload({href, as, ...configs[preloadConfig].attributes}, t);
        await loaders[as](href, configs[resourceConfig].attributes, t)
        verifyNumberOfResourceTimingEntries(href, expected === "reuse" ? 1 : 2)
    }, `Loading ${type} (${resourceConfig}) with link (${preloadConfig}) should ${expected} the preloaded response`);
}

for (const [resourceTypeName, resourceInfo] of Object.entries(resourceTypes)) {
    const configNames = resourceInfo.config ? [resourceInfo.config, 'same-origin'] : Object.keys(configs)
    for (const resourceConfigName of configNames) {
        for (const preloadConfigName of Object.keys(configs)) {
            // Same-origin requests ignore their CORS attributes, so no need to match all of them.
            if ((resourceConfigName === 'same-origin' && preloadConfigName === 'same-origin') ||
                (resourceConfigName !== 'same-origin' && preloadConfigName !== 'same-origin'))
            preload_reuse_test(resourceTypeName, resourceInfo.as, resourceInfo.url, preloadConfigName, resourceConfigName);
        }
    }

}
</script>