Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/netwerk/test/unit/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 35 kB image not shown  

Quelle  test_trr.js   Sprache: JAVA

 

"use strict";

/* import-globals-from trr_common.js */
/* import-globals-from head_trr.js */

const gDefaultPref = Services.prefs.getDefaultBranch("");

const { NodeServer } = ChromeUtils.importESModule(
  "resource://testing-common/NodeServer.sys.mjs"
);

SetParentalControlEnabled(false);

let trrServer;
add_setup(async function setup() {
  Services.prefs.setBoolPref("network.dns.get-ttl", false);
  trr_test_setup();
  trrServer = new TRRServer();
  await trrServer.start();
  h2Port = trrServer.port();

  registerCleanupFunction(async () => {
    trr_clear_prefs();
    Services.prefs.clearUserPref("network.dns.get-ttl");
    Services.prefs.clearUserPref("network.dns.disableIPv6");
    if (trrServer) {
      await trrServer.stop();
    }
  });
});

async function waitForConfirmation(expectedResponseIP, confirmationShouldFail) {
  // Check that the confirmation eventually completes.
  let count = 100;
  while (count > 0) {
    if (count == 50 || count == 10) {
      // At these two points we do a longer timeout to account for a slow
      // response on the server side. This is usually a problem on the Android
      // because of the increased delay between the emulator and host.
      await new Promise(resolve => do_timeout(100 * (100 / count), resolve));
    }
    let { inRecord } = await new TRRDNSListener(
      `ip${count}.example.org`,
      undefined,
      false
    );
    inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
    let responseIP = inRecord.getNextAddrAsString();
    Assert.ok(true, responseIP);
    if (responseIP == expectedResponseIP) {
      break;
    }
    count--;
  }

  if (confirmationShouldFail) {
    Assert.equal(count, 0, "Confirmation did not finish after 100 iterations");
    return;
  }

  Assert.greater(count, 0, "Finished confirmation before 100 iterations");
}

function setModeAndURI(mode, path) {
  Services.prefs.setIntPref("network.trr.mode", mode);
  Services.prefs.setCharPref(
    "network.trr.uri",
    `https://${TRR_Domain}:${h2Port}/${path}`
  );
}

function makeChan(url, mode) {
  let chan = NetUtil.newChannel({
    uri: url,
    loadUsingSystemPrincipal: true,
  }).QueryInterface(Ci.nsIHttpChannel);
  chan.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
  chan.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
  chan.setTRRMode(mode);
  return chan;
}

add_task(async function test_server_up() {
  // This test checks that moz-http2.js running in node is working.
  // This should always be the first test in this file (except for setup)
  // otherwise we may encounter random failures when the http2 server is down.

  await NodeServer.execute("bad_id", `"hello"`)
    .then(() => ok(false, "expecting to throw"))
    .catch(e => equal(e.message, "Error: could not find id"));
});

add_task(async function test_trr_flags() {
  Services.prefs.setBoolPref("network.trr.fallback-on-zero-response", true);
  Services.prefs.setIntPref("network.trr.request_timeout_ms", 10000);
  Services.prefs.setIntPref(
    "network.trr.request_timeout_mode_trronly_ms",
    10000
  );

  let httpserv = new HttpServer();
  httpserv.registerPathHandler("/", function handler(metadata, response) {
    let content = "ok";
    response.setHeader("Content-Length", `${content.length}`);
    response.bodyOutputStream.write(content, content.length);
  });
  httpserv.start(-1);

  const URL = `http://example.com:${httpserv.identity.primaryPort}/`;

  for (let mode of [0, 1, 2, 3, 4, 5]) {
    setModeAndURI(mode, "doh?responseIP=127.0.0.1");
    for (let flag of [
      Ci.nsIRequest.TRR_DEFAULT_MODE,
      Ci.nsIRequest.TRR_DISABLED_MODE,
      Ci.nsIRequest.TRR_FIRST_MODE,
      Ci.nsIRequest.TRR_ONLY_MODE,
    ]) {
      Services.dns.clearCache(true);
      let chan = makeChan(URL, flag);
      let expectTRR =
        ([2, 3].includes(mode) && flag != Ci.nsIRequest.TRR_DISABLED_MODE) ||
        (mode == 0 &&
          [Ci.nsIRequest.TRR_FIRST_MODE, Ci.nsIRequest.TRR_ONLY_MODE].includes(
            flag
          ));

      await new Promise(resolve =>
        chan.asyncOpen(new ChannelListener(resolve))
      );

      equal(chan.getTRRMode(), flag);
      equal(
        expectTRR,
        chan.QueryInterface(Ci.nsIHttpChannelInternal).isResolvedByTRR
      );
    }
  }

  await new Promise(resolve => httpserv.stop(resolve));
  Services.prefs.clearUserPref("network.trr.fallback-on-zero-response");
  Services.prefs.clearUserPref("network.trr.request_timeout_ms");
  Services.prefs.clearUserPref("network.trr.request_timeout_mode_trronly_ms");
});

add_task(test_A_record);

add_task(test_AAAA_records);

add_task(test_RFC1918);

add_task(test_GET_ECS);

add_task(test_timeout_mode3);

add_task(test_trr_retry);

add_task(test_strict_native_fallback);

add_task(test_no_answers_fallback);

add_task(test_404_fallback);

add_task(test_mode_1_and_4);

add_task(test_CNAME);

add_task(test_name_mismatch);

add_task(test_mode_2);

add_task(test_excluded_domains);

add_task(test_captiveportal_canonicalURL);

add_task(test_parentalcontrols);

// TRR-first check that DNS result is used if domain is part of the builtin-excluded-domains pref
add_task(test_builtin_excluded_domains);

add_task(test_excluded_domains_mode3);

add_task(test25e);

add_task(test_parentalcontrols_mode3);

add_task(test_builtin_excluded_domains_mode3);

add_task(count_cookies);

add_task(test_connection_closed);

add_task(async function test_clearCacheOnURIChange() {
  info("Check that the TRR cache should be cleared by a pref change.");
  Services.dns.clearCache(true);
  Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", true);
  setModeAndURI(2, "doh?responseIP=7.7.7.7");

  await new TRRDNSListener("bar.example.com", "7.7.7.7");

  // The TRR cache should be cleared by this pref change.
  Services.prefs.setCharPref(
    "network.trr.uri",
    `https://localhost:${h2Port}/doh?responseIP=8.8.8.8`
  );

  await new TRRDNSListener("bar.example.com", "8.8.8.8");
  Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
});

add_task(async function test_dnsSuffix() {
  info("Checking that domains matching dns suffix list use Do53");
  // Preserve historical behavior of this task: DNS-suffix domains are
  // excluded from TRR in mode 3 as well. The new behavior is exercised by
  // test_dnsSuffix_mode3_pref below.
  Services.prefs.setBoolPref(
    "network.trr.exclude_dns_suffix_in_mode_trronly",
    true
  );
  async function checkDnsSuffixInMode(mode) {
    Services.dns.clearCache(true);
    setModeAndURI(mode, "doh?responseIP=1.2.3.4");
    await new TRRDNSListener("example.org", "1.2.3.4");
    await new TRRDNSListener("test.com", "1.2.3.4");

    let networkLinkService = {
      dnsSuffixList: ["example.org"],
      QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
    };
    Services.obs.notifyObservers(
      networkLinkService,
      "network:dns-suffix-list-updated"
    );
    await new TRRDNSListener("test.com", "1.2.3.4");
    if (Services.prefs.getBoolPref("network.trr.split_horizon_mitigations")) {
      await new TRRDNSListener("example.org", "127.0.0.1");
    } else {
      await new TRRDNSListener("example.org", "1.2.3.4");
    }

    // Attempt to clean up, just in case
    networkLinkService.dnsSuffixList = [];
    Services.obs.notifyObservers(
      networkLinkService,
      "network:dns-suffix-list-updated"
    );
  }

  Services.prefs.setBoolPref("network.trr.split_horizon_mitigations", true);
  await checkDnsSuffixInMode(2);
  Services.prefs.setCharPref("network.trr.bootstrapAddr", "127.0.0.1");
  await checkDnsSuffixInMode(3);
  Services.prefs.setBoolPref("network.trr.split_horizon_mitigations", false);
  // Test again with mitigations off
  await checkDnsSuffixInMode(2);
  await checkDnsSuffixInMode(3);
  Services.prefs.clearUserPref("network.trr.split_horizon_mitigations");
  Services.prefs.clearUserPref("network.trr.bootstrapAddr");
  Services.prefs.clearUserPref(
    "network.trr.exclude_dns_suffix_in_mode_trronly"
  );
});

add_task(async function test_dnsSuffix_mode3_pref() {
  info(
    "In TRR-only mode the DNS suffix list should be ignored when " +
      "network.trr.exclude_dns_suffix_in_mode_trronly is false (default)."
  );
  Services.prefs.setBoolPref("network.trr.split_horizon_mitigations", true);
  Services.prefs.setCharPref("network.trr.bootstrapAddr", "127.0.0.1");

  let networkLinkService = {
    dnsSuffixList: ["example.org"],
    QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
  };

  async function checkMode3(prefValue, expectedIP) {
    Services.prefs.setBoolPref(
      "network.trr.exclude_dns_suffix_in_mode_trronly",
      prefValue
    );
    Services.dns.clearCache(true);
    setModeAndURI(3, "doh?responseIP=1.2.3.4");
    Services.obs.notifyObservers(
      networkLinkService,
      "network:dns-suffix-list-updated"
    );
    await new TRRDNSListener("example.org", expectedIP);
  }

  // Default behavior: pref is false, suffix is ignored in mode 3, so the
  // host is resolved via TRR.
  await checkMode3(false, "1.2.3.4");
  // Opt-in to old behavior: pref is true, suffix is excluded so the local
  // bootstrap resolver answers with 127.0.0.1.
  await checkMode3(true, "127.0.0.1");

  networkLinkService.dnsSuffixList = [];
  Services.obs.notifyObservers(
    networkLinkService,
    "network:dns-suffix-list-updated"
  );
  Services.prefs.clearUserPref(
    "network.trr.exclude_dns_suffix_in_mode_trronly"
  );
  Services.prefs.clearUserPref("network.trr.split_horizon_mitigations");
  Services.prefs.clearUserPref("network.trr.bootstrapAddr");
});

add_task(async function test_dnsSuffix_request_mode_trronly() {
  info(
    "A per-request TRR mode of TRR_ONLY_MODE should also cause the DNS " +
      "suffix list to be ignored by default, even when the global mode is " +
      "TRR-first."
  );
  Services.prefs.setBoolPref("network.trr.split_horizon_mitigations", true);
  Services.prefs.setCharPref("network.trr.bootstrapAddr", "127.0.0.1");

  let networkLinkService = {
    dnsSuffixList: ["example.org"],
    QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
  };

  // TRR_ONLY_MODE encoded into resolve flags. See RESOLVE_TRR_MODE_MASK in
  // nsIDNSService.idl: the request TRR mode lives in bits 11/12, so
  // TRR_ONLY_MODE (=3) corresponds to (3 << 11).
  const TRR_ONLY_FLAGS = 3 << 11;

  async function checkRequestModeTRROnly(prefValue, expectedIP) {
    Services.prefs.setBoolPref(
      "network.trr.exclude_dns_suffix_in_mode_trronly",
      prefValue
    );
    Services.dns.clearCache(true);
    // Global mode is 2 (TRR-first); the per-request override drives behavior.
    setModeAndURI(2, "doh?responseIP=1.2.3.4");
    Services.obs.notifyObservers(
      networkLinkService,
      "network:dns-suffix-list-updated"
    );
    await new TRRDNSListener("example.org", {
      expectedAnswer: expectedIP,
      flags: TRR_ONLY_FLAGS,
    });
  }

  // Default: pref is false → request-mode TRR_ONLY ignores the suffix.
  await checkRequestModeTRROnly(false, "1.2.3.4");
  // Opt-in: pref is true → suffix is honored even for TRR_ONLY requests.
  await checkRequestModeTRROnly(true, "127.0.0.1");

  networkLinkService.dnsSuffixList = [];
  Services.obs.notifyObservers(
    networkLinkService,
    "network:dns-suffix-list-updated"
  );
  Services.prefs.clearUserPref(
    "network.trr.exclude_dns_suffix_in_mode_trronly"
  );
  Services.prefs.clearUserPref("network.trr.split_horizon_mitigations");
  Services.prefs.clearUserPref("network.trr.bootstrapAddr");
});

add_task(async function test_async_resolve_with_trr_server() {
  info("Checking asyncResolveWithTrrServer");
  Services.dns.clearCache(true);
  Services.prefs.setIntPref("network.trr.mode", 0); // TRR-disabled

  await new TRRDNSListener(
    "bar_with_trr1.example.com",
    "2.2.2.2",
    true,
    undefined,
    `https://foo.example.com:${h2Port}/doh?responseIP=2.2.2.2`
  );

  // Test request without trr server, it should return a native dns response.
  await new TRRDNSListener("bar_with_trr1.example.com", "127.0.0.1");

  // Mode 2
  Services.dns.clearCache(true);
  setModeAndURI(2, "doh?responseIP=2.2.2.2");

  await new TRRDNSListener(
    "bar_with_trr2.example.com",
    "3.3.3.3",
    true,
    undefined,
    `https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
  );

  // Test request without trr server, it should return a response from trr server defined in the pref.
  await new TRRDNSListener("bar_with_trr2.example.com", "2.2.2.2");

  // Mode 3
  Services.dns.clearCache(true);
  setModeAndURI(3, "doh?responseIP=2.2.2.2");

  await new TRRDNSListener(
    "bar_with_trr3.example.com",
    "3.3.3.3",
    true,
    undefined,
    `https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
  );

  // Test request without trr server, it should return a response from trr server defined in the pref.
  await new TRRDNSListener("bar_with_trr3.example.com", "2.2.2.2");

  // Mode 5
  Services.dns.clearCache(true);
  setModeAndURI(5, "doh?responseIP=2.2.2.2");

  // When dns is resolved in socket process, we can't set |expectEarlyFail| to true.
  let inSocketProcess = mozinfo.socketprocess_networking;
  await new TRRDNSListener(
    "bar_with_trr3.example.com",
    undefined,
    false,
    undefined,
    `https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`,
    !inSocketProcess
  );

  // Call normal AsyncOpen, it will return result from the native resolver.
  await new TRRDNSListener("bar_with_trr3.example.com", "127.0.0.1");

  // Check that cache is ignored when server is different
  Services.dns.clearCache(true);
  setModeAndURI(3, "doh?responseIP=2.2.2.2");

  await new TRRDNSListener("bar_with_trr4.example.com", "2.2.2.2", true);

  // The record will be fetch again.
  await new TRRDNSListener(
    "bar_with_trr4.example.com",
    "3.3.3.3",
    true,
    undefined,
    `https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
  );

  // The record will be fetch again.
  await new TRRDNSListener(
    "bar_with_trr5.example.com",
    "4.4.4.4",
    true,
    undefined,
    `https://foo.example.com:${h2Port}/doh?responseIP=4.4.4.4`
  );

  // Check no fallback and no blocklisting upon failure
  Services.dns.clearCache(true);
  setModeAndURI(2, "doh?responseIP=2.2.2.2");

  let { inStatus } = await new TRRDNSListener(
    "bar_with_trr6.example.com",
    undefined,
    false,
    undefined,
    `https://foo.example.com:${h2Port}/404`
  );
  Assert.ok(
    !Components.isSuccessCode(inStatus),
    `${inStatus} should be an error code`
  );

  await new TRRDNSListener("bar_with_trr6.example.com", "2.2.2.2", true);

  // Check that DoH push doesn't work
  Services.dns.clearCache(true);
  setModeAndURI(2, "doh?responseIP=2.2.2.2");

  await new TRRDNSListener(
    "bar_with_trr7.example.com",
    "3.3.3.3",
    true,
    undefined,
    `https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
  );

  // Check confirmation is ignored
  Services.dns.clearCache(true);
  setModeAndURI(2, "doh?responseIP=1::ffff");
  Services.prefs.clearUserPref("network.trr.useGET");
  Services.prefs.clearUserPref("network.trr.disable-ECS");
  Services.prefs.setCharPref(
    "network.trr.confirmationNS",
    "confirm.example.com"
  );

  // AsyncResoleWithTrrServer will succeed
  await new TRRDNSListener(
    "bar_with_trr8.example.com",
    "3.3.3.3",
    true,
    undefined,
    `https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
  );

  Services.prefs.setCharPref("network.trr.confirmationNS", "skip");

  // Bad port
  Services.dns.clearCache(true);
  setModeAndURI(2, "doh?responseIP=2.2.2.2");

  ({ inStatus } = await new TRRDNSListener(
    "only_once.example.com",
    undefined,
    false,
    undefined,
    `https://target.example.com:666/404`
  ));
  Assert.ok(
    !Components.isSuccessCode(inStatus),
    `${inStatus} should be an error code`
  );

  // // MOZ_LOG=sync,timestamp,nsHostResolver:5 We should not keep resolving only_once.example.com
  // // TODO: find a way of automating this
  // await new Promise(resolve => {});
});

add_task(test_fetch_time);

add_task(async function test_content_encoding_gzip() {
  info("Checking gzip content encoding");
  Services.dns.clearCache(true);
  Services.prefs.setBoolPref(
    "network.trr.send_empty_accept-encoding_headers",
    false
  );
  setModeAndURI(3, "doh?responseIP=2.2.2.2");

  await new TRRDNSListener("bar.example.com", "2.2.2.2");
  Services.prefs.clearUserPref(
    "network.trr.send_empty_accept-encoding_headers"
  );
});

add_task(async function test_redirect() {
  info("Check handling of redirect");

  // GET
  Services.dns.clearCache(true);
  setModeAndURI(3, "doh?redirect=4.4.4.4{&dns}");
  Services.prefs.setBoolPref("network.trr.useGET", true);
  Services.prefs.setBoolPref("network.trr.disable-ECS", true);

  await new TRRDNSListener("ecs.example.com", "4.4.4.4");

  // POST
  Services.dns.clearCache(true);
  Services.prefs.setBoolPref("network.trr.useGET", false);
  setModeAndURI(3, "doh?redirect=4.4.4.4");

  await new TRRDNSListener("bar.example.com", "4.4.4.4");

  Services.prefs.clearUserPref("network.trr.useGET");
  Services.prefs.clearUserPref("network.trr.disable-ECS");
});

// confirmationNS set without confirmed NS yet
// checks that we properly fall back to DNS is confirmation is not ready yet,
// and wait-for-confirmation pref is true
add_task(async function test_confirmation() {
  info("Checking that we fall back correctly when confirmation is pending");
  Services.dns.clearCache(true);
  Services.prefs.setBoolPref("network.trr.wait-for-confirmation", true);
  setModeAndURI(2, "doh?responseIP=7.7.7.7&slowConfirm=true");
  Services.prefs.setCharPref(
    "network.trr.confirmationNS",
    "confirm.example.com"
  );

  await new TRRDNSListener("example.org", "127.0.0.1");
  await new Promise(resolve => do_timeout(1000, resolve));
  await waitForConfirmation("7.7.7.7");

  // Reset between each test to force re-confirm
  Services.prefs.setCharPref("network.trr.confirmationNS", "skip");

  info("Check that confirmation is skipped in mode 3");
  // This is just a smoke test to make sure lookups succeed immediately
  // in mode 3 without waiting for confirmation.
  Services.dns.clearCache(true);
  setModeAndURI(3, "doh?responseIP=1::ffff&slowConfirm=true");
  Services.prefs.setCharPref(
    "network.trr.confirmationNS",
    "confirm.example.com"
  );

  await new TRRDNSListener("skipConfirmationForMode3.example.com", "1::ffff");

  // Reset between each test to force re-confirm
  Services.prefs.setCharPref("network.trr.confirmationNS", "skip");

  Services.dns.clearCache(true);
  Services.prefs.setBoolPref("network.trr.wait-for-confirmation", false);
  setModeAndURI(2, "doh?responseIP=7.7.7.7&slowConfirm=true");
  Services.prefs.setCharPref(
    "network.trr.confirmationNS",
    "confirm.example.com"
  );

  // DoH available immediately
  await new TRRDNSListener("example.org", "7.7.7.7");

  // Reset between each test to force re-confirm
  Services.prefs.setCharPref("network.trr.confirmationNS", "skip");

  // Fallback when confirmation fails
  Services.dns.clearCache(true);
  Services.prefs.setBoolPref("network.trr.wait-for-confirmation", true);
  setModeAndURI(2, "404");
  Services.prefs.setCharPref(
    "network.trr.confirmationNS",
    "confirm.example.com"
  );

  await waitForConfirmation("7.7.7.7", true);

  await new TRRDNSListener("example.org", "127.0.0.1");

  // Reset
  Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
  Services.prefs.clearUserPref("network.trr.wait-for-confirmation");
});

add_task(test_fqdn);

add_task(async function test_detected_uri() {
  info("Test setDetectedTrrURI");
  Services.dns.clearCache(true);
  Services.prefs.setIntPref("network.trr.mode", 3);
  Services.prefs.clearUserPref("network.trr.uri");
  let defaultURI = gDefaultPref.getCharPref("network.trr.default_provider_uri");
  gDefaultPref.setCharPref(
    "network.trr.default_provider_uri",
    `https://foo.example.com:${h2Port}/doh?responseIP=3.4.5.6`
  );
  await new TRRDNSListener("domainA.example.org.", "3.4.5.6");
  Services.dns.setDetectedTrrURI(
    `https://foo.example.com:${h2Port}/doh?responseIP=1.2.3.4`
  );
  await new TRRDNSListener("domainB.example.org.", "1.2.3.4");
  gDefaultPref.setCharPref("network.trr.default_provider_uri", defaultURI);

  // With a user-set doh uri this time.
  Services.dns.clearCache(true);
  setModeAndURI(2, "doh?responseIP=4.5.6.7");
  await new TRRDNSListener("domainA.example.org.", "4.5.6.7");

  // This should be a no-op, since we have a user-set URI
  Services.dns.setDetectedTrrURI(
    `https://foo.example.com:${h2Port}/doh?responseIP=1.2.3.4`
  );
  await new TRRDNSListener("domainB.example.org.", "4.5.6.7");

  // Test network link status change
  Services.dns.clearCache(true);
  Services.prefs.setIntPref("network.trr.mode", 3);
  Services.prefs.clearUserPref("network.trr.uri");
  gDefaultPref.setCharPref(
    "network.trr.default_provider_uri",
    `https://foo.example.com:${h2Port}/doh?responseIP=3.4.5.6`
  );
  await new TRRDNSListener("domainA.example.org.", "3.4.5.6");
  Services.dns.setDetectedTrrURI(
    `https://foo.example.com:${h2Port}/doh?responseIP=1.2.3.4`
  );
  await new TRRDNSListener("domainB.example.org.", "1.2.3.4");

  let networkLinkService = {
    platformDNSIndications: 0,
    QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
  };

  Services.obs.notifyObservers(
    networkLinkService,
    "network:link-status-changed",
    "changed"
  );

  await new TRRDNSListener("domainC.example.org.", "3.4.5.6");

  gDefaultPref.setCharPref("network.trr.default_provider_uri", defaultURI);
});

add_task(async function test_pref_changes() {
  info("Testing pref change handling");
  Services.prefs.clearUserPref("network.trr.uri");
  let defaultURI = gDefaultPref.getCharPref("network.trr.default_provider_uri");

  async function doThenCheckURI(closure, expectedURI, expectChange = true) {
    let uriChanged;
    if (expectChange) {
      uriChanged = topicObserved("network:trr-uri-changed");
    }
    closure();
    if (expectChange) {
      await uriChanged;
    }
    equal(Services.dns.currentTrrURI, expectedURI);
  }

  // setting the default value of the pref should be reflected in the URI
  await doThenCheckURI(() => {
    gDefaultPref.setCharPref(
      "network.trr.default_provider_uri",
      `https://foo.example.com:${h2Port}/doh?default`
    );
  }, `https://foo.example.com:${h2Port}/doh?default`);

  // the user set value should be reflected in the URI
  await doThenCheckURI(() => {
    Services.prefs.setCharPref(
      "network.trr.uri",
      `https://foo.example.com:${h2Port}/doh?user`
    );
  }, `https://foo.example.com:${h2Port}/doh?user`);

  // A user set pref is selected, so it should be chosen instead of the rollout
  await doThenCheckURI(
    () => {
      Services.prefs.setCharPref(
        "doh-rollout.uri",
        `https://foo.example.com:${h2Port}/doh?rollout`
      );
    },
    `https://foo.example.com:${h2Port}/doh?user`,
    false
  );

  // There is no user set pref, so we go to the rollout pref
  await doThenCheckURI(() => {
    Services.prefs.clearUserPref("network.trr.uri");
  }, `https://foo.example.com:${h2Port}/doh?rollout`);

  // When the URI is set by the rollout addon, detection is allowed
  await doThenCheckURI(() => {
    Services.dns.setDetectedTrrURI(
      `https://foo.example.com:${h2Port}/doh?detected`
    );
  }, `https://foo.example.com:${h2Port}/doh?detected`);

  // Should switch back to the default provided by the rollout addon
  await doThenCheckURI(() => {
    let networkLinkService = {
      platformDNSIndications: 0,
      QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
    };
    Services.obs.notifyObservers(
      networkLinkService,
      "network:link-status-changed",
      "changed"
    );
  }, `https://foo.example.com:${h2Port}/doh?rollout`);

  // Again the user set pref should be chosen
  await doThenCheckURI(() => {
    Services.prefs.setCharPref(
      "network.trr.uri",
      `https://foo.example.com:${h2Port}/doh?user`
    );
  }, `https://foo.example.com:${h2Port}/doh?user`);

  // Detection should not work with a user set pref
  await doThenCheckURI(
    () => {
      Services.dns.setDetectedTrrURI(
        `https://foo.example.com:${h2Port}/doh?detected`
      );
    },
    `https://foo.example.com:${h2Port}/doh?user`,
    false
  );

  // Should stay the same on network changes
  await doThenCheckURI(
    () => {
      let networkLinkService = {
        platformDNSIndications: 0,
        QueryInterface: ChromeUtils.generateQI(["nsINetworkLinkService"]),
      };
      Services.obs.notifyObservers(
        networkLinkService,
        "network:link-status-changed",
        "changed"
      );
    },
    `https://foo.example.com:${h2Port}/doh?user`,
    false
  );

  // Restore the pref
  gDefaultPref.setCharPref("network.trr.default_provider_uri", defaultURI);
});

add_task(async function test_dohrollout_mode() {
  info("Testing doh-rollout.mode");
  Services.prefs.clearUserPref("network.trr.mode");
  Services.prefs.clearUserPref("doh-rollout.mode");

  equal(Services.dns.currentTrrMode, 0);

  async function doThenCheckMode(trrMode, rolloutMode, expectedMode, message) {
    let modeChanged;
    if (Services.dns.currentTrrMode != expectedMode) {
      modeChanged = topicObserved("network:trr-mode-changed");
    }

    if (trrMode != undefined) {
      Services.prefs.setIntPref("network.trr.mode", trrMode);
    }

    if (rolloutMode != undefined) {
      Services.prefs.setIntPref("doh-rollout.mode", rolloutMode);
    }

    if (modeChanged) {
      await modeChanged;
    }
    equal(Services.dns.currentTrrMode, expectedMode, message);
  }

  await doThenCheckMode(2, undefined, 2);
  await doThenCheckMode(3, undefined, 3);
  await doThenCheckMode(5, undefined, 5);
  await doThenCheckMode(2, undefined, 2);
  await doThenCheckMode(0, undefined, 0);
  await doThenCheckMode(1, undefined, 5);
  await doThenCheckMode(6, undefined, 5);

  await doThenCheckMode(2, 0, 2);
  await doThenCheckMode(2, 1, 2);
  await doThenCheckMode(2, 2, 2);
  await doThenCheckMode(2, 3, 2);
  await doThenCheckMode(2, 5, 2);
  await doThenCheckMode(3, 2, 3);
  await doThenCheckMode(5, 2, 5);

  Services.prefs.clearUserPref("network.trr.mode");
  Services.prefs.clearUserPref("doh-rollout.mode");

  await doThenCheckMode(undefined, 2, 2);
  await doThenCheckMode(undefined, 3, 3);

  // All modes that are not 0,2,3 are treated as 5
  await doThenCheckMode(undefined, 5, 5);
  await doThenCheckMode(undefined, 4, 5);
  await doThenCheckMode(undefined, 6, 5);

  await doThenCheckMode(undefined, 2, 2);
  await doThenCheckMode(3, undefined, 3);

  Services.prefs.clearUserPref("network.trr.mode");
  equal(Services.dns.currentTrrMode, 2);
  Services.prefs.clearUserPref("doh-rollout.mode");
  equal(Services.dns.currentTrrMode, 0);
});

add_task(test_ipv6_trr_fallback);

add_task(test_ipv4_trr_fallback);

add_task(test_no_retry_without_doh);

// This test checks that normally when the TRR mode goes from ON -> OFF
// we purge the DNS cache (including TRR), so the entries aren't used on
// networks where they shouldn't. For example - turning on a VPN.
add_task(async function test_purge_trr_cache_on_mode_change() {
  info("Checking that we purge cache when TRR is turned off");
  Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", true);

  Services.prefs.setIntPref("network.trr.mode", 0);
  Services.prefs.setIntPref("doh-rollout.mode", 2);
  Services.prefs.setCharPref(
    "network.trr.uri",
    `https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`
  );

  await new TRRDNSListener("cached.example.com", "3.3.3.3");
  Services.prefs.clearUserPref("doh-rollout.mode");

  await new TRRDNSListener("cached.example.com", "127.0.0.1");

  Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
  Services.prefs.clearUserPref("doh-rollout.mode");
});

add_task(async function test_old_bootstrap_pref() {
  Services.dns.clearCache(true);
  // Note this is a remote address. Setting this pref should have no effect,
  // as this is the old name for the bootstrap pref.
  // If this were to be used, the test would crash when accessing a non-local
  // IP address.
  Services.prefs.setCharPref("network.trr.bootstrapAddress", "1.1.1.1");
  setModeAndURI(Ci.nsIDNSService.MODE_TRRONLY, `doh?responseIP=4.4.4.4`);
  await new TRRDNSListener("testytest.com", "4.4.4.4");
});

add_task(async function test_padding() {
  setModeAndURI(Ci.nsIDNSService.MODE_TRRONLY, `doh`);
  async function CheckPadding(
    pad_length,
    request,
    none,
    ecs,
    padding,
    ecsPadding
  ) {
    Services.prefs.setIntPref("network.trr.padding.length", pad_length);
    Services.dns.clearCache(true);
    Services.prefs.setBoolPref("network.trr.padding", false);
    Services.prefs.setBoolPref("network.trr.disable-ECS", false);
    await new TRRDNSListener(request, none);

    Services.dns.clearCache(true);
    Services.prefs.setBoolPref("network.trr.padding", false);
    Services.prefs.setBoolPref("network.trr.disable-ECS", true);
    await new TRRDNSListener(request, ecs);

    Services.dns.clearCache(true);
    Services.prefs.setBoolPref("network.trr.padding", true);
    Services.prefs.setBoolPref("network.trr.disable-ECS", false);
    await new TRRDNSListener(request, padding);

    Services.dns.clearCache(true);
    Services.prefs.setBoolPref("network.trr.padding", true);
    Services.prefs.setBoolPref("network.trr.disable-ECS", true);
    await new TRRDNSListener(request, ecsPadding);
  }

  // short domain name
  await CheckPadding(
    16,
    "a.pd",
    "2.2.0.22",
    "2.2.0.41",
    "1.1.0.48",
    "1.1.0.48"
  );
  await CheckPadding(256, "a.pd", "2.2.0.22", "2.2.0.41", "1.1.1.0", "1.1.1.0");

  // medium domain name
  await CheckPadding(
    16,
    "has-padding.pd",
    "2.2.0.32",
    "2.2.0.51",
    "1.1.0.48",
    "1.1.0.64"
  );
  await CheckPadding(
    128,
    "has-padding.pd",
    "2.2.0.32",
    "2.2.0.51",
    "1.1.0.128",
    "1.1.0.128"
  );
  await CheckPadding(
    80,
    "has-padding.pd",
    "2.2.0.32",
    "2.2.0.51",
    "1.1.0.80",
    "1.1.0.80"
  );

  // long domain name
  await CheckPadding(
    16,
    "abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.pd",
    "2.2.0.131",
    "2.2.0.150",
    "1.1.0.160",
    "1.1.0.160"
  );
  await CheckPadding(
    128,
    "abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.pd",
    "2.2.0.131",
    "2.2.0.150",
    "1.1.1.0",
    "1.1.1.0"
  );
  await CheckPadding(
    80,
    "abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.abcdefghijklmnopqrstuvwxyz0123456789.pd",
    "2.2.0.131",
    "2.2.0.150",
    "1.1.0.160",
    "1.1.0.160"
  );
});

// Can't test for socket process since telemetry is captured in different process.
add_task(
  { skip_if: () => mozinfo.socketprocess_networking },
  async function test_trr_pb_telemetry() {
    setModeAndURI(Ci.nsIDNSService.MODE_TRRONLY, `doh`);
    Services.dns.clearCache(true);
    Services.fog.initializeFOG();
    Services.fog.testResetFOG();
    await new TRRDNSListener("testytest.com", { expectedAnswer: "5.5.5.5" });

    Assert.equal(
      await Glean.networking.trrRequestCount.regular.testGetValue(),
      2
    ); // One for IPv4 and one for IPv6.
    Assert.equal(
      await Glean.networking.trrRequestCount.private.testGetValue(),
      null
    );

    await new TRRDNSListener("testytest.com", {
      expectedAnswer: "5.5.5.5",
      originAttributes: { privateBrowsingId: 1 },
    });

    Assert.equal(
      await Glean.networking.trrRequestCount.regular.testGetValue(),
      2
    );
    Assert.equal(
      await Glean.networking.trrRequestCount.private.testGetValue(),
      2
    );
    // We've made 4 TRR requests.
    Assert.equal(
      await Glean.networking.trrRequestSize.other.testGetValue().count,
      4
    );
    Assert.equal(
      await Glean.networking.trrResponseSize.other.testGetValue().count,
      4
    );
  }
);

add_task(
  { skip_if: () => mozinfo.socketprocess_networking },
  async function test_trr_timing_telemetry() {
    setModeAndURI(Ci.nsIDNSService.MODE_TRRONLY, `doh`);
    Services.dns.clearCache(true);

    // Close the previous TRR connection.
    Services.obs.notifyObservers(null, "net:cancel-all-connections");
    await new Promise(r => do_timeout(3000, r));

    Services.fog.testResetFOG();
    // Disable IPv6, so we only send one TRR request.
    Services.prefs.setBoolPref("network.dns.disableIPv6", true);
    await new TRRDNSListener("timing.com", { expectedAnswer: "5.5.5.5" });

    await new Promise(r => do_timeout(100, r));

    let dnsStart = await Glean.networking.trrDnsStart.other.testGetValue();
    let dnsEnd = await Glean.networking.trrDnsEnd.other.testGetValue();
    let tcpConnection =
      await Glean.networking.trrTcpConnection.other.testGetValue();
    let tlsHandshake =
      await Glean.networking.trrTlsHandshake.other.testGetValue();
    let openToFirstSent =
      await Glean.networking.trrOpenToFirstSent.other.testGetValue();
    let firstSentToLastReceived =
      await Glean.networking.trrFirstSentToLastReceived.other.testGetValue();
    let openToFirstReceived =
      await Glean.networking.trrOpenToFirstReceived.other.testGetValue();
    let completeLoad =
      await Glean.networking.trrCompleteLoad.other.testGetValue();

    info("dnsStart=" + JSON.stringify(dnsStart));
    info("dnsEnd=" + JSON.stringify(dnsEnd));
    info("tcpConnection=" + JSON.stringify(tcpConnection));
    info("tlsHandshake=" + JSON.stringify(tlsHandshake));
    info("openToFirstSent=" + JSON.stringify(openToFirstSent));
    info("firstSentToLastReceived=" + JSON.stringify(firstSentToLastReceived));
    info("openToFirstReceived=" + JSON.stringify(openToFirstReceived));
    info("completeLoad=" + JSON.stringify(completeLoad));

    Assert.equal(dnsStart.count, 1);
    Assert.equal(dnsEnd.count, 1);
    Assert.equal(tcpConnection.count, 1);
    Assert.equal(tlsHandshake.count, 1);
    Assert.equal(openToFirstSent.count, 1);
    Assert.equal(firstSentToLastReceived.count, 1);
    Assert.equal(openToFirstReceived.count, 1);
    Assert.equal(completeLoad.count, 1);

    function getValue(obj) {
      const keys = Object.keys(obj);
      return keys.length ? +keys[0] : 0;
    }
    Assert.greaterOrEqual(
      getValue(openToFirstReceived.values),
      getValue(openToFirstSent.values),
      "openToFirstReceived >= openToFirstSent"
    );
    Assert.greaterOrEqual(
      getValue(completeLoad.values),
      getValue(openToFirstReceived.values),
      "completeLoad >= openToFirstReceived"
    );
  }
);

add_task(
  { skip_if: () => mozinfo.socketprocess_networking },
  async function test_trr_request_per_conn_telemetry() {
    setModeAndURI(Ci.nsIDNSService.MODE_TRRONLY, `doh`);
    Services.dns.clearCache(true);

    // Close the previous TRR connection.
    Services.obs.notifyObservers(null, "net:cancel-all-connections");
    await new Promise(r => do_timeout(3000, r));

    Services.fog.testResetFOG();
    Services.prefs.setBoolPref("network.dns.disableIPv6", false);
    await new TRRDNSListener("timing.com", { expectedAnswer: "5.5.5.5" });

    // Close the TRR connection again, so trr_request_count_per_conn
    // can be recorded.
    Services.obs.notifyObservers(null, "net:cancel-all-connections");
    await new Promise(r => do_timeout(3000, r));

    let requestPerConn =
      await Glean.networking.trrRequestCountPerConn.other.testGetValue();

    info("requestPerConn=" + JSON.stringify(requestPerConn));

    Assert.greaterOrEqual(requestPerConn, 2);
  }
);

Messung V0.5 in Prozent
C=89 H=97 G=93

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet am  2026-09-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.