tor-browser

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

browser_net_overrides.js (11627B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // This test might take a very long time on slow platforms such as TSAN.
      7 requestLongerTimeout(2);
      8 
      9 /* import-globals-from network-overrides-test-helpers.js */
     10 Services.scriptloader.loadSubScript(
     11  CHROME_URL_ROOT + "network-overrides-test-helpers.js",
     12  this
     13 );
     14 
     15 function clearMemoryCache(browser) {
     16  info("Clearing subresource cache");
     17  return SpecialPowers.spawn(browser, [], () => {
     18    ChromeUtils.clearResourceCache();
     19  });
     20 }
     21 
     22 /**
     23 * Test adding and removing overrides for three resources:
     24 * - HTML file
     25 * - JS file
     26 * - CSS file
     27 */
     28 
     29 async function testHTMLOverrideWithOptions(options) {
     30  const { monitor, tab, document } = await setupNetworkOverridesTest(options);
     31 
     32  let htmlRequest = findRequestByInitiator(document, "document");
     33  ok(
     34    !htmlRequest.querySelector(".requests-list-override"),
     35    "There is no override cell"
     36  );
     37  await assertOverrideColumnStatus(monitor, { visible: false });
     38 
     39  info("Set a network override for the HTML request");
     40  const overrideFileName = `index-override.html`;
     41  const overridePath = await setNetworkOverride(
     42    monitor,
     43    htmlRequest,
     44    overrideFileName,
     45    OVERRIDDEN_HTML
     46  );
     47 
     48  // Assert override column is checked but disabled in context menu
     49  await assertOverrideColumnStatus(monitor, { visible: true });
     50 
     51  // Assert override is only displayed for appropriate request
     52  assertOverrideCellStatus(htmlRequest, { overridden: true });
     53  const overrideCell = htmlRequest.querySelector(".requests-list-override");
     54  ok(
     55    overrideCell.getAttribute("title").includes(overrideFileName),
     56    "The override icon's title contains the overridden path"
     57  );
     58 
     59  const scriptRequest = findRequestByInitiator(document, "script");
     60  assertOverrideCellStatus(scriptRequest, { overridden: false });
     61  const stylesheetRequest = findRequestByInitiator(document, "stylesheet");
     62  assertOverrideCellStatus(stylesheetRequest, { overridden: false });
     63 
     64  info("Reloading to check override is applied on the page");
     65  let waitForEvents = waitForNetworkEvents(monitor, 1);
     66  tab.linkedBrowser.reload();
     67  await waitForEvents;
     68 
     69  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
     70    ok(content.document.body.textContent.includes("Overridden content"));
     71  });
     72 
     73  htmlRequest = findRequestByInitiator(document, "document");
     74  // If the HTML file was properly overridden, reloading the page should only
     75  // create one request, because there is no longer any JS or CSS file loaded
     76  // by the overridden HTML response.
     77  is(
     78    document.querySelectorAll(".request-list-item").length,
     79    1,
     80    "Only one request (html file) - no additional script or stylesheet"
     81  );
     82 
     83  // Assert Response Tab shows the appropriate content
     84  await assertOverriddenResponseTab(document, htmlRequest, overridePath);
     85 
     86  // Remove Network override
     87  await removeNetworkOverride(monitor, htmlRequest);
     88 
     89  await assertOverrideColumnStatus(monitor, { visible: false });
     90  ok(
     91    !htmlRequest.querySelector(".requests-list-override"),
     92    "There is no override cell"
     93  );
     94 
     95  info("Reload again to check the override is no longer applied on the page");
     96  waitForEvents = waitForNetworkEvents(monitor, 3);
     97  tab.linkedBrowser.reload();
     98  await waitForEvents;
     99 
    100  is(
    101    document.querySelectorAll(".request-list-item").length,
    102    3,
    103    "3 requests displayed after removing the override and reloading"
    104  );
    105 
    106  // Assert HTML content is back to normal
    107  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
    108    ok(content.document.body.textContent.includes("Original content"));
    109  });
    110 
    111  return teardown(monitor);
    112 }
    113 
    114 add_task(async function testHTMLOverrideWithoutCache() {
    115  await testHTMLOverrideWithOptions({ enableCache: false });
    116 });
    117 
    118 add_task(async function testHTMLOverrideWithCache() {
    119  await testHTMLOverrideWithOptions({ enableCache: true });
    120 });
    121 
    122 async function testScriptOverrideWithOptions(options) {
    123  const { monitor, tab, document } = await setupNetworkOverridesTest(options);
    124 
    125  async function assertScriptOverrideInContent({ override }) {
    126    await SpecialPowers.spawn(
    127      gBrowser.selectedBrowser,
    128      [override],
    129      _override => {
    130        is(
    131          !!content.document.querySelector("#created-by-original"),
    132          !_override,
    133          `original div should ${!_override ? "" : "not "}be found`
    134        );
    135        is(
    136          !!content.document.querySelector("#created-by-override"),
    137          _override,
    138          `override div should ${_override ? "" : "not "}be found`
    139        );
    140      }
    141    );
    142  }
    143 
    144  let scriptRequest = findRequestByInitiator(document, "script");
    145  ok(
    146    !scriptRequest.querySelector(".requests-list-override"),
    147    "There is no override cell"
    148  );
    149  await assertOverrideColumnStatus(monitor, { visible: false });
    150 
    151  info("Check the original div was created by the script in the content page");
    152  await assertScriptOverrideInContent({ override: false });
    153 
    154  info("Set a network override for the script request");
    155  const overrideFileName = `script-override.js`;
    156  const overridePath = await setNetworkOverride(
    157    monitor,
    158    scriptRequest,
    159    overrideFileName,
    160    OVERRIDDEN_SCRIPT,
    161    // If cache is used and the navigation cache is enabled, the response is
    162    // not available.
    163    Services.prefs.getBoolPref(
    164      "dom.script_loader.experimental.navigation_cache"
    165    ) && options.enableCache
    166  );
    167 
    168  // Assert override column is checked but disabled in context menu
    169  await assertOverrideColumnStatus(monitor, { visible: true });
    170 
    171  // Assert override is only displayed for appropriate request
    172  assertOverrideCellStatus(scriptRequest, { overridden: true });
    173  const overrideCell = scriptRequest.querySelector(".requests-list-override");
    174  ok(
    175    overrideCell.getAttribute("title").includes(overrideFileName),
    176    "The override icon's title contains the overridden path"
    177  );
    178  const htmlRequest = findRequestByInitiator(document, "document");
    179  assertOverrideCellStatus(htmlRequest, { overridden: false });
    180  const stylesheetRequest = findRequestByInitiator(document, "stylesheet");
    181  assertOverrideCellStatus(stylesheetRequest, { overridden: false });
    182 
    183  info("Reloading to check the overridden script is loaded on the page");
    184  let waitForEvents = waitForNetworkEvents(monitor, 3);
    185  tab.linkedBrowser.reload();
    186  await waitForEvents;
    187 
    188  info("Check the override div was created by the script in the content page");
    189  await assertScriptOverrideInContent({ override: true });
    190 
    191  scriptRequest = findRequestByInitiator(document, "script");
    192 
    193  // Assert Response Tab shows the appropriate content
    194  await assertOverriddenResponseTab(document, scriptRequest, overridePath);
    195 
    196  // Remove Network override
    197  await removeNetworkOverride(monitor, scriptRequest);
    198 
    199  await assertOverrideColumnStatus(monitor, { visible: false });
    200  ok(
    201    !scriptRequest.querySelector(".requests-list-override"),
    202    "There is no override cell"
    203  );
    204 
    205  info("Reload again to check the override script is no longer loaded");
    206  waitForEvents = waitForNetworkEvents(monitor, 3);
    207  tab.linkedBrowser.reload();
    208  await waitForEvents;
    209 
    210  info("Check the original div was created by the script in the content page");
    211  await assertScriptOverrideInContent({ override: false });
    212 
    213  return teardown(monitor);
    214 }
    215 
    216 add_task(async function testScriptOverrideWithoutCache() {
    217  await testScriptOverrideWithOptions({ enableCache: false });
    218 });
    219 
    220 add_task(async function testScriptOverrideWithCache() {
    221  await testScriptOverrideWithOptions({ enableCache: true });
    222 });
    223 
    224 async function testStylesheetOverrideWithOptions(options) {
    225  const { monitor, tab, document } = await setupNetworkOverridesTest(options);
    226 
    227  async function assertStylesheetOverrideInContent({ override }) {
    228    await SpecialPowers.spawn(
    229      gBrowser.selectedBrowser,
    230      [override],
    231      _override => {
    232        const body = content.document.body;
    233        const color = content.getComputedStyle(body).color;
    234        is(color, _override ? "rgb(0, 0, 255)" : "rgb(255, 0, 0)");
    235      }
    236    );
    237  }
    238 
    239  let stylesheetRequest = findRequestByInitiator(document, "stylesheet");
    240  ok(
    241    !stylesheetRequest.querySelector(".requests-list-override"),
    242    "There is no override cell"
    243  );
    244  await assertOverrideColumnStatus(monitor, { visible: false });
    245 
    246  info("Check the original div was created by the script in the content page");
    247  await assertStylesheetOverrideInContent({ override: false });
    248 
    249  info("Set a network override for the stylesheet request");
    250  const overrideFileName = `style-override.css`;
    251  const overridePath = await setNetworkOverride(
    252    monitor,
    253    stylesheetRequest,
    254    overrideFileName,
    255    OVERRIDDEN_STYLESHEET,
    256    // If cache is used, the response is not available.
    257    options.enableCache
    258  );
    259 
    260  // Assert override column is checked but disabled in context menu
    261  await assertOverrideColumnStatus(monitor, { visible: true });
    262 
    263  // Assert override is only displayed for appropriate request
    264  assertOverrideCellStatus(stylesheetRequest, { overridden: true });
    265  const overrideCell = stylesheetRequest.querySelector(
    266    ".requests-list-override"
    267  );
    268  ok(
    269    overrideCell.getAttribute("title").includes(overrideFileName),
    270    "The override icon's title contains the overridden path"
    271  );
    272  const htmlRequest = findRequestByInitiator(document, "document");
    273  assertOverrideCellStatus(htmlRequest, { overridden: false });
    274  const scriptRequest = findRequestByInitiator(document, "script");
    275  assertOverrideCellStatus(scriptRequest, { overridden: false });
    276 
    277  await clearMemoryCache(tab.linkedBrowser);
    278 
    279  info("Reloading to check the overridden script is loaded on the page");
    280  let waitForEvents = waitForNetworkEvents(monitor, 3);
    281  tab.linkedBrowser.reload();
    282  await waitForEvents;
    283 
    284  info("Check the overridden stylesheet was loaded in the content page");
    285  await assertStylesheetOverrideInContent({ override: true });
    286 
    287  info("Check the response tab");
    288  stylesheetRequest = findRequestByInitiator(document, "stylesheet");
    289  await assertOverriddenResponseTab(document, stylesheetRequest, overridePath);
    290 
    291  info("Remove the network override");
    292  await removeNetworkOverride(monitor, stylesheetRequest);
    293  await assertOverrideColumnStatus(monitor, { visible: false });
    294  ok(
    295    !stylesheetRequest.querySelector(".requests-list-override"),
    296    "There is no override cell"
    297  );
    298 
    299  await clearMemoryCache(tab.linkedBrowser);
    300 
    301  info("Reload again to check the overridden stylesheet is no longer loaded");
    302  waitForEvents = waitForNetworkEvents(monitor, 3);
    303  tab.linkedBrowser.reload();
    304  await waitForEvents;
    305 
    306  info("Check the original div was created by the script in the content page");
    307  await assertStylesheetOverrideInContent({ override: false });
    308 
    309  return teardown(monitor);
    310 }
    311 
    312 add_task(async function testStylesheetOverrideWithoutCache() {
    313  await testStylesheetOverrideWithOptions({ enableCache: false });
    314 });
    315 
    316 add_task(async function testStylesheetOverrideWithCache() {
    317  await testStylesheetOverrideWithOptions({ enableCache: true });
    318 });
    319 
    320 async function assertOverriddenResponseTab(doc, request, overrideFileName) {
    321  EventUtils.sendMouseEvent({ type: "mousedown" }, request);
    322  await waitFor(
    323    () => doc.querySelector("#response-tab"),
    324    "Wait for the response tab to be displayed"
    325  );
    326  ok(
    327    doc.querySelector(".tab-response-overridden"),
    328    "Response tab is marked as overridden"
    329  );
    330  const responsePanelTab = doc.querySelector("#response-tab");
    331  ok(
    332    responsePanelTab.getAttribute("title").includes(overrideFileName),
    333    "The response panel tab title contains the overridden path"
    334  );
    335 }