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
|
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="/common/subset-tests-by-key.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="../resources/utils.js"></script>
<script src="resources/utils.sub.js"></script>
<meta name="variant" content="?include=BaseCase">
<meta name="variant" content="?include=FollowRedirect">
<meta name="variant" content="?include=RelativeUrlForSpeculationRulesSet">
<meta name="variant" content="?include=RelativeUrlForCandidate">
<meta name="variant" content="?include=UseNonUTF8EncodingForSpeculationRulesSet">
<meta name="variant" content="?include=FailCORS">
<meta name="variant" content="?include=FailToParseSpeculationRulesHeader">
<meta name="variant" content="?include=InnerListInSpeculationRulesHeader">
<meta name="variant" content="?include=EmptyRuleSet">
<meta name="variant" content="?include=FailToParseRuleSet">
<meta name="variant" content="?include=InvalidUrlForSpeculationRulesSet">
<meta name="variant" content="?include=StatusCode199">
<meta name="variant" content="?include=StatusCode404">
<meta name="variant" content="?include=InvalidMimeType">
<meta name="variant" content="?include=CSPExemption">
<script>
setup(() => assertSpeculationRulesIsSupported());
async function runSpeculationRulesFetchTest(t, options) {
options = {
// Whether a prefetch is expected to succeed.
shouldPrefetch: true,
// Status code to be returned in the response.
status: 200,
// Whether a redirect must be followed to reach the rule set.
redirect: false,
// Whether to use relative URLs for the candidates in the rule set.
useRelativeUrlForCandidate: false,
// Whether to use relative URL for the rule set in SpeculationRules header.
useRelativeUrlForSpeculationRulesSet: false,
// Whether to use UTF-8 encoding for the rule set.
useUtf8EncodingForSpeculationRulesSet: true,
// Whether to force the response to cause a CORS failure.
failCors: false,
// Whether to use a valid SpeculationRules header format.
useValidSpeculationRulesHeaderValue: true,
// Whether to use an inner list of URLS in SpeculationRules header.
useInnerListInSpeculationRulesHeaderValue: false,
// Whether to return an empty response.
useEmptySpeculationRulesSet: false,
// Wheter to return a rule set with valid JSON format
useValidJsonForSpeculationRulesSet: true,
// Wheter to use a valid URL for the rule set in SpeculationRules header.
useValidUrlForSpeculationRulesSet: true,
// Wheter to use the valid "application/speculationrules-json" MIME type for the rule set.
useValidMimeTypeForSpeculationRulesSet: true,
// Whether to use a strict CSP for the main page.
strictCSP: false,
...options
};
let page = 2;
let uuid = token();
let executor_url = new URL(`executor.sub.html`, SR_PREFETCH_UTILS_URL).toString();
if (options.useRelativeUrlForCandidate) {
executor_url = `executor.sub.html`;
}
let speculation_rule_set_url = `ruleset.py?url=${executor_url}&uuid=${uuid}&page=${page}&status=${options.status}&valid_mime=${options.useValidMimeTypeForSpeculationRulesSet}&valid_json=${options.useValidJsonForSpeculationRulesSet}&empty_json=${options.useEmptySpeculationRulesSet}&fail_cors=${options.failCors}&valid_encoding=${options.useUtf8EncodingForSpeculationRulesSet}&redirect=${options.redirect}`;
if (!options.useRelativeUrlForSpeculationRulesSet) {
let base_url = new URL(SR_PREFETCH_UTILS_URL);
base_url.hostname = get_host_info().NOTSAMESITE_HOST;
speculation_rule_set_url = new URL(speculation_rule_set_url, base_url).toString();
}
if (!options.useValidUrlForSpeculationRulesSet) {
speculation_rule_set_url = "http://:80/";
}
let speculation_rules_header = `header(Speculation-Rules,"${speculation_rule_set_url}")`;
if (!options.useValidSpeculationRulesHeaderValue) {
speculation_rules_header = `header(Speculation-Rules, x y z)`;
}
else if (options.useInnerListInSpeculationRulesHeaderValue) {
speculation_rules_header = `header(Speculation-Rules, \\("${speculation_rule_set_url}" "xyz.com/rule-set.json"\\))`;
}
if (options.strictCSP) {
speculation_rules_header = speculation_rules_header + `|header(Content-Security-Policy, script-src 'strict-dynamic' 'nonce-abc' 'unsafe-eval')`;
}
let agent = await spawnWindow(t, {pipe: speculation_rules_header}, uuid);
await new Promise(resolve => t.step_timeout(resolve, 2000));
// Passing non-ascii character 'รท' as part of the next URL to check if we always decode the speculation rules set using utf-8 or not. This character is encoded differently in utf-8 and windows-1250
let nextUrl = agent.getExecutorURL({ page, str: decodeURIComponent('%C3%B7')});
await agent.navigate(nextUrl);
await new Promise(resolve => t.step_timeout(resolve, 2000));
let test_case_desc = JSON.stringify(options);
if (options.shouldPrefetch)
assert_prefetched(await agent.getRequestHeaders(), `Prefetch should work for request ${test_case_desc}.`);
else
assert_not_prefetched(await agent.getRequestHeaders(), `Prefetch should not work for request ${test_case_desc}.`);
}
subsetTestByKey('BaseCase', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {});
}, "Base case.");
subsetTestByKey('FollowRedirect', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {redirect: true});
}, "It should follow redirects and fetch the speculation rules set.");
subsetTestByKey('RelativeUrlForSpeculationRulesSet', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {useRelativeUrlForSpeculationRulesSet: true});
}, "It should fetch a speculation rules set using its relative URL.");
subsetTestByKey('RelativeUrlForCandidate', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {useRelativeUrlForCandidate: true, shouldPrefetch: false});
}, "It should resolve the relative candidate URLs in the speculation rules set based on the speculation rules set's URL");
subsetTestByKey('UseNonUTF8EncodingForSpeculationRulesSet', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {useUtf8EncodingForSpeculationRulesSet: false, shouldPrefetch: false});
}, "The speculation rules set should always be encoded using UTF-8.");
subsetTestByKey('FailCORS', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {failCors: true, shouldPrefetch: false});
}, "It should reject the speculation rules set if CORS fails.");
subsetTestByKey('FailToParseSpeculationRulesHeader', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {useValidSpeculationRulesHeaderValue: false, shouldPrefetch: false});
}, "It should reject the speculation rules set if it fails to parse the SpeculationRules header.");
subsetTestByKey('InnerListInSpeculationRulesHeader', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {useInnerListInSpeculationRulesHeaderValue: true, shouldPrefetch: false});
}, "It should reject the speculation rules passed as inner list in the SpeculationRules header.");
subsetTestByKey('EmptyRuleSet', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {useEmptySpeculationRulesSet: true, shouldPrefetch: false});
}, "It should reject an empty speculation rules set.");
subsetTestByKey('FailToParseRuleSet', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {useValidJsonForSpeculationRulesSet: false, shouldPrefetch: false});
}, "It should reject the speculation rules set if it cannot parse it.");
subsetTestByKey('InvalidUrlForSpeculationRulesSet', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {useValidUrlForSpeculationRulesSet: false, shouldPrefetch: false});
}, "It should reject the speculation rules set with invalid URL.");
subsetTestByKey('StatusCode199', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {status: 199, shouldPrefetch: false});
}, "It should reject the speculation rules set with unsuccessful status code.");
subsetTestByKey('StatusCode404', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {status: 404, shouldPrefetch: false});
}, "It should reject the speculation rules set with unsuccessful status code.");
subsetTestByKey('InvalidMimeType', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {useValidMimeTypeForSpeculationRulesSet: false, shouldPrefetch: false});
}, "It should reject the speculation rules set with invalid MIME type.");
subsetTestByKey('CSPExemption', promise_test, async t => {
return runSpeculationRulesFetchTest(t, {shouldPrefetch: true, strictCSP: true});
}, "It should accept the speculation rules when the main page has strict CSP.");
</script>
|