tor-browser

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

test_suspend_channel_on_modified.js (4933B)


      1 // This file tests async handling of a channel suspended in http-on-modify-request.
      2 "use strict";
      3 
      4 const { HttpServer } = ChromeUtils.importESModule(
      5  "resource://testing-common/httpd.sys.mjs"
      6 );
      7 
      8 var obs = Services.obs;
      9 
     10 var ios = Services.io;
     11 
     12 // baseUrl is always the initial connection attempt and is handled by
     13 // failResponseHandler since every test expects that request will either be
     14 // redirected or cancelled.
     15 var baseUrl;
     16 
     17 function failResponseHandler(metadata, response) {
     18  var text = "failure response";
     19  response.setHeader("Content-Type", "text/plain", false);
     20  response.bodyOutputStream.write(text, text.length);
     21  Assert.ok(false, "Received request when we shouldn't.");
     22 }
     23 
     24 function successResponseHandler(metadata, response) {
     25  var text = "success response";
     26  response.setHeader("Content-Type", "text/plain", false);
     27  response.bodyOutputStream.write(text, text.length);
     28  Assert.ok(true, "Received expected request.");
     29 }
     30 
     31 function onModifyListener(callback) {
     32  obs.addObserver(
     33    {
     34      observe(subject) {
     35        obs.removeObserver(this, "http-on-modify-request");
     36        callback(subject.QueryInterface(Ci.nsIHttpChannel));
     37      },
     38    },
     39    "http-on-modify-request"
     40  );
     41 }
     42 
     43 function startChannelRequest(uri, flags, expectedResponse = null) {
     44  var chan = NetUtil.newChannel({
     45    uri,
     46    loadUsingSystemPrincipal: true,
     47  });
     48  chan.asyncOpen(
     49    new ChannelListener(
     50      (request, data) => {
     51        if (expectedResponse) {
     52          Assert.equal(data, expectedResponse);
     53        } else {
     54          Assert.ok(!data, "no response");
     55        }
     56        executeSoon(run_next_test);
     57      },
     58      null,
     59      flags
     60    )
     61  );
     62 }
     63 
     64 add_test(function testSimpleRedirect() {
     65  onModifyListener(chan => {
     66    chan.redirectTo(ios.newURI(`${baseUrl}/success`));
     67  });
     68  startChannelRequest(baseUrl, undefined, "success response");
     69 });
     70 
     71 add_test(function testSimpleCancel() {
     72  onModifyListener(chan => {
     73    chan.cancel(Cr.NS_BINDING_ABORTED);
     74  });
     75  startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
     76 });
     77 
     78 add_test(function testSimpleCancelRedirect() {
     79  onModifyListener(chan => {
     80    chan.redirectTo(ios.newURI(`${baseUrl}/fail`));
     81    chan.cancel(Cr.NS_BINDING_ABORTED);
     82  });
     83  startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
     84 });
     85 
     86 // Test a request that will get redirected asynchronously.  baseUrl should
     87 // not be requested, we should receive the request for the redirectedUrl.
     88 add_test(function testAsyncRedirect() {
     89  onModifyListener(chan => {
     90    // Suspend the channel then yield to make this async.
     91    chan.suspend();
     92    Promise.resolve().then(() => {
     93      chan.redirectTo(ios.newURI(`${baseUrl}/success`));
     94      chan.resume();
     95    });
     96  });
     97  startChannelRequest(baseUrl, undefined, "success response");
     98 });
     99 
    100 add_test(function testSyncRedirect() {
    101  onModifyListener(chan => {
    102    chan.suspend();
    103    chan.redirectTo(ios.newURI(`${baseUrl}/success`));
    104    Promise.resolve().then(() => {
    105      chan.resume();
    106    });
    107  });
    108  startChannelRequest(baseUrl, undefined, "success response");
    109 });
    110 
    111 add_test(function testAsyncCancel() {
    112  onModifyListener(chan => {
    113    // Suspend the channel then yield to make this async.
    114    chan.suspend();
    115    Promise.resolve().then(() => {
    116      chan.cancel(Cr.NS_BINDING_ABORTED);
    117      chan.resume();
    118    });
    119  });
    120  startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
    121 });
    122 
    123 add_test(function testSyncCancel() {
    124  onModifyListener(chan => {
    125    chan.suspend();
    126    chan.cancel(Cr.NS_BINDING_ABORTED);
    127    Promise.resolve().then(() => {
    128      chan.resume();
    129    });
    130  });
    131  startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
    132 });
    133 
    134 // Test request that will get redirected and cancelled asynchronously,
    135 // ensure no connection is made.
    136 add_test(function testAsyncCancelRedirect() {
    137  onModifyListener(chan => {
    138    // Suspend the channel then yield to make this async.
    139    chan.suspend();
    140    Promise.resolve().then(() => {
    141      chan.cancel(Cr.NS_BINDING_ABORTED);
    142      chan.redirectTo(ios.newURI(`${baseUrl}/fail`));
    143      chan.resume();
    144    });
    145  });
    146  startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
    147 });
    148 
    149 // Test a request that will get cancelled synchronously, ensure async redirect
    150 // is not made.
    151 add_test(function testSyncCancelRedirect() {
    152  onModifyListener(chan => {
    153    chan.suspend();
    154    chan.cancel(Cr.NS_BINDING_ABORTED);
    155    Promise.resolve().then(() => {
    156      chan.redirectTo(ios.newURI(`${baseUrl}/fail`));
    157      chan.resume();
    158    });
    159  });
    160  startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
    161 });
    162 
    163 function run_test() {
    164  var httpServer = new HttpServer();
    165  httpServer.registerPathHandler("/", failResponseHandler);
    166  httpServer.registerPathHandler("/fail", failResponseHandler);
    167  httpServer.registerPathHandler("/success", successResponseHandler);
    168  httpServer.start(-1);
    169 
    170  baseUrl = `http://localhost:${httpServer.identity.primaryPort}`;
    171 
    172  run_next_test();
    173 
    174  registerCleanupFunction(function () {
    175    httpServer.stop(() => {});
    176  });
    177 }