tor-browser

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

test_verify_traffic.js (4797B)


      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 /* import-globals-from head_cache.js */
      8 /* import-globals-from head_cookies.js */
      9 /* import-globals-from head_channels.js */
     10 
     11 const gDashboard = Cc["@mozilla.org/network/dashboard;1"].getService(
     12  Ci.nsIDashboard
     13 );
     14 
     15 const { NodeHTTP2Server } = ChromeUtils.importESModule(
     16  "resource://testing-common/NodeServer.sys.mjs"
     17 );
     18 
     19 const { TestUtils } = ChromeUtils.importESModule(
     20  "resource://testing-common/TestUtils.sys.mjs"
     21 );
     22 
     23 function makeChan(uri) {
     24  let chan = NetUtil.newChannel({
     25    uri,
     26    loadUsingSystemPrincipal: true,
     27  }).QueryInterface(Ci.nsIHttpChannel);
     28  chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
     29  return chan;
     30 }
     31 
     32 function channelOpenPromise(chan, flags) {
     33  return new Promise(resolve => {
     34    function finish(req, buffer) {
     35      resolve([req, buffer]);
     36    }
     37    chan.asyncOpen(new ChannelListener(finish, null, flags));
     38  });
     39 }
     40 
     41 async function registerSimplePathHandler(server, path) {
     42  return server.registerPathHandler(path, (req, resp) => {
     43    resp.writeHead(200);
     44    resp.end("done");
     45  });
     46 }
     47 
     48 add_task(async function test_verify_traffic_for_http2() {
     49  Services.prefs.setBoolPref(
     50    "network.http.http2.move_to_pending_list_after_network_change",
     51    true
     52  );
     53 
     54  // Bug 1878505: It seems when HTTPS RR is enabled, a speculative
     55  // connection that waits to receive a HTTPS response will receive it
     56  // after the actual connection is established, leading to an extra
     57  // connection being established.
     58  Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
     59 
     60  let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
     61    Ci.nsIX509CertDB
     62  );
     63  addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
     64 
     65  let server = new NodeHTTP2Server();
     66  await server.start();
     67  registerCleanupFunction(async () => {
     68    Services.prefs.clearUserPref(
     69      "network.http.http2.move_to_pending_list_after_network_change"
     70    );
     71    await server.stop();
     72  });
     73 
     74  try {
     75    await server.registerPathHandler("/longDelay", (req, resp) => {
     76      // eslint-disable-next-line mozilla/no-arbitrary-setTimeout, no-undef
     77      setTimeout(function () {
     78        resp.writeHead(200);
     79        resp.end("done");
     80      }, 8000);
     81    });
     82  } catch (e) {}
     83 
     84  await registerSimplePathHandler(server, "/test");
     85 
     86  // Send some requests and check if we have only one h2 session.
     87  for (let i = 0; i < 2; i++) {
     88    let chan = makeChan(`https://localhost:${server.port()}/test`);
     89    await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL);
     90  }
     91  let sessionCount = await server.sessionCount();
     92  Assert.equal(sessionCount, 1);
     93 
     94  let res = await new Promise(resolve => {
     95    // Create a request that takes 8s to finish.
     96    let chan = makeChan(`https://localhost:${server.port()}/longDelay`);
     97    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
     98 
     99    // Send a network change event to trigger VerifyTraffic(). After this,
    100    // the connnection will be put in the pending list.
    101    // We'll crate a new connection for the new request.
    102    Services.obs.notifyObservers(
    103      null,
    104      "network:link-status-changed",
    105      "changed"
    106    );
    107 
    108    // This request will use the new connection.
    109    let chan1 = makeChan(`https://localhost:${server.port()}/test`);
    110    chan1.asyncOpen(new ChannelListener(() => {}, null, CL_ALLOW_UNKNOWN_CL));
    111  });
    112 
    113  // The connection in the pending list should be still working.
    114  Assert.equal(res.status, Cr.NS_OK);
    115  Assert.equal(res.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    116 
    117  sessionCount = await server.sessionCount();
    118  Assert.equal(sessionCount, 2);
    119 
    120  // Create another request and trigger the network change event again.
    121  // The second network change event is to put the second connection into the
    122  // pending list.
    123  res = await new Promise(resolve => {
    124    // Create a request that takes 8s to finish.
    125    let chan = makeChan(`https://localhost:${server.port()}/longDelay`);
    126    chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
    127 
    128    Services.obs.notifyObservers(
    129      null,
    130      "network:link-status-changed",
    131      "changed"
    132    );
    133  });
    134 
    135  Assert.equal(res.status, Cr.NS_OK);
    136  Assert.equal(res.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    137 
    138  async function getSocketCount() {
    139    return new Promise(resolve => {
    140      gDashboard.requestSockets(function (data) {
    141        resolve(data.sockets.length);
    142      });
    143    });
    144  }
    145 
    146  await TestUtils.waitForCondition(async () => {
    147    const socketCount = await getSocketCount();
    148    return socketCount === 0;
    149  }, "Socket count should be 0");
    150 
    151  await server.stop();
    152 });