tor-browser

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

test_alt-data_stream.js (4773B)


      1 /**
      2 * Test for the "alternative data stream" stored withing a cache entry.
      3 *
      4 * - we load a URL with preference for an alt data (check what we get is the raw data,
      5 *   since there was nothing previously cached)
      6 * - we write a big chunk of alt-data to the output stream
      7 * - we load the URL again, expecting to get alt-data
      8 * - we check that the alt-data is streamed. We should get the first chunk, then
      9 *   the rest of the alt-data is written, and we check that it is received in
     10 *   the proper order.
     11 *
     12 */
     13 
     14 "use strict";
     15 
     16 const { HttpServer } = ChromeUtils.importESModule(
     17  "resource://testing-common/httpd.sys.mjs"
     18 );
     19 
     20 ChromeUtils.defineLazyGetter(this, "URL", function () {
     21  return "http://localhost:" + httpServer.identity.primaryPort + "/content";
     22 });
     23 
     24 var httpServer = null;
     25 
     26 function make_channel(url) {
     27  return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
     28 }
     29 
     30 const responseContent = "response body";
     31 // We need a large content in order to make sure that the IPDL stream is cut
     32 // into several different chunks.
     33 // We fill each chunk with a different character for easy debugging.
     34 const altContent =
     35  "a".repeat(128 * 1024) +
     36  "b".repeat(128 * 1024) +
     37  "c".repeat(128 * 1024) +
     38  "d".repeat(128 * 1024) +
     39  "e".repeat(128 * 1024) +
     40  "f".repeat(128 * 1024) +
     41  "g".repeat(128 * 1024) +
     42  "h".repeat(128 * 1024) +
     43  "i".repeat(13); // Just so the chunk size doesn't match exactly.
     44 
     45 const firstChunkSize = Math.floor(altContent.length / 4);
     46 const altContentType = "text/binary";
     47 
     48 function contentHandler(metadata, response) {
     49  response.setHeader("Content-Type", "text/plain");
     50  response.setHeader("Cache-Control", "max-age=86400");
     51 
     52  response.bodyOutputStream.write(responseContent, responseContent.length);
     53 }
     54 
     55 function run_test() {
     56  do_get_profile();
     57  httpServer = new HttpServer();
     58  httpServer.registerPathHandler("/content", contentHandler);
     59  httpServer.start(-1);
     60 
     61  var chan = make_channel(URL);
     62 
     63  var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
     64  cc.preferAlternativeDataType(
     65    altContentType,
     66    "",
     67    Ci.nsICacheInfoChannel.ASYNC
     68  );
     69 
     70  chan.asyncOpen(new ChannelListener(readServerContent, null));
     71  do_test_pending();
     72 }
     73 
     74 // Output stream used to write alt-data to the cache entry.
     75 var os;
     76 
     77 function readServerContent(request, buffer) {
     78  var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
     79 
     80  Assert.equal(buffer, responseContent);
     81  Assert.equal(cc.alternativeDataType, "");
     82 
     83  executeSoon(() => {
     84    os = cc.openAlternativeOutputStream(altContentType, altContent.length);
     85    // Write a quarter of the alt data content
     86    os.write(altContent, firstChunkSize);
     87 
     88    executeSoon(openAltChannel);
     89  });
     90 }
     91 
     92 function openAltChannel() {
     93  var chan = make_channel(URL);
     94  var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
     95  cc.preferAlternativeDataType(
     96    altContentType,
     97    "",
     98    Ci.nsICacheInfoChannel.ASYNC
     99  );
    100 
    101  chan.asyncOpen(altDataListener);
    102 }
    103 
    104 var altDataListener = {
    105  buffer: "",
    106  onStartRequest() {},
    107  onDataAvailable(request, stream, offset, count) {
    108    let string = NetUtil.readInputStreamToString(stream, count);
    109    this.buffer += string;
    110 
    111    // XXX: this condition might be a bit volatile. If this test times out,
    112    // it probably means that for some reason, the listener didn't get all the
    113    // data in the first chunk.
    114    if (this.buffer.length == firstChunkSize) {
    115      // write the rest of the content
    116      os.write(
    117        altContent.substring(firstChunkSize, altContent.length),
    118        altContent.length - firstChunkSize
    119      );
    120      os.close();
    121    }
    122  },
    123  onStopRequest(request) {
    124    var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
    125    Assert.equal(cc.alternativeDataType, altContentType);
    126    Assert.equal(this.buffer.length, altContent.length);
    127    Assert.equal(this.buffer, altContent);
    128    openAltChannelWithOriginalContent();
    129  },
    130 };
    131 
    132 function openAltChannelWithOriginalContent() {
    133  var chan = make_channel(URL);
    134  var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
    135  cc.preferAlternativeDataType(
    136    altContentType,
    137    "",
    138    Ci.nsICacheInfoChannel.SERIALIZE
    139  );
    140 
    141  chan.asyncOpen(originalListener);
    142 }
    143 
    144 var originalListener = {
    145  buffer: "",
    146  onStartRequest() {},
    147  onDataAvailable(request, stream, offset, count) {
    148    let string = NetUtil.readInputStreamToString(stream, count);
    149    this.buffer += string;
    150  },
    151  onStopRequest(request) {
    152    var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
    153    Assert.equal(cc.alternativeDataType, altContentType);
    154    Assert.equal(this.buffer.length, responseContent.length);
    155    Assert.equal(this.buffer, responseContent);
    156    testAltDataStream(cc);
    157  },
    158 };
    159 
    160 function testAltDataStream(cc) {
    161  Assert.ok(!!cc.alternativeDataInputStream);
    162  httpServer.stop(do_test_finished);
    163 }