tor-browser

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

early_hint_preload_test_helper.sys.mjs (5424B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { Assert } from "resource://testing-common/Assert.sys.mjs";
      6 import { BrowserTestUtils } from "resource://testing-common/BrowserTestUtils.sys.mjs";
      7 
      8 const { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
      9 
     10 export async function request_count_checking(testName, got, expected) {
     11  // stringify to pretty print assert output
     12  let g = JSON.stringify(got);
     13  let e = JSON.stringify(expected);
     14  // each early hint request can starts one hinted request, but doesn't yet
     15  // complete the early hint request during the test case
     16  Assert.ok(
     17    got.hinted == expected.hinted,
     18    `${testName}: unexpected amount of hinted request made expected ${expected.hinted} (${e}), got ${got.hinted} (${g})`
     19  );
     20  // when the early hint request doesn't complete fast enough, another request
     21  // is currently sent from the main document
     22  let expected_normal = expected.normal;
     23  Assert.ok(
     24    got.normal == expected_normal,
     25    `${testName}: unexpected amount of normal request made expected ${expected_normal} (${e}), got ${got.normal} (${g})`
     26  );
     27 }
     28 
     29 export async function test_hint_preload(
     30  testName,
     31  requestFrom,
     32  imgUrl,
     33  expectedRequestCount,
     34  uuid = undefined
     35 ) {
     36  // generate a uuid if none were passed
     37  if (uuid == undefined) {
     38    uuid = Services.uuid.generateUUID();
     39  }
     40  await test_hint_preload_internal(
     41    testName,
     42    requestFrom,
     43    [[imgUrl, uuid.toString()]],
     44    expectedRequestCount
     45  );
     46 }
     47 
     48 // - testName is just there to be printed during Asserts when failing
     49 // - the baseUrl can't have query strings, because they are currently used to pass
     50 //   the early hint the server responds with
     51 // - urls are in the form [[url1, uuid1], ...]. The uuids are there to make each preload
     52 //   unique and not available in the cache from other test cases
     53 // - expectedRequestCount is the sum of all requested objects { normal: count, hinted: count }
     54 export async function test_hint_preload_internal(
     55  testName,
     56  requestFrom,
     57  imgUrls,
     58  expectedRequestCount
     59 ) {
     60  // reset the count
     61  let headers = new Headers();
     62  headers.append("X-Early-Hint-Count-Start", "");
     63  await fetch(
     64    "http://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs",
     65    { headers }
     66  );
     67 
     68  let requestUrl =
     69    requestFrom +
     70    "/browser/netwerk/test/browser/early_hint_main_html.sjs?" +
     71    new URLSearchParams(imgUrls).toString(); // encode the hinted images as query string
     72 
     73  await BrowserTestUtils.withNewTab(
     74    {
     75      gBrowser,
     76      url: requestUrl,
     77      waitForLoad: true,
     78    },
     79    async function () {}
     80  );
     81 
     82  let gotRequestCount = await fetch(
     83    "http://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs"
     84  ).then(response => response.json());
     85 
     86  await request_count_checking(testName, gotRequestCount, expectedRequestCount);
     87 }
     88 
     89 // Verify that CSP policies in both the 103 response as well as the main response are respected.
     90 // e.g.
     91 // 103 Early Hint
     92 // Content-Security-Policy: style-src: self;
     93 // Link: </style.css>; rel=preload; as=style
     94 // 200 OK
     95 // Content-Security-Policy: style-src: none;
     96 // Link: </font.ttf>; rel=preload; as=font
     97 
     98 // Server-side we verify that:
     99 //  - the hinted preload request was made as expected
    100 //  - the load request request was made as expected
    101 // Client-side, we verify that the image was loaded or not loaded, depending on the scenario
    102 
    103 // This verifies preload hints and requests
    104 export async function test_preload_hint_and_request(input, expected_results) {
    105  // reset the count
    106  let headers = new Headers();
    107  headers.append("X-Early-Hint-Count-Start", "");
    108  await fetch(
    109    "https://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs",
    110    { headers }
    111  );
    112 
    113  let requestUrl = `https://example.com/browser/netwerk/test/browser/early_hint_csp_options_html.sjs?as=${
    114    input.resource_type
    115  }&hinted=${input.hinted ? "1" : "0"}${input.csp ? "&csp=" + input.csp : ""}${
    116    input.csp_in_early_hint
    117      ? "&csp_in_early_hint=" + input.csp_in_early_hint
    118      : ""
    119  }${input.host ? "&host=" + input.host : ""}`;
    120 
    121  await BrowserTestUtils.openNewForegroundTab(gBrowser, requestUrl, true);
    122 
    123  let gotRequestCount = await fetch(
    124    "https://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs"
    125  ).then(response => response.json());
    126 
    127  await Assert.deepEqual(gotRequestCount, expected_results, input.test_name);
    128 
    129  gBrowser.removeCurrentTab();
    130  Services.cache2.clear();
    131 }
    132 
    133 // simple loading of one url and then checking the request count against the
    134 // passed expected count
    135 export async function test_preload_url(testName, url, expectedRequestCount) {
    136  // reset the count
    137  let headers = new Headers();
    138  headers.append("X-Early-Hint-Count-Start", "");
    139  await fetch(
    140    "http://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs",
    141    { headers }
    142  );
    143 
    144  await BrowserTestUtils.withNewTab(
    145    {
    146      gBrowser,
    147      url,
    148      waitForLoad: true,
    149    },
    150    async function () {}
    151  );
    152 
    153  let gotRequestCount = await fetch(
    154    "http://example.com/browser/netwerk/test/browser/early_hint_pixel_count.sjs"
    155  ).then(response => response.json());
    156 
    157  await request_count_checking(testName, gotRequestCount, expectedRequestCount);
    158  Services.cache2.clear();
    159 }