tor-browser

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

test_alt-data_overwrite.js (6246B)


      1 /**
      2 * Test for overwriting the alternative data in a cache entry.
      3 *
      4 * - run_test loads a new channel
      5 * - readServerContent checks the content, and saves alt-data
      6 * - cacheFlushObserver creates a new channel with "text/binary" alt-data type
      7 * - readAltContent checks that it gets back alt-data and creates a channel with the dummy/null alt-data type
      8 * - readServerContent2 checks that it gets regular content, from the cache and tries to overwrite the alt-data with the same representation
      9 * - cacheFlushObserver2 creates a new channel with "text/binary" alt-data type
     10 * - readAltContent2 checks that it gets back alt-data, and tries to overwrite with a kind of alt-data
     11 * - cacheFlushObserver3 creates a new channel with "text/binary2" alt-data type
     12 * - readAltContent3 checks that it gets back the newly saved alt-data
     13 */
     14 
     15 "use strict";
     16 
     17 const { HttpServer } = ChromeUtils.importESModule(
     18  "resource://testing-common/httpd.sys.mjs"
     19 );
     20 
     21 ChromeUtils.defineLazyGetter(this, "URL", function () {
     22  return "http://localhost:" + httpServer.identity.primaryPort + "/content";
     23 });
     24 
     25 let httpServer = null;
     26 
     27 function make_and_open_channel(url, altContentType, callback) {
     28  let chan = NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
     29  if (altContentType) {
     30    let cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
     31    cc.preferAlternativeDataType(
     32      altContentType,
     33      "",
     34      Ci.nsICacheInfoChannel.ASYNC
     35    );
     36  }
     37  chan.asyncOpen(new ChannelListener(callback, null));
     38 }
     39 
     40 const responseContent = "response body";
     41 const altContent = "!@#$%^&*()";
     42 const altContentType = "text/binary";
     43 const altContent2 = "abc";
     44 const altContentType2 = "text/binary2";
     45 
     46 let servedNotModified = false;
     47 
     48 function contentHandler(metadata, response) {
     49  response.setHeader("Content-Type", "text/plain");
     50  response.setHeader("Cache-Control", "no-cache");
     51  response.setHeader("ETag", "test-etag1");
     52  let etag = "";
     53  try {
     54    etag = metadata.getHeader("If-None-Match");
     55  } catch (ex) {
     56    etag = "";
     57  }
     58 
     59  if (etag == "test-etag1") {
     60    response.setStatusLine(metadata.httpVersion, 304, "Not Modified");
     61    servedNotModified = true;
     62  } else {
     63    servedNotModified = false;
     64    response.bodyOutputStream.write(responseContent, responseContent.length);
     65  }
     66 }
     67 
     68 function run_test() {
     69  do_get_profile();
     70  httpServer = new HttpServer();
     71  httpServer.registerPathHandler("/content", contentHandler);
     72  httpServer.start(-1);
     73 
     74  do_test_pending();
     75  make_and_open_channel(URL, altContentType, readServerContent);
     76 }
     77 
     78 function readServerContent(request, buffer) {
     79  let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
     80 
     81  Assert.equal(buffer, responseContent);
     82  Assert.equal(cc.alternativeDataType, "");
     83 
     84  executeSoon(() => {
     85    let os = cc.openAlternativeOutputStream(altContentType, altContent.length);
     86    os.write(altContent, altContent.length);
     87    os.close();
     88 
     89    executeSoon(flushAndOpenAltChannel);
     90  });
     91 }
     92 
     93 function flushAndOpenAltChannel() {
     94  // We need to do a GC pass to ensure the cache entry has been freed.
     95  Cu.forceShrinkingGC();
     96  Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver);
     97 }
     98 
     99 // needs to be rooted
    100 let cacheFlushObserver = {
    101  observe() {
    102    if (!cacheFlushObserver) {
    103      info("ignoring cacheFlushObserver\n");
    104      return;
    105    }
    106    cacheFlushObserver = null;
    107    Cu.forceShrinkingGC();
    108    make_and_open_channel(URL, altContentType, readAltContent);
    109  },
    110 };
    111 
    112 function readAltContent(request, buffer, closure, fromCache) {
    113  Cu.forceShrinkingGC();
    114  let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
    115 
    116  Assert.equal(fromCache || servedNotModified, true);
    117  Assert.equal(cc.alternativeDataType, altContentType);
    118  Assert.equal(buffer, altContent);
    119 
    120  make_and_open_channel(URL, "dummy/null", readServerContent2);
    121 }
    122 
    123 function readServerContent2(request, buffer, closure, fromCache) {
    124  Cu.forceShrinkingGC();
    125  let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
    126 
    127  Assert.equal(fromCache || servedNotModified, true);
    128  Assert.equal(buffer, responseContent);
    129  Assert.equal(cc.alternativeDataType, "");
    130 
    131  executeSoon(() => {
    132    let os = cc.openAlternativeOutputStream(altContentType, altContent.length);
    133    os.write(altContent, altContent.length);
    134    os.close();
    135 
    136    executeSoon(flushAndOpenAltChannel2);
    137  });
    138 }
    139 
    140 function flushAndOpenAltChannel2() {
    141  // We need to do a GC pass to ensure the cache entry has been freed.
    142  Cu.forceShrinkingGC();
    143  Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver2);
    144 }
    145 
    146 // needs to be rooted
    147 let cacheFlushObserver2 = {
    148  observe() {
    149    if (!cacheFlushObserver2) {
    150      info("ignoring cacheFlushObserver2\n");
    151      return;
    152    }
    153    cacheFlushObserver2 = null;
    154    Cu.forceShrinkingGC();
    155    make_and_open_channel(URL, altContentType, readAltContent2);
    156  },
    157 };
    158 
    159 function readAltContent2(request, buffer, closure, fromCache) {
    160  Cu.forceShrinkingGC();
    161  let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
    162 
    163  Assert.equal(servedNotModified || fromCache, true);
    164  Assert.equal(cc.alternativeDataType, altContentType);
    165  Assert.equal(buffer, altContent);
    166 
    167  executeSoon(() => {
    168    Cu.forceShrinkingGC();
    169    info("writing other content\n");
    170    let os = cc.openAlternativeOutputStream(
    171      altContentType2,
    172      altContent2.length
    173    );
    174    os.write(altContent2, altContent2.length);
    175    os.close();
    176 
    177    executeSoon(flushAndOpenAltChannel3);
    178  });
    179 }
    180 
    181 function flushAndOpenAltChannel3() {
    182  // We need to do a GC pass to ensure the cache entry has been freed.
    183  Cu.forceShrinkingGC();
    184  Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver3);
    185 }
    186 
    187 // needs to be rooted
    188 let cacheFlushObserver3 = {
    189  observe() {
    190    if (!cacheFlushObserver3) {
    191      info("ignoring cacheFlushObserver3\n");
    192      return;
    193    }
    194 
    195    cacheFlushObserver3 = null;
    196    Cu.forceShrinkingGC();
    197    make_and_open_channel(URL, altContentType2, readAltContent3);
    198  },
    199 };
    200 
    201 function readAltContent3(request, buffer, closure, fromCache) {
    202  let cc = request.QueryInterface(Ci.nsICacheInfoChannel);
    203 
    204  Assert.equal(servedNotModified || fromCache, true);
    205  Assert.equal(cc.alternativeDataType, altContentType2);
    206  Assert.equal(buffer, altContent2);
    207 
    208  httpServer.stop(do_test_finished);
    209 }