1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
/**
* 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.
*/
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";
if (success) {
link.onload = t.step_func_done(() => {});
link.onerror = t.step_func_done(() => assert_unreached(`error fired when load expected: ${href}`) );
} else {
link.onerror = t.step_func_done(() => {});
link.onload = t.step_func_done(() => assert_unreached(`load fired when error expected: ${href}`) );
}
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)");
}
|