blob: 33c8709579e3b341b5455e73780244c6d8bb1704 [file] [log] [blame]
/**
* This is the guts of the load/error event tests for <link rel="stylesheet">.
*
* We have a list of tests each of which is an object containing: href value,
* expected load success boolean, test description. Href values are set up in
* such a way that we guarantee that all stylesheet URLs are unique. This
* avoids issues around caching of sheets based on URL.
*/
// Our URLs are random, so we don't use them in error messages by
// default, but enable doing it if someone wants to debug things.
const DEBUG_URLS = false;
var isHttps = location.protocol == "https:";
var tests = [
// Basic tests
{
href: existingSheet(),
success: true,
description: "Basic load of stylesheet",
},
{
href: nonexistentSheet(),
success: false,
description: "Attempted load of nonexistent stylesheet",
},
{
href: `data:text/css,@import url("${existingSheet()}")`,
success: true,
description: "Import of stylesheet",
},
{
href: `data:text/css,@import url("${nonexistentSheet()}")`,
success: false,
description: "Import of nonexistent stylesheet",
},
{
href: `data:text/css,@import url("data:text/css,@import url('${existingSheet()}')")`,
success: true,
description: "Import of import of stylesheet",
},
{
href: `data:text/css,@import url("data:text/css,@import url('${nonexistentSheet()}')")`,
success: false,
description: "Import of import of nonexistent stylesheet",
},
// Non-CSS-response tests.
{
href: makeUnique(""),
success: false,
description: "Load of non-CSS stylesheet",
},
{
href: `data:text/css,@import url("${makeUnique("")}")`,
success: false,
description: "Import of non-CSS stylesheet",
},
{
href: `data:text/css,@import url("data:text/css,@import url('${makeUnique("")}')")`,
success: false,
description: "Import of import of non-CSS stylesheet",
},
// http:// tests, to test what happens with mixed content blocking.
{
href: httpSheet(),
success: !isHttps,
description: "Load of http:// stylesheet",
},
{
href: `data:text/css,@import url("${httpSheet()}")`,
success: !isHttps,
description: "Import of http:// stylesheet",
},
{
href: `data:text/css,@import url("data:text/css,@import url('${httpSheet()}')")`,
success: !isHttps,
description: "Import of import of http:// stylesheet",
},
// https:// tests just as a control
{
href: httpsSheet(),
success: true,
description: "Load of https:// stylesheet",
},
{
href: `data:text/css,@import url("${httpsSheet()}")`,
success: true,
description: "Import of https:// stylesheet",
},
{
href: `data:text/css,@import url("data:text/css,@import url('${httpsSheet()}')")`,
success: true,
description: "Import of import of https:// stylesheet",
},
// Tests with multiple imports some of which are slow and some are fast.
{
href: `data:text/css,@import url("${slowResponse(existingSheet())}"); @import url("${nonexistentSheet()}");`,
success: false,
description: "Slow successful import, fast failing import",
},
{
href: `data:text/css,@import url("${existingSheet()}"); @import url("${slowResponse(nonexistentSheet())}");`,
success: false,
description: "Fast successful import, slow failing import",
}
];
// Note: Here we really do need to use "let" at least for the href,
// because we lazily evaluate it in the unreached cases.
for (var test of tests) {
let {href, success, description} = test;
var t = async_test(description);
var link = document.createElement("link");
link.rel = "stylesheet";
hrefString = DEBUG_URLS ? `: ${href}` : "";
if (success) {
link.onload = t.step_func_done(() => {});
link.onerror = t.step_func_done(() => assert_unreached(`error fired when load expected${hrefString}`) );
} else {
link.onerror = t.step_func_done(() => {});
link.onload = t.step_func_done(() => assert_unreached(`load fired when error expected${hrefString}`) );
}
link.href = href;
document.head.appendChild(link);
}
/* Utility function */
function makeUnique(url) {
// Make sure we copy here, even if the thing coming in is a URL, so we don't
// mutate our caller's data.
url = new URL(url, location.href);
// We want to generate a unique URI to avoid the various caches browsers have
// for stylesheets. We don't want to just use a counter, because that would
// not be robust to the test being reloaded or othewise run multiple times
// without a browser restart. We don't want to use timstamps, because those
// are not likely to be unique across calls to this function, especially given
// the degraded timer resolution browsers have due to Spectre.
//
// So just fall back on Math.random() and assume it can't duplicate values.
url.searchParams.append("r", Math.random());
return url;
}
function existingSheet() {
return makeUnique("resources/good.css");
}
/**
* Function the add values to the "pipe" search param. See
* http://wptserve.readthedocs.io/en/latest/pipes.html for why one would do
* this. Because this param uses a weird '|'-separated syntax instead of just
* using multiple params with the same name, we need some manual code to munge
* the value properly.
*/
function addPipe(url, pipeVal) {
url = new URL(url, location.href);
var params = url.searchParams;
var oldVal = params.get("pipe");
if (oldVal) {
params.set("pipe", oldVal + "|" + pipeVal);
} else {
params.set("pipe", pipeVal);
}
return url;
}
function nonexistentSheet() {
return addPipe(existingSheet(), "status(404)");
}
function httpSheet() {
var url = existingSheet();
url.protocol = "http";
url.port = {{ports[http][0]}};
return url;
}
function httpsSheet() {
var url = existingSheet();
url.protocol = "https";
url.port = {{ports[https][0]}};
return url;
}
function slowResponse(url) {
return addPipe(url, "trickle(d1)");
}