summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/mochitest/test_ext_dnr_upgradeScheme.html
blob: 43bc8a5a005a466503b49414423f283406dd3768 (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
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <title>DNR with upgradeScheme action</title>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
  <script type="text/javascript" src="head.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
"use strict";

// This test is not a xpcshell test, because we want to test upgrades to https,
// and HttpServer helper does not support https (bug 1742061).

add_setup(async () => {
  await SpecialPowers.pushPrefEnv({
    set: [
      ["extensions.manifestV3.enabled", true],
      ["extensions.dnr.enabled", true],
      ["extensions.dnr.match_requests_from_other_extensions", true],
    ],
  });
});

// Tests that the upgradeScheme action works as expected:
// - http should be upgraded to https
// - after the https upgrade the request should happen instead of being stuck
//   in a upgrade redirect loop.
add_task(async function upgradeScheme_with_dnr() {
  let extension = ExtensionTestUtils.loadExtension({
    async background() {
      await browser.declarativeNetRequest.updateSessionRules({
        addRules: [{ id: 1, condition: { requestDomains: ["example.com"] }, action: { type: "upgradeScheme" } }],
      });

      let sanityCheckResponse = await fetch(
        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
        "http://example.net/tests/toolkit/components/extensions/test/mochitest/file_sample.txt"
      );
      browser.test.assertEq(
        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
        "http://example.net/tests/toolkit/components/extensions/test/mochitest/file_sample.txt",
        sanityCheckResponse.url,
        "non-matching request should not be upgraded"
      );

      let res = await fetch(
        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
        "http://example.com/tests/toolkit/components/extensions/test/mochitest/file_sample.txt"
      );
      browser.test.assertEq(
        "https://example.com/tests/toolkit/components/extensions/test/mochitest/file_sample.txt",
        res.url,
        "upgradeScheme should have upgraded to https"
      );
      // Server adds "Access-Control-Allow-Origin: *" to file_sample.txt, so
      // we should be able to read the response despite no host_permissions.
      browser.test.assertEq("Sample", await res.text(), "read body with CORS");

      browser.test.sendMessage("dnr_registered");
    },
    manifest: {
      manifest_version: 3,
      // Note: host_permissions missing. upgradeScheme should not need it.
      permissions: ["declarativeNetRequest"],
    },
    allowInsecureRequests: true,
  });
  await extension.startup();
  await extension.awaitMessage("dnr_registered");

  // The request made by otherExtension is affected by the DNR rule from the
  // extension because extensions.dnr.match_requests_from_other_extensions was
  // set to true. A realistic alternative would have been to trigger the fetch
  // requests from a content page instead of the extension.
  let otherExtension = ExtensionTestUtils.loadExtension({
    async background() {
      let firstRequestPromise = new Promise(resolve => {
        let count = 0;
        browser.webRequest.onBeforeRequest.addListener(
          ({ url }) => {
            ++count;
            browser.test.assertTrue(
              count <= 2,
              `Expected at most two requests; got ${count} to ${url}`
            );
            resolve(url);
          },
          { urls: ["*://example.com/?test_dnr_upgradeScheme"] }
        );
      });
      // Round-trip through ext-webRequest.js implementation to ensure that the
      // listener has been registered (workaround for bug 1300234).
      await browser.webRequest.handlerBehaviorChanged();

      // eslint-disable-next-line @microsoft/sdl/no-insecure-url
      const insecureInitialUrl = "http://example.com/?test_dnr_upgradeScheme";
      browser.test.log(`Requesting insecure URL: ${insecureInitialUrl}`);

      let req = await fetch(insecureInitialUrl);
      browser.test.assertEq(
        "https://example.com/?test_dnr_upgradeScheme",
        req.url,
        "upgradeScheme action upgraded http to https"
      );
      browser.test.assertEq(200, req.status, "Correct HTTP status");

      await req.text(); // Verify that the body can be read, just in case.

      // Sanity check that the test did not pass trivially due to an automatic
      // https upgrade of the extension / test environment.
      browser.test.assertEq(
        insecureInitialUrl,
        await firstRequestPromise,
        "Initial URL should be http"
      );

      browser.test.sendMessage("tested_dnr_upgradeScheme");
    },
    manifest: {
      host_permissions: ["*://example.com/*"],
      permissions: ["webRequest"],
    },
  });
  await otherExtension.startup();
  await otherExtension.awaitMessage("tested_dnr_upgradeScheme");
  await otherExtension.unload();

  await extension.unload();
});

</script>
</body>
</html>