tor-browser

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

test_cache-entry-id.js (5466B)


      1 /**
      2 * Test for the "CacheEntryId" under several cases.
      3 */
      4 
      5 "use strict";
      6 
      7 const { HttpServer } = ChromeUtils.importESModule(
      8  "resource://testing-common/httpd.sys.mjs"
      9 );
     10 
     11 ChromeUtils.defineLazyGetter(this, "URL", function () {
     12  return "http://localhost:" + httpServer.identity.primaryPort + "/content";
     13 });
     14 
     15 var httpServer = null;
     16 
     17 const responseContent = "response body";
     18 const responseContent2 = "response body 2";
     19 const altContent = "!@#$%^&*()";
     20 const altContentType = "text/binary";
     21 
     22 function isParentProcess() {
     23  let appInfo = Cc["@mozilla.org/xre/app-info;1"];
     24  return (
     25    !appInfo ||
     26    Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
     27  );
     28 }
     29 
     30 var handlers = [
     31  (m, r) => {
     32    r.bodyOutputStream.write(responseContent, responseContent.length);
     33  },
     34  (m, r) => {
     35    r.setStatusLine(m.httpVersion, 304, "Not Modified");
     36  },
     37  (m, r) => {
     38    r.setStatusLine(m.httpVersion, 304, "Not Modified");
     39  },
     40  (m, r) => {
     41    r.setStatusLine(m.httpVersion, 304, "Not Modified");
     42  },
     43  (m, r) => {
     44    r.setStatusLine(m.httpVersion, 304, "Not Modified");
     45  },
     46  (m, r) => {
     47    r.bodyOutputStream.write(responseContent2, responseContent2.length);
     48  },
     49  (m, r) => {
     50    r.setStatusLine(m.httpVersion, 304, "Not Modified");
     51  },
     52 ];
     53 
     54 function contentHandler(metadata, response) {
     55  response.setHeader("Content-Type", "text/plain");
     56  response.setHeader("Cache-Control", "no-cache");
     57 
     58  var handler = handlers.shift();
     59  if (handler) {
     60    handler(metadata, response);
     61    return;
     62  }
     63 
     64  Assert.ok(false, "Should not reach here.");
     65 }
     66 
     67 function fetch(preferredDataType = null) {
     68  return new Promise(resolve => {
     69    var chan = NetUtil.newChannel({ uri: URL, loadUsingSystemPrincipal: true });
     70 
     71    if (preferredDataType) {
     72      var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
     73      cc.preferAlternativeDataType(
     74        altContentType,
     75        "",
     76        Ci.nsICacheInfoChannel.ASYNC
     77      );
     78    }
     79 
     80    chan.asyncOpen(
     81      new ChannelListener((request, buffer, ctx, isFromCache, cacheEntryId) => {
     82        resolve({ request, buffer, isFromCache, cacheEntryId });
     83      }, null)
     84    );
     85  });
     86 }
     87 
     88 function check(
     89  response,
     90  content,
     91  preferredDataType,
     92  isFromCache,
     93  cacheEntryIdChecker
     94 ) {
     95  var cc = response.request.QueryInterface(Ci.nsICacheInfoChannel);
     96 
     97  Assert.equal(response.buffer, content);
     98  Assert.equal(cc.alternativeDataType, preferredDataType);
     99  Assert.equal(response.isFromCache, isFromCache);
    100  Assert.ok(!cacheEntryIdChecker || cacheEntryIdChecker(response.cacheEntryId));
    101 
    102  return response;
    103 }
    104 
    105 function writeAltData(request) {
    106  var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
    107  var os = cc.openAlternativeOutputStream(altContentType, altContent.length);
    108  os.write(altContent, altContent.length);
    109  os.close();
    110  gc(); // We need to do a GC pass to ensure the cache entry has been freed.
    111 
    112  return new Promise(resolve => {
    113    if (isParentProcess()) {
    114      Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(resolve);
    115    } else {
    116      do_send_remote_message("flush");
    117      do_await_remote_message("flushed").then(resolve);
    118    }
    119  });
    120 }
    121 
    122 function run_test() {
    123  do_get_profile();
    124  httpServer = new HttpServer();
    125  httpServer.registerPathHandler("/content", contentHandler);
    126  httpServer.start(-1);
    127  do_test_pending();
    128 
    129  var targetCacheEntryId = null;
    130  var secondCacheEntryId = null;
    131 
    132  return (
    133    Promise.resolve()
    134      // Setup testing environment: Placing alternative data into HTTP cache.
    135      .then(_ => fetch(altContentType))
    136      .then(r =>
    137        check(
    138          r,
    139          responseContent,
    140          "",
    141          false,
    142          cacheEntryId => cacheEntryId !== undefined
    143        )
    144      )
    145      .then(r => {
    146        targetCacheEntryId = r.cacheEntryId;
    147        writeAltData(r.request);
    148      })
    149 
    150      // Start testing.
    151      .then(_ => fetch(altContentType))
    152      .then(r =>
    153        check(
    154          r,
    155          altContent,
    156          altContentType,
    157          true,
    158          cacheEntryId => cacheEntryId !== undefined
    159        )
    160      )
    161 
    162      .then(_ => fetch())
    163      .then(r =>
    164        check(
    165          r,
    166          responseContent,
    167          "",
    168          true,
    169          cacheEntryId => cacheEntryId === targetCacheEntryId
    170        )
    171      )
    172 
    173      .then(_ => fetch(altContentType))
    174      .then(r =>
    175        check(
    176          r,
    177          altContent,
    178          altContentType,
    179          true,
    180          cacheEntryId => cacheEntryId === targetCacheEntryId
    181        )
    182      )
    183 
    184      .then(_ => fetch())
    185      .then(r =>
    186        check(
    187          r,
    188          responseContent,
    189          "",
    190          true,
    191          cacheEntryId => cacheEntryId === targetCacheEntryId
    192        )
    193      )
    194 
    195      .then(_ => fetch()) // The response is changed here.
    196      .then(r =>
    197        check(
    198          r,
    199          responseContent2,
    200          "",
    201          false,
    202          cacheEntryId =>
    203            cacheEntryId !== undefined && cacheEntryId !== targetCacheEntryId
    204        )
    205      )
    206      .then(r => {
    207        secondCacheEntryId = r.cacheEntryId;
    208      })
    209 
    210      .then(_ => fetch())
    211      .then(r =>
    212        check(
    213          r,
    214          responseContent2,
    215          "",
    216          true,
    217          cacheEntryId => cacheEntryId === secondCacheEntryId
    218        )
    219      )
    220 
    221      // Tear down.
    222      .catch(e => Assert.ok(false, "Unexpected exception: " + e))
    223      .then(_ => Assert.equal(handlers.length, 0))
    224      .then(_ => httpServer.stop(do_test_finished))
    225  );
    226 }