tor-browser

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

test_channel_id.js (3429B)


      1 const { HttpServer } = ChromeUtils.importESModule(
      2  "resource://testing-common/httpd.sys.mjs"
      3 );
      4 
      5 /*
      6 * Test that when doing HTTP requests, the nsIHttpChannel is detected in
      7 * both parent and child and shares the same channelId across processes.
      8 */
      9 
     10 let httpserver;
     11 let port;
     12 
     13 function startHttpServer() {
     14  httpserver = new HttpServer();
     15 
     16  httpserver.registerPathHandler("/resource", (metadata, response) => {
     17    response.setStatusLine(metadata.httpVersion, 200, "OK");
     18    response.setHeader("Content-Type", "text/plain", false);
     19    response.setHeader("Cache-Control", "no-cache", false);
     20    response.bodyOutputStream.write("data", 4);
     21  });
     22 
     23  httpserver.registerPathHandler("/redirect", (metadata, response) => {
     24    response.setStatusLine(metadata.httpVersion, 302, "Redirect");
     25    response.setHeader("Location", "/resource", false);
     26    response.setHeader("Cache-Control", "no-cache", false);
     27  });
     28 
     29  httpserver.start(-1);
     30  port = httpserver.identity.primaryPort;
     31 }
     32 
     33 function stopHttpServer(next) {
     34  httpserver.stop(next);
     35 }
     36 
     37 let expectedParentChannels = [];
     38 let expectedChildMessages = [];
     39 
     40 let maybeFinishWaitForParentChannels;
     41 let parentChannelsDone = new Promise(resolve => {
     42  maybeFinishWaitForParentChannels = () => {
     43    if (!expectedParentChannels.length) {
     44      dump("All expected parent channels were detected\n");
     45      resolve();
     46    }
     47  };
     48 });
     49 
     50 function observer(subject) {
     51  let channel = subject.QueryInterface(Ci.nsIHttpChannel);
     52 
     53  let uri = channel.URI.spec;
     54  let origUri = channel.originalURI.spec;
     55  let id = channel.channelId;
     56  dump(`Parent detected channel: ${uri} (orig=${origUri}): channelId=${id}\n`);
     57 
     58  // did we expect a new channel?
     59  let expected = expectedParentChannels.shift();
     60  Assert.ok(!!expected);
     61 
     62  // Start waiting for the messages about request/response from child
     63  for (let event of expected) {
     64    let message = `${event}:${id}`;
     65    dump(`Expecting message from child: ${message}\n`);
     66 
     67    let messagePromise = do_await_remote_message(message).then(() => {
     68      dump(`Expected message from child arrived: ${message}\n`);
     69    });
     70    expectedChildMessages.push(messagePromise);
     71  }
     72 
     73  // If we don't expect any further parent channels, finish the parent wait
     74  maybeFinishWaitForParentChannels();
     75 }
     76 
     77 function run_test() {
     78  startHttpServer();
     79  Services.obs.addObserver(observer, "http-on-modify-request");
     80  run_test_in_child("child_channel_id.js", makeRequests);
     81 }
     82 
     83 function makeRequests() {
     84  // First, a normal request without any redirect. Expect one channel detected
     85  // in parent, used by both request and response.
     86  expectedParentChannels.push(["request", "response"]);
     87  sendCommand(`makeRequest("http://localhost:${port}/resource");`);
     88 
     89  // Second request will be redirected. Expect two channels, one with the
     90  // original request, then the redirected one which gets the final response.
     91  expectedParentChannels.push(["request"], ["response"]);
     92  sendCommand(`makeRequest("http://localhost:${port}/redirect");`);
     93 
     94  waitForParentChannels();
     95 }
     96 
     97 function waitForParentChannels() {
     98  parentChannelsDone.then(waitForChildMessages);
     99 }
    100 
    101 function waitForChildMessages() {
    102  dump(`Waiting for ${expectedChildMessages.length} child messages\n`);
    103  Promise.all(expectedChildMessages).then(finish);
    104 }
    105 
    106 function finish() {
    107  Services.obs.removeObserver(observer, "http-on-modify-request");
    108  sendCommand("finish();", () => stopHttpServer(do_test_finished));
    109 }