/** * This is the guts of the load/error event tests for . * * 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)"); }