tor-browser

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

head_helpers.js (6637B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /* import-globals-from head_global.js */
      6 
      7 var { Log } = ChromeUtils.importESModule("resource://gre/modules/Log.sys.mjs");
      8 var { CommonUtils } = ChromeUtils.importESModule(
      9  "resource://services-common/utils.sys.mjs"
     10 );
     11 var {
     12  HTTP_400,
     13  HTTP_401,
     14  HTTP_402,
     15  HTTP_403,
     16  HTTP_404,
     17  HTTP_405,
     18  HTTP_406,
     19  HTTP_407,
     20  HTTP_408,
     21  HTTP_409,
     22  HTTP_410,
     23  HTTP_411,
     24  HTTP_412,
     25  HTTP_413,
     26  HTTP_414,
     27  HTTP_415,
     28  HTTP_417,
     29  HTTP_500,
     30  HTTP_501,
     31  HTTP_502,
     32  HTTP_503,
     33  HTTP_504,
     34  HTTP_505,
     35  HttpError,
     36  HttpServer,
     37 } = ChromeUtils.importESModule("resource://testing-common/httpd.sys.mjs");
     38 var { getTestLogger, initTestLogging } = ChromeUtils.importESModule(
     39  "resource://testing-common/services/common/logging.sys.mjs"
     40 );
     41 var { MockRegistrar } = ChromeUtils.importESModule(
     42  "resource://testing-common/MockRegistrar.sys.mjs"
     43 );
     44 var { NetUtil } = ChromeUtils.importESModule(
     45  "resource://gre/modules/NetUtil.sys.mjs"
     46 );
     47 
     48 function do_check_empty(obj) {
     49  do_check_attribute_count(obj, 0);
     50 }
     51 
     52 function do_check_attribute_count(obj, c) {
     53  Assert.equal(c, Object.keys(obj).length);
     54 }
     55 
     56 function do_check_throws(aFunc, aResult) {
     57  try {
     58    aFunc();
     59  } catch (e) {
     60    Assert.equal(e.result, aResult);
     61    return;
     62  }
     63  do_throw("Expected result " + aResult + ", none thrown.");
     64 }
     65 
     66 /**
     67 * Test whether specified function throws exception with expected
     68 * result.
     69 *
     70 * @param func
     71 *        Function to be tested.
     72 * @param message
     73 *        Message of expected exception. <code>null</code> for no throws.
     74 */
     75 function do_check_throws_message(aFunc, aResult) {
     76  try {
     77    aFunc();
     78  } catch (e) {
     79    Assert.equal(e.message, aResult);
     80    return;
     81  }
     82  do_throw("Expected an error, none thrown.");
     83 }
     84 
     85 /**
     86 * Print some debug message to the console. All arguments will be printed,
     87 * separated by spaces.
     88 *
     89 * @param [arg0, arg1, arg2, ...]
     90 *        Any number of arguments to print out
     91 * @example
     92 * _("Hello World") -> prints "Hello World"
     93 * _(1, 2, 3) -> prints "1 2 3"
     94 */
     95 var _ = function () {
     96  print(Array.from(arguments).join(" "));
     97 };
     98 
     99 function httpd_setup(handlers, port = -1) {
    100  let server = new HttpServer();
    101  for (let path in handlers) {
    102    server.registerPathHandler(path, handlers[path]);
    103  }
    104  try {
    105    server.start(port);
    106  } catch (ex) {
    107    _("==========================================");
    108    _("Got exception starting HTTP server on port " + port);
    109    _("Error: " + Log.exceptionStr(ex));
    110    _("Is there a process already listening on port " + port + "?");
    111    _("==========================================");
    112    do_throw(ex);
    113  }
    114 
    115  // Set the base URI for convenience.
    116  let i = server.identity;
    117  server.baseURI =
    118    i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort;
    119 
    120  return server;
    121 }
    122 
    123 function httpd_handler(statusCode, status, body) {
    124  return function handler(request, response) {
    125    _("Processing request");
    126    // Allow test functions to inspect the request.
    127    request.body = readBytesFromInputStream(request.bodyInputStream);
    128    handler.request = request;
    129 
    130    response.setStatusLine(request.httpVersion, statusCode, status);
    131    if (body) {
    132      response.bodyOutputStream.write(body, body.length);
    133    }
    134  };
    135 }
    136 
    137 function promiseStopServer(server) {
    138  return new Promise(resolve => server.stop(resolve));
    139 }
    140 
    141 /*
    142 * Read bytes string from an nsIInputStream.  If 'count' is omitted,
    143 * all available input is read.
    144 */
    145 function readBytesFromInputStream(inputStream, count) {
    146  if (!count) {
    147    count = inputStream.available();
    148  }
    149  if (!count) {
    150    return "";
    151  }
    152  return NetUtil.readInputStreamToString(inputStream, count, {
    153    charset: "UTF-8",
    154  });
    155 }
    156 
    157 function writeBytesToOutputStream(outputStream, string) {
    158  if (!string) {
    159    return;
    160  }
    161  let converter = Cc[
    162    "@mozilla.org/intl/converter-output-stream;1"
    163  ].createInstance(Ci.nsIConverterOutputStream);
    164  converter.init(outputStream, "UTF-8");
    165  converter.writeString(string);
    166  converter.close();
    167 }
    168 
    169 /*
    170 * Ensure exceptions from inside callbacks leads to test failures.
    171 */
    172 function ensureThrows(func) {
    173  return function () {
    174    try {
    175      func.apply(this, arguments);
    176    } catch (ex) {
    177      do_throw(ex);
    178    }
    179  };
    180 }
    181 
    182 /**
    183 * Proxy auth helpers.
    184 */
    185 
    186 /**
    187 * Fake a PAC to prompt a channel replacement.
    188 */
    189 var PACSystemSettings = {
    190  QueryInterface: ChromeUtils.generateQI(["nsISystemProxySettings"]),
    191 
    192  // Replace this URI for each test to avoid caching. We want to ensure that
    193  // each test gets a completely fresh setup.
    194  mainThreadOnly: true,
    195  PACURI: null,
    196  getProxyForURI: function getProxyForURI() {
    197    throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
    198  },
    199 };
    200 
    201 var fakePACCID;
    202 function installFakePAC() {
    203  _("Installing fake PAC.");
    204  fakePACCID = MockRegistrar.register(
    205    "@mozilla.org/system-proxy-settings;1",
    206    PACSystemSettings
    207  );
    208 }
    209 
    210 function uninstallFakePAC() {
    211  _("Uninstalling fake PAC.");
    212  MockRegistrar.unregister(fakePACCID);
    213 }
    214 
    215 function getUptakeTelemetrySnapshot(component, source) {
    216  const TELEMETRY_CATEGORY_ID = "uptake.remotecontent.result";
    217  const snapshot = Services.telemetry.snapshotEvents(
    218    Ci.nsITelemetry.DATASET_ALL_CHANNELS,
    219    true
    220  );
    221  const parentEvents = snapshot.parent || [];
    222  return (
    223    parentEvents
    224      // Transform raw event data to objects.
    225      .map(([, category, method, object, value, extras]) => {
    226        return { category, method, object, value, extras };
    227      })
    228      // Keep only for the specified component and source.
    229      .filter(
    230        e =>
    231          e.category == TELEMETRY_CATEGORY_ID &&
    232          e.object == component &&
    233          e.extras.source == source
    234      )
    235      // Return total number of events received by status, to mimic histograms snapshots.
    236      .reduce((acc, e) => {
    237        acc[e.value] = (acc[e.value] || 0) + 1;
    238        return acc;
    239      }, {})
    240  );
    241 }
    242 
    243 function checkUptakeTelemetry(snapshot1, snapshot2, expectedIncrements) {
    244  const { UptakeTelemetry } = ChromeUtils.importESModule(
    245    "resource://services-common/uptake-telemetry.sys.mjs"
    246  );
    247  const STATUSES = Object.values(UptakeTelemetry.STATUS);
    248  for (const status of STATUSES) {
    249    const expected = expectedIncrements[status] || 0;
    250    const previous = snapshot1[status] || 0;
    251    const current = snapshot2[status] || previous;
    252    Assert.equal(expected, current - previous, `check events for ${status}`);
    253  }
    254 }
    255 
    256 function arrayEqual(a, b) {
    257  return JSON.stringify(a) == JSON.stringify(b);
    258 }