summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/about/browser_aboutNetError_native_fallback.js
blob: 4a87ad5cce8704e997943f879f222327fe328337 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

let oldProxyType = Services.prefs.getIntPref("network.proxy.type");

function reset() {
  Services.prefs.clearUserPref("network.trr.display_fallback_warning");
  Services.prefs.clearUserPref("network.trr.mode");
  Services.prefs.clearUserPref("network.dns.native-is-localhost");
  Services.prefs.clearUserPref("doh-rollout.disable-heuristics");
  Services.prefs.setIntPref("network.proxy.type", oldProxyType);
  Services.prefs.clearUserPref("network.trr.uri");

  Services.dns.setHeuristicDetectionResult(Ci.nsITRRSkipReason.TRR_OK);
}

// This helper verifies that the given url loads correctly
async function verifyLoad(url, testName) {
  let browser;
  await BrowserTestUtils.openNewForegroundTab(
    gBrowser,
    () => {
      gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, url);
      browser = gBrowser.selectedBrowser;
    },
    true
  );

  await SpecialPowers.spawn(browser, [{ url, testName }], function (args) {
    const doc = content.document;
    ok(
      doc.documentURI == args.url,
      "Should have loaded page: " + args.testName
    );
  });
  BrowserTestUtils.removeTab(gBrowser.selectedTab);
}

// This helper verifies that loading the given url will lead to an error -- the fallback warning if the parameter is true
async function verifyError(url, fallbackWarning, testName) {
  // Clear everything.
  Services.telemetry.clearEvents();
  await TestUtils.waitForCondition(() => {
    let events = Services.telemetry.snapshotEvents(
      Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
      true
    ).content;
    return !events || !events.length;
  });
  Services.telemetry.setEventRecordingEnabled("security.doh.neterror", true);

  let browser;
  let pageLoaded;
  await BrowserTestUtils.openNewForegroundTab(
    gBrowser,
    () => {
      gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, url);
      browser = gBrowser.selectedBrowser;
      pageLoaded = BrowserTestUtils.waitForErrorPage(browser);
    },
    false
  );

  info("Loading and waiting for the net error");
  await pageLoaded;

  await SpecialPowers.spawn(
    browser,
    [{ url, fallbackWarning, testName }],
    function (args) {
      const doc = content.document;

      ok(doc.documentURI.startsWith("about:neterror"));
      "Should be showing error page: " + args.testName;

      const titleEl = doc.querySelector(".title-text");
      const actualDataL10nID = titleEl.getAttribute("data-l10n-id");
      if (args.fallbackWarning) {
        is(
          actualDataL10nID,
          "dns-not-found-native-fallback-title2",
          "Correct fallback warning error page title is set: " + args.testName
        );
      } else {
        ok(
          actualDataL10nID != "dns-not-found-native-fallback-title2",
          "Should not show fallback warning: " + args.testName
        );
      }
    }
  );

  if (fallbackWarning) {
    let loadEvent = await TestUtils.waitForCondition(() => {
      let events = Services.telemetry.snapshotEvents(
        Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
        true
      ).content;
      return events?.find(
        e => e[1] == "security.doh.neterror" && e[2] == "load"
      );
    }, "recorded telemetry for the load");
    loadEvent.shift();
    Assert.deepEqual(loadEvent, [
      "security.doh.neterror",
      "load",
      "dohwarning",
      "NativeFallbackWarning",
      {
        mode: "0",
        provider_key: "0.0.0.0",
        skip_reason: "TRR_HEURISTIC_TRIPPED_CANARY",
      },
    ]);
  }
  BrowserTestUtils.removeTab(gBrowser.selectedTab);
}

// This test verifies that the native fallback warning appears in the desired scenarios, and only in those scenarios
add_task(async function nativeFallbackWarnings() {
  Services.prefs.setBoolPref("network.dns.native-is-localhost", true);

  // Disable heuristics since they will attempt to connect to external servers
  Services.prefs.setBoolPref("doh-rollout.disable-heuristics", true);

  // Set a local TRR to prevent external connections
  Services.prefs.setCharPref("network.trr.uri", "https://0.0.0.0/dns-query");

  registerCleanupFunction(reset);

  // Test without DoH
  Services.prefs.setIntPref(
    "network.trr.mode",
    Ci.nsIDNSService.MODE_NATIVEONLY
  );

  Services.dns.clearCache(true);
  await verifyLoad("https://www.example.com/", "valid url, no error");

  // Should not trigger the native fallback warning
  await verifyError("https://does-not-exist.test", false, "non existent url");

  // We need to disable proxy, otherwise TRR isn't used for name resolution.
  Services.prefs.setIntPref("network.proxy.type", 0);

  // Switch to TRR first
  Services.prefs.setIntPref(
    "network.trr.mode",
    Ci.nsIDNSService.MODE_NATIVEONLY
  );
  Services.prefs.setBoolPref("network.trr.display_fallback_warning", true);

  // Simulate a tripped canary network
  Services.dns.setHeuristicDetectionResult(
    Ci.nsITRRSkipReason.TRR_HEURISTIC_TRIPPED_CANARY
  );

  // We should see the fallback warning displayed in both of these scenarios
  Services.dns.clearCache(true);
  await verifyError(
    "https://www.example.com",
    true,
    "canary heuristic tripped"
  );
  await verifyError(
    "https://does-not-exist.test",
    true,
    "canary heuristic tripped - non existent url"
  );

  reset();
});