tor-browser

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

test_remote_settings_utils.js (6879B)


      1 const BinaryOutputStream = Components.Constructor(
      2  "@mozilla.org/binaryoutputstream;1",
      3  "nsIBinaryOutputStream",
      4  "setOutputStream"
      5 );
      6 
      7 const server = new HttpServer();
      8 server.start(-1);
      9 registerCleanupFunction(() => server.stop(() => {}));
     10 const SERVER_BASE_URL = `http://localhost:${server.identity.primaryPort}`;
     11 
     12 const proxyServer = new HttpServer();
     13 proxyServer.identity.add("http", "localhost", server.identity.primaryPort);
     14 proxyServer.start(-1);
     15 registerCleanupFunction(() => proxyServer.stop(() => {}));
     16 const PROXY_PORT = proxyServer.identity.primaryPort;
     17 
     18 // A sequence of bytes that would become garbage if it were to be read as UTF-8:
     19 // - 0xEF 0xBB 0xBF is a byte order mark.
     20 // - 0xC0 on its own is invalid (it's the first byte of a 2-byte encoding).
     21 const INVALID_UTF_8_BYTES = [0xef, 0xbb, 0xbf, 0xc0];
     22 
     23 server.registerPathHandler("/binary.dat", (request, response) => {
     24  response.setStatusLine(null, 201, "StatusLineHere");
     25  response.setHeader("headerName", "HeaderValue: HeaderValueEnd");
     26  let binaryOut = new BinaryOutputStream(response.bodyOutputStream);
     27  binaryOut.writeByteArray([0xef, 0xbb, 0xbf, 0xc0]);
     28 });
     29 
     30 // HTTPS requests are proxied with CONNECT, but our test server is HTTP,
     31 // which means that the proxy will receive GET http://localhost:port.
     32 var proxiedCount = 0;
     33 proxyServer.registerPrefixHandler("/", (request, response) => {
     34  ++proxiedCount;
     35  Assert.equal(request.path, "/binary.dat", `Proxy request ${proxiedCount}`);
     36  // Close connection without sending any response.
     37  response.seizePower();
     38  response.finish();
     39 });
     40 
     41 add_task(async function test_utils_fetch_binary() {
     42  let res = await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`);
     43 
     44  Assert.equal(res.status, 201, "res.status");
     45  Assert.equal(res.statusText, "StatusLineHere", "res.statusText");
     46  Assert.equal(
     47    res.headers.get("headerName"),
     48    "HeaderValue: HeaderValueEnd",
     49    "Utils.fetch should return the header"
     50  );
     51 
     52  Assert.deepEqual(
     53    Array.from(new Uint8Array(await res.arrayBuffer())),
     54    INVALID_UTF_8_BYTES,
     55    "Binary response body should be returned as is"
     56  );
     57 });
     58 
     59 add_task(async function test_utils_fetch_binary_as_text() {
     60  let res = await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`);
     61  Assert.deepEqual(
     62    Array.from(await res.text(), c => c.charCodeAt(0)),
     63    [65533],
     64    "Interpreted as UTF-8, the response becomes garbage"
     65  );
     66 });
     67 
     68 add_task(async function test_utils_fetch_binary_as_json() {
     69  let res = await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`);
     70  await Assert.rejects(
     71    res.json(),
     72    /SyntaxError: JSON.parse: unexpected character/,
     73    "Binary data is invalid JSON"
     74  );
     75 });
     76 
     77 add_task(async function test_utils_fetch_has_conservative() {
     78  let channelPromise = TestUtils.topicObserved("http-on-modify-request");
     79  await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`);
     80 
     81  let channel = (await channelPromise)[0].QueryInterface(Ci.nsIHttpChannel);
     82 
     83  Assert.equal(channel.URI.spec, `${SERVER_BASE_URL}/binary.dat`, "URL OK");
     84 
     85  let internalChannel = channel.QueryInterface(Ci.nsIHttpChannelInternal);
     86  Assert.ok(internalChannel.beConservative, "beConservative flag is set");
     87 });
     88 
     89 add_task(async function test_utils_fetch_has_conservative() {
     90  let channelPromise = TestUtils.topicObserved("http-on-modify-request");
     91  await Utils.fetch(`${SERVER_BASE_URL}/binary.dat`);
     92 
     93  let channel = (await channelPromise)[0].QueryInterface(Ci.nsIHttpChannel);
     94 
     95  Assert.equal(channel.URI.spec, `${SERVER_BASE_URL}/binary.dat`, "URL OK");
     96 
     97  let internalChannel = channel.QueryInterface(Ci.nsIHttpChannelInternal);
     98  Assert.ok(internalChannel.beConservative, "beConservative flag is set");
     99 });
    100 
    101 add_task(async function test_utils_fetch_with_bad_proxy() {
    102  Services.prefs.setIntPref("network.proxy.type", 1);
    103  Services.prefs.setStringPref("network.proxy.http", "127.0.0.1");
    104  Services.prefs.setIntPref("network.proxy.http_port", PROXY_PORT);
    105  Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true);
    106 
    107  // The URL that we're going to request.
    108  const DESTINATION_URL = `${SERVER_BASE_URL}/binary.dat`;
    109 
    110  Assert.equal(proxiedCount, 0, "Proxy not used yet");
    111  {
    112    info("Bad proxy, default prefs");
    113    let res = await Utils.fetch(DESTINATION_URL);
    114    Assert.equal(res.status, 201, "Bypassed bad proxy");
    115    // 10 instead of 1 because of reconnect attempts after a dropped request.
    116    Assert.equal(proxiedCount, 10, "Proxy was used by HttpChannel");
    117  }
    118 
    119  // Disables the failover logic from HttpChannel.
    120  Services.prefs.setBoolPref("network.proxy.failover_direct", false);
    121  proxiedCount = 0;
    122  {
    123    info("Bad proxy, disabled network.proxy.failover_direct");
    124    let res = await Utils.fetch(DESTINATION_URL);
    125    Assert.equal(res.status, 201, "Bypassed bad proxy");
    126    // 10 instead of 1 because of reconnect attempts after a dropped request.
    127    Assert.equal(proxiedCount, 10, "Proxy was used by ServiceRequest");
    128  }
    129 
    130  proxiedCount = 0;
    131  {
    132    info("Using internal option of Utils.fetch: bypassProxy=true");
    133    let res = await Utils.fetch(DESTINATION_URL, { bypassProxy: true });
    134    Assert.equal(res.status, 201, "Bypassed bad proxy");
    135    Assert.equal(proxiedCount, 0, "Not using proxy when bypassProxy=true");
    136  }
    137 
    138  // Disables the failover logic from ServiceRequest/Utils.fetch
    139  Services.prefs.setBoolPref("network.proxy.allow_bypass", false);
    140  proxiedCount = 0;
    141 
    142  info("Bad proxy, disabled network.proxy.allow_bypass");
    143  await Assert.rejects(
    144    Utils.fetch(DESTINATION_URL),
    145    /NetworkError/,
    146    "Bad proxy request should fail without failover"
    147  );
    148  // 10 instead of 1 because of reconnect attempts after a dropped request.
    149  Assert.equal(proxiedCount, 10, "Attempted to use proxy again");
    150 
    151  Services.prefs.clearUserPref("network.proxy.type");
    152  Services.prefs.clearUserPref("network.proxy.http");
    153  Services.prefs.clearUserPref("network.proxy.http_port");
    154  Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
    155  Services.prefs.clearUserPref("network.proxy.failover_direct");
    156  Services.prefs.clearUserPref("network.proxy.allow_bypass");
    157 });
    158 
    159 add_task(async function test_base_attachment_url_depends_on_server() {
    160  Services.prefs.setStringPref(
    161    "services.settings.server",
    162    `http://localhost:${server.identity.primaryPort}/v2`
    163  );
    164 
    165  Assert.equal(
    166    Services.prefs.getStringPref("services.settings.server"),
    167    Utils.SERVER_URL
    168  );
    169 
    170  server.registerPathHandler("/v2/", (request, response) => {
    171    response.write(
    172      JSON.stringify({
    173        capabilities: {
    174          attachments: {
    175            base_url: "http://some-cdn-url.org",
    176          },
    177        },
    178      })
    179    );
    180    response.setHeader("Content-Type", "application/json; charset=UTF-8");
    181    response.setStatusLine(null, 200, "OK");
    182  });
    183 
    184  const after = await Utils.baseAttachmentsURL();
    185 
    186  Assert.equal(after, "http://some-cdn-url.org/", "A trailing slash is added");
    187 });