summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/mochitest/test_ext_dnr_tabIds.html
blob: 0278a8ccc8d06cde0e70b042d2fb338115b7eb64 (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 tabIds condition</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";

// While most DNR tests are xpcshell tests, this one is a mochitest because it
// is not possible to create a tab and get a tabId in a xpcshell test.

// toolkit/components/extensions/test/xpcshell/test_ext_dnr_tabIds.js does
// exist, as an isolated xpcshell is needed to verify that the internals are
// working as expected. A mochitest is not a good fit for that because it has
// built-in add-ons that may affect the observed behavior.

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

add_task(async function match_by_tabIds() {
  let extension = ExtensionTestUtils.loadExtension({
    async background() {
      async function createTabAndPort() {
        let portPromise = new Promise(resolve => {
          browser.runtime.onConnect.addListener(function listener(port) {
            browser.runtime.onConnect.removeListener(listener);
            browser.test.assertEq("port_from_tab", port.name, "Got port");
            resolve(port);
          });
        });
        const tab = await browser.tabs.create({ url: "tab.html" });
        const port = await portPromise;
        browser.test.assertEq(tab.id, port.sender.tab.id, "Got port from tab");
        browser.test.assertTrue(tab.id > 0, `tabId must be valid: ${tab.id}`);
        tab.port = port;
        return tab;
      }
      async function getFinalUrlForFetchInTab(tabWithPort, url) {
        const port = tabWithPort.port; // from createTabAndPort.
        return new Promise(resolve => {
          port.onMessage.addListener(function listener(responseUrl) {
            port.onMessage.removeListener(listener);
            resolve(responseUrl);
          });
          port.postMessage(url);
        });
      }
      let tab1 = await createTabAndPort();
      let tab2 = await createTabAndPort();

      const URL_PREFIX = "https://example.com/tests/toolkit/components/extensions/test/mochitest/file_sample.txt";

      function makeRedirect(id, condition, url) {
        return {
          id,
          // The test sends a request to example.net and expects a redirect to
          // URL_PREFIX (example.com).
          condition: { requestDomains: ["example.net"], ...condition },
          action: { type: "redirect", redirect: { url }},
        };
      }
      await browser.declarativeNetRequest.updateSessionRules({
        addRules: [
          makeRedirect(1, { tabIds: [-1] }, `${URL_PREFIX}?tabId/-1`),
          makeRedirect(2, { tabIds: [tab1.id] }, `${URL_PREFIX}?tabId/tab1`),
          makeRedirect(
            3,
            { excludedTabIds: [-1, tab1.id] },
            `${URL_PREFIX}?tabId/not-1,not-tab1`
          ),
        ],
      });

      browser.test.assertEq(
        `${URL_PREFIX}?tabId/-1`,
        (await fetch("https://example.net/?pre-redirect-bg")).url,
        "Request from background should match tabIds: [-1]"
      );
      browser.test.assertEq(
        `${URL_PREFIX}?tabId/tab1`,
        await getFinalUrlForFetchInTab(tab1, "https://example.net/?pre-tab1"),
        "Request from tab1 should match tabIds: [tab1]"
      );
      browser.test.assertEq(
        `${URL_PREFIX}?tabId/not-1,not-tab1`,
        await getFinalUrlForFetchInTab(tab2, "https://example.net/?pre-tab2"),
        "Request from tab2 should match excludedTabIds: [-1, tab1]"
      );

      await browser.tabs.remove(tab1.id);
      await browser.tabs.remove(tab2.id);

      browser.test.sendMessage("done");
    },
    temporarilyInstalled: true, // Needed for granted_host_permissions
    manifest: {
      manifest_version: 3,
      host_permissions: ["*://example.com/*", "*://example.net/*"],
      permissions: ["declarativeNetRequest"],
      granted_host_permissions: true,
    },
    files: {
      "tab.html": `<!DOCTYPE html><script src="tab.js"><\/script>`,
      "tab.js": () => {
        let port = browser.runtime.connect({ name: "port_from_tab" });
        port.onMessage.addListener(async url => {
          try {
            let res = await fetch(url);
            port.postMessage(res.url);
          } catch (e) {
            port.postMessage(e.message);
          }
        });
      },
    },
  });
  await extension.startup();
  await extension.awaitMessage("done");

  await extension.unload();
});

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