tor-browser

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

test_networking_over_socket_process.js (4795B)


      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 const { TestUtils } = ChromeUtils.importESModule(
     11  "resource://testing-common/TestUtils.sys.mjs"
     12 );
     13 
     14 let h2Port;
     15 let trrServer;
     16 
     17 const certOverrideService = Cc[
     18  "@mozilla.org/security/certoverride;1"
     19 ].getService(Ci.nsICertOverrideService);
     20 
     21 function setup() {
     22  Services.prefs.setIntPref("network.max_socket_process_failed_count", 2);
     23  trr_test_setup();
     24 
     25  h2Port = Services.env.get("MOZHTTP2_PORT");
     26  Assert.notEqual(h2Port, null);
     27  Assert.notEqual(h2Port, "");
     28 
     29  Assert.ok(mozinfo.socketprocess_networking);
     30 }
     31 
     32 setup();
     33 registerCleanupFunction(async () => {
     34  Services.prefs.clearUserPref("network.max_socket_process_failed_count");
     35  trr_clear_prefs();
     36  if (trrServer) {
     37    await trrServer.stop();
     38  }
     39 });
     40 
     41 function makeChan(url) {
     42  let chan = NetUtil.newChannel({
     43    uri: url,
     44    loadUsingSystemPrincipal: true,
     45    contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
     46  }).QueryInterface(Ci.nsIHttpChannel);
     47  return chan;
     48 }
     49 
     50 function channelOpenPromise(chan, flags) {
     51  return new Promise(resolve => {
     52    function finish(req, buffer) {
     53      resolve([req, buffer]);
     54      certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
     55        false
     56      );
     57    }
     58    certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
     59      true
     60    );
     61    chan.asyncOpen(new ChannelListener(finish, null, flags));
     62  });
     63 }
     64 
     65 add_task(async function setupTRRServer() {
     66  trrServer = new TRRServer();
     67  await trrServer.start();
     68 
     69  Services.prefs.setIntPref("network.trr.mode", 3);
     70  Services.prefs.setCharPref(
     71    "network.trr.uri",
     72    `https://foo.example.com:${trrServer.port()}/dns-query`
     73  );
     74 
     75  // Only the last record is valid to use.
     76  await trrServer.registerDoHAnswers("test.example.com", "HTTPS", {
     77    answers: [
     78      {
     79        name: "test.example.com",
     80        ttl: 55,
     81        type: "HTTPS",
     82        flush: false,
     83        data: {
     84          priority: 1,
     85          name: "test.example.com",
     86          values: [
     87            { key: "alpn", value: ["h2"] },
     88            { key: "port", value: h2Port },
     89          ],
     90        },
     91      },
     92    ],
     93  });
     94 
     95  await trrServer.registerDoHAnswers("test.example.com", "A", {
     96    answers: [
     97      {
     98        name: "test.example.com",
     99        ttl: 55,
    100        type: "A",
    101        flush: false,
    102        data: "127.0.0.1",
    103      },
    104    ],
    105  });
    106 });
    107 
    108 async function doTestSimpleRequest(fromSocketProcess) {
    109  let { inRecord } = await new TRRDNSListener("test.example.com", "127.0.0.1");
    110  inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
    111  Assert.equal(inRecord.resolvedInSocketProcess(), fromSocketProcess);
    112 
    113  let chan = makeChan(`https://test.example.com/server-timing`);
    114  let [req] = await channelOpenPromise(chan);
    115  // Test if this request is done by h2.
    116  Assert.equal(req.getResponseHeader("x-connection-http2"), "yes");
    117 
    118  let internal = chan.QueryInterface(Ci.nsIHttpChannelInternal);
    119  Assert.equal(internal.isLoadedBySocketProcess, fromSocketProcess);
    120 }
    121 
    122 // Test if the data is loaded from socket process.
    123 add_task(async function testSimpleRequest() {
    124  await doTestSimpleRequest(true);
    125 });
    126 
    127 function killSocketProcess(pid) {
    128  const ProcessTools = Cc["@mozilla.org/processtools-service;1"].getService(
    129    Ci.nsIProcessToolsService
    130  );
    131  ProcessTools.kill(pid);
    132 }
    133 
    134 // Test if socket process is restarted.
    135 add_task(async function testSimpleRequestAfterCrash() {
    136  let socketProcessId = Services.io.socketProcessId;
    137  info(`socket process pid is ${socketProcessId}`);
    138  Assert.notEqual(socketProcessId, 0);
    139 
    140  killSocketProcess(socketProcessId);
    141 
    142  info("wait socket process restart...");
    143  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
    144  await new Promise(resolve => setTimeout(resolve, 1000));
    145  Services.dns; // Needed to trigger socket process.
    146  await TestUtils.waitForCondition(() => Services.io.socketProcessLaunched);
    147 
    148  await doTestSimpleRequest(true);
    149 });
    150 
    151 // Test if data is loaded from parent process.
    152 add_task(async function testTooManyCrashes() {
    153  let socketProcessId = Services.io.socketProcessId;
    154  info(`socket process pid is ${socketProcessId}`);
    155  Assert.notEqual(socketProcessId, 0);
    156 
    157  let socketProcessCrashed = false;
    158  Services.obs.addObserver(function observe(subject, topic) {
    159    Services.obs.removeObserver(observe, topic);
    160    socketProcessCrashed = true;
    161  }, "network:socket-process-crashed");
    162 
    163  killSocketProcess(socketProcessId);
    164  await TestUtils.waitForCondition(() => socketProcessCrashed);
    165  await doTestSimpleRequest(false);
    166 });