tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

out-of-document-rule-set.https.html (9137B)


      1 <!DOCTYPE html>
      2 <script src="/resources/testharness.js"></script>
      3 <script src="/resources/testharnessreport.js"></script>
      4 <script src="/common/dispatcher/dispatcher.js"></script>
      5 <script src="/common/subset-tests-by-key.js"></script>
      6 <script src="/common/utils.js"></script>
      7 <script src="/common/get-host-info.sub.js"></script>
      8 <script src="../resources/utils.js"></script>
      9 <script src="resources/utils.sub.js"></script>
     10 
     11 <meta name="variant" content="?include=BaseCase">
     12 <meta name="variant" content="?include=FollowRedirect">
     13 <meta name="variant" content="?include=RelativeUrlForSpeculationRulesSet">
     14 <meta name="variant" content="?include=RelativeUrlForCandidate">
     15 <meta name="variant" content="?include=UseNonUTF8EncodingForSpeculationRulesSet">
     16 <meta name="variant" content="?include=FailCORS">
     17 <meta name="variant" content="?include=FailToParseSpeculationRulesHeader">
     18 <meta name="variant" content="?include=InnerListInSpeculationRulesHeader">
     19 <meta name="variant" content="?include=EmptyRuleSet">
     20 <meta name="variant" content="?include=FailToParseRuleSet">
     21 <meta name="variant" content="?include=InvalidUrlForSpeculationRulesSet">
     22 <meta name="variant" content="?include=StatusCode199">
     23 <meta name="variant" content="?include=StatusCode404">
     24 <meta name="variant" content="?include=InvalidMimeType">
     25 <meta name="variant" content="?include=CSPExemption">
     26 
     27 <script>
     28  setup(() => assertSpeculationRulesIsSupported());
     29 
     30  async function runSpeculationRulesFetchTest(t, options) {
     31    options = {
     32      // Whether a prefetch is expected to succeed.
     33      shouldPrefetch: true,
     34      // Status code to be returned in the response.
     35      status: 200,
     36      // Whether a redirect must be followed to reach the rule set.
     37      redirect: false,
     38      // Whether to use relative URLs for the candidates in the rule set.
     39      useRelativeUrlForCandidate: false,
     40      // Whether to use relative URL for the rule set in SpeculationRules header.
     41      useRelativeUrlForSpeculationRulesSet: false,
     42      // Whether to use UTF-8 encoding for the rule set.
     43      useUtf8EncodingForSpeculationRulesSet: true,
     44      // Whether to force the response to cause a CORS failure.
     45      failCors: false,
     46      // Whether to use a valid SpeculationRules header format.
     47      useValidSpeculationRulesHeaderValue: true,
     48      // Whether to use an inner list of URLS in SpeculationRules header.
     49      useInnerListInSpeculationRulesHeaderValue: false,
     50      // Whether to return an empty response.
     51      useEmptySpeculationRulesSet: false,
     52      // Wheter to return a rule set with valid JSON format
     53      useValidJsonForSpeculationRulesSet: true,
     54      // Wheter to use a valid URL for the rule set in SpeculationRules header.
     55      useValidUrlForSpeculationRulesSet: true,
     56      // Wheter to use the valid "application/speculationrules-json" MIME type for the rule set.
     57      useValidMimeTypeForSpeculationRulesSet: true,
     58      // Whether to use a strict CSP for the main page.
     59      strictCSP: false,
     60      ...options
     61    };
     62 
     63    let page = 2;
     64    let uuid = token();
     65    let executor_url = new URL(`executor.sub.html`, SR_PREFETCH_UTILS_URL).toString();
     66    if (options.useRelativeUrlForCandidate) {
     67      executor_url = `executor.sub.html`;
     68    }
     69    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}`;
     70    if (!options.useRelativeUrlForSpeculationRulesSet) {
     71      let base_url = new URL(SR_PREFETCH_UTILS_URL);
     72      base_url.hostname = get_host_info().NOTSAMESITE_HOST;
     73      speculation_rule_set_url = new URL(speculation_rule_set_url, base_url).toString();
     74    }
     75    if (!options.useValidUrlForSpeculationRulesSet) {
     76      speculation_rule_set_url = "http://:80/";
     77    }
     78 
     79    let speculation_rules_header = `header(Speculation-Rules,"${speculation_rule_set_url}")`;
     80    if (!options.useValidSpeculationRulesHeaderValue) {
     81      speculation_rules_header = `header(Speculation-Rules, x y z)`;
     82    }
     83    else if (options.useInnerListInSpeculationRulesHeaderValue) {
     84      speculation_rules_header =  `header(Speculation-Rules, \\("${speculation_rule_set_url}" "xyz.com/rule-set.json"\\))`;
     85    }
     86    if (options.strictCSP) {
     87      speculation_rules_header = speculation_rules_header + `|header(Content-Security-Policy, script-src 'strict-dynamic' 'nonce-abc' 'unsafe-eval')`;
     88    }
     89 
     90    let agent = await spawnWindow(t, {pipe: speculation_rules_header}, uuid);
     91    await new Promise(resolve => t.step_timeout(resolve, 2000));
     92    // 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
     93    let nextUrl = agent.getExecutorURL({ page, str: decodeURIComponent('%C3%B7')});
     94    await agent.navigate(nextUrl);
     95 
     96    await new Promise(resolve => t.step_timeout(resolve, 2000));
     97 
     98    let test_case_desc = JSON.stringify(options);
     99    if (options.shouldPrefetch)
    100      assert_prefetched(await agent.getRequestHeaders(), `Prefetch should work for request ${test_case_desc}.`);
    101    else
    102      assert_not_prefetched(await agent.getRequestHeaders(), `Prefetch should not work for request ${test_case_desc}.`);
    103  }
    104 
    105  subsetTestByKey('BaseCase', promise_test, async t => {
    106    return runSpeculationRulesFetchTest(t, {});
    107  }, "Base case.");
    108 
    109  subsetTestByKey('FollowRedirect', promise_test, async t => {
    110    return runSpeculationRulesFetchTest(t, {redirect: true});
    111  }, "It should follow redirects and fetch the speculation rules set.");
    112 
    113  subsetTestByKey('RelativeUrlForSpeculationRulesSet', promise_test, async t => {
    114    return runSpeculationRulesFetchTest(t, {useRelativeUrlForSpeculationRulesSet: true});
    115  }, "It should fetch a speculation rules set using its relative URL.");
    116 
    117  subsetTestByKey('RelativeUrlForCandidate', promise_test, async t => {
    118    return runSpeculationRulesFetchTest(t, {useRelativeUrlForCandidate: true, shouldPrefetch: false});
    119  }, "It should resolve the relative candidate URLs in the speculation rules set based on the speculation rules set's URL");
    120 
    121  subsetTestByKey('UseNonUTF8EncodingForSpeculationRulesSet', promise_test, async t => {
    122    return runSpeculationRulesFetchTest(t, {useUtf8EncodingForSpeculationRulesSet: false, shouldPrefetch: false});
    123  }, "The speculation rules set should always be encoded using UTF-8.");
    124 
    125  subsetTestByKey('FailCORS', promise_test, async t => {
    126    return runSpeculationRulesFetchTest(t, {failCors: true, shouldPrefetch: false});
    127  }, "It should reject the speculation rules set if CORS fails.");
    128 
    129  subsetTestByKey('FailToParseSpeculationRulesHeader', promise_test, async t => {
    130    return runSpeculationRulesFetchTest(t, {useValidSpeculationRulesHeaderValue: false, shouldPrefetch: false});
    131  }, "It should reject the speculation rules set if it fails to parse the SpeculationRules header.");
    132 
    133  subsetTestByKey('InnerListInSpeculationRulesHeader', promise_test, async t => {
    134    return runSpeculationRulesFetchTest(t, {useInnerListInSpeculationRulesHeaderValue: true, shouldPrefetch: false});
    135  }, "It should reject the speculation rules passed as inner list in the SpeculationRules header.");
    136 
    137  subsetTestByKey('EmptyRuleSet', promise_test, async t => {
    138    return runSpeculationRulesFetchTest(t, {useEmptySpeculationRulesSet: true, shouldPrefetch: false});
    139  }, "It should reject an empty speculation rules set.");
    140 
    141  subsetTestByKey('FailToParseRuleSet', promise_test, async t => {
    142    return runSpeculationRulesFetchTest(t, {useValidJsonForSpeculationRulesSet: false, shouldPrefetch: false});
    143  }, "It should reject the speculation rules set if it cannot parse it.");
    144 
    145  subsetTestByKey('InvalidUrlForSpeculationRulesSet', promise_test, async t => {
    146    return runSpeculationRulesFetchTest(t, {useValidUrlForSpeculationRulesSet: false, shouldPrefetch: false});
    147  }, "It should reject the speculation rules set with invalid URL.");
    148 
    149  subsetTestByKey('StatusCode199', promise_test, async t => {
    150    return runSpeculationRulesFetchTest(t, {status: 199, shouldPrefetch: false});
    151  }, "It should reject the speculation rules set with unsuccessful status code.");
    152 
    153  subsetTestByKey('StatusCode404', promise_test, async t => {
    154    return runSpeculationRulesFetchTest(t, {status: 404, shouldPrefetch: false});
    155  }, "It should reject the speculation rules set with unsuccessful status code.");
    156 
    157  subsetTestByKey('InvalidMimeType', promise_test, async t => {
    158    return runSpeculationRulesFetchTest(t, {useValidMimeTypeForSpeculationRulesSet: false, shouldPrefetch: false});
    159  }, "It should reject the speculation rules set with invalid MIME type.");
    160 
    161  subsetTestByKey('CSPExemption', promise_test, async t => {
    162    return runSpeculationRulesFetchTest(t, {shouldPrefetch: true, strictCSP: true});
    163  }, "It should accept the speculation rules when the main page has strict CSP.");
    164 
    165 </script>