tor-browser

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

test_bug1948203.js (5881B)


      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 "use strict";
      6 
      7 var { setTimeout } = ChromeUtils.importESModule(
      8  "resource://gre/modules/Timer.sys.mjs"
      9 );
     10 
     11 let trrServer;
     12 let h3Port;
     13 let host;
     14 
     15 add_setup(async function setup() {
     16  trr_test_setup();
     17 
     18  h3Port = Services.env.get("MOZHTTP3_PORT_ECH");
     19  Assert.notEqual(h3Port, null);
     20  Assert.notEqual(h3Port, "");
     21 
     22  host = `https://alt1.example.com:${h3Port}/`;
     23 
     24  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
     25 });
     26 
     27 registerCleanupFunction(async () => {
     28  trr_clear_prefs();
     29  if (trrServer) {
     30    await trrServer.stop();
     31  }
     32 });
     33 
     34 function makeChan(url) {
     35  let chan = NetUtil.newChannel({
     36    uri: url,
     37    loadUsingSystemPrincipal: true,
     38    contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
     39  }).QueryInterface(Ci.nsIHttpChannel);
     40  return chan;
     41 }
     42 
     43 function channelOpenPromise(chan, flags) {
     44  return new Promise(resolve => {
     45    function finish(req, buffer) {
     46      resolve([req, buffer]);
     47    }
     48    chan.asyncOpen(new ChannelListener(finish, null, flags));
     49  });
     50 }
     51 
     52 function ActivityObserver() {
     53  this.activites = [];
     54 }
     55 
     56 ActivityObserver.prototype = {
     57  activites: [],
     58  observeActivity(
     59    aHttpChannel,
     60    aActivityType,
     61    aActivitySubtype,
     62    aTimestamp,
     63    aExtraSizeData,
     64    aExtraStringData
     65  ) {
     66    try {
     67      aHttpChannel.QueryInterface(Ci.nsINullChannel);
     68      aHttpChannel.QueryInterface(Ci.nsIChannel);
     69      if (aHttpChannel.URI.spec === host) {
     70        dump(
     71          "*** HTTP Activity 0x" +
     72            aActivityType.toString(16) +
     73            " 0x" +
     74            aActivitySubtype.toString(16) +
     75            " " +
     76            aExtraStringData +
     77            "\n"
     78        );
     79        this.activites.push({ host, subType: aActivitySubtype });
     80      }
     81    } catch (e) {}
     82  },
     83 };
     84 
     85 function checkHttpActivities(activites, expected) {
     86  let foundTransClosed = false;
     87  for (let activity of activites) {
     88    switch (activity.subType) {
     89      case Ci.nsIHttpActivityObserver.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE:
     90        foundTransClosed = true;
     91        break;
     92      default:
     93        break;
     94    }
     95  }
     96 
     97  Assert.equal(
     98    foundTransClosed,
     99    expected,
    100    "The activity of speculative transaction should match"
    101  );
    102 }
    103 // Test steps:
    104 // 1. Create a TRR server that serves the HTTPS record for the H3 server.
    105 // 2. Create a channel and connect to the H3 server.
    106 // 3. Use nsIHttpActivityObserver to observe if we receive the HTTP activity
    107 //    that is sent from the speculative transaction.
    108 async function doTestAltSVCWithHTTPSRR(foundActivity) {
    109  trrServer = new TRRServer();
    110  await trrServer.start();
    111 
    112  let observerService = Cc[
    113    "@mozilla.org/network/http-activity-distributor;1"
    114  ].getService(Ci.nsIHttpActivityDistributor);
    115 
    116  Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRONLY);
    117  Services.prefs.setCharPref(
    118    "network.trr.uri",
    119    `https://foo.example.com:${trrServer.port()}/dns-query`
    120  );
    121 
    122  let portPrefixedName = `_${h3Port}._https.alt1.example.com`;
    123  let vals = [
    124    { key: "alpn", value: "h3" },
    125    { key: "port", value: h3Port },
    126  ];
    127 
    128  await trrServer.registerDoHAnswers(portPrefixedName, "HTTPS", {
    129    answers: [
    130      {
    131        name: portPrefixedName,
    132        ttl: 55,
    133        type: "HTTPS",
    134        flush: false,
    135        data: {
    136          priority: 1,
    137          name: ".",
    138          values: vals,
    139        },
    140      },
    141    ],
    142  });
    143 
    144  await trrServer.registerDoHAnswers("alt1.example.com", "A", {
    145    answers: [
    146      {
    147        name: "alt1.example.com",
    148        ttl: 55,
    149        type: "A",
    150        flush: false,
    151        data: "127.0.0.1",
    152      },
    153    ],
    154  });
    155 
    156  let chan = makeChan(`${host}alt_svc_header`);
    157  let h3AltSvc = ":" + h3Port;
    158  chan.setRequestHeader("x-altsvc", h3AltSvc, false);
    159  let observer = new ActivityObserver();
    160 
    161  let responseObserver = {
    162    QueryInterface: ChromeUtils.generateQI(["nsIObserver"]),
    163    observe(aSubject, aTopic) {
    164      let channel = aSubject.QueryInterface(Ci.nsIChannel);
    165      if (
    166        aTopic == "http-on-examine-response" &&
    167        channel.URI.spec === `${host}alt_svc_header`
    168      ) {
    169        Services.obs.removeObserver(
    170          responseObserver,
    171          "http-on-examine-response"
    172        );
    173 
    174        observerService.addObserver(observer);
    175        channel.suspend();
    176        // We need to close all connections here, otherwise we are not allowed
    177        // to create a specul connection to validate the Alt-svc header.
    178        Services.obs.notifyObservers(null, "net:cancel-all-connections");
    179        // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
    180        setTimeout(function () {
    181          channel.resume();
    182        }, 3000);
    183      }
    184    },
    185  };
    186  Services.obs.addObserver(responseObserver, "http-on-examine-response");
    187 
    188  await channelOpenPromise(chan);
    189 
    190  // Some dekay here to collect HTTP activites.
    191  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
    192  await new Promise(resolve => setTimeout(resolve, 3000));
    193 
    194  checkHttpActivities(observer.activites, foundActivity);
    195 
    196  await trrServer.stop();
    197  observerService.removeObserver(observer);
    198 }
    199 
    200 add_task(async function testAltSVCWithHTTPSRR() {
    201  Services.prefs.setBoolPref(
    202    "network.http.skip_alt_svc_validation_on_https_rr",
    203    false
    204  );
    205 
    206  await doTestAltSVCWithHTTPSRR(true);
    207 
    208  // Clear the alt-svc mapping.
    209  Services.obs.notifyObservers(null, "last-pb-context-exited");
    210  Services.obs.notifyObservers(null, "net:cancel-all-connections");
    211  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
    212  await new Promise(resolve => setTimeout(resolve, 3000));
    213 
    214  Services.prefs.setBoolPref(
    215    "network.http.skip_alt_svc_validation_on_https_rr",
    216    true
    217  );
    218 
    219  await doTestAltSVCWithHTTPSRR(false);
    220 });