summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_dnr_download.js
blob: 5a5ac79473436d8d3025a14c4294f557753d7797 (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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
"use strict";

let server = createHttpServer({ hosts: ["example.com"] });
let downloadReqCount = 0;
server.registerPathHandler("/downloadtest", () => {
  ++downloadReqCount;
});

add_setup(async () => {
  let downloadDir = await IOUtils.createUniqueDirectory(
    Services.dirsvc.get("TmpD", Ci.nsIFile).path,
    "downloadDirForDnrDownloadTest"
  );
  info(`Using download directory ${downloadDir.path}`);

  Services.prefs.setIntPref("browser.download.folderList", 2);
  Services.prefs.setCharPref("browser.download.dir", downloadDir);

  registerCleanupFunction(async () => {
    Services.prefs.clearUserPref("browser.download.folderList");
    Services.prefs.clearUserPref("browser.download.dir");
    try {
      await IOUtils.remove(downloadDir);
    } catch (e) {
      info(`Failed to remove ${downloadDir} because: ${e}`);
      // Downloaded files should have been deleted by tests.
      // Clean up + report error otherwise.
      let children = await IOUtils.getChildren(downloadDir).catch(e => e);
      ok(false, `Unexpected files in downloadDir: ${children}`);
      await IOUtils.remove(downloadDir, { recursive: true });
    }
  });

  Services.prefs.setBoolPref("extensions.dnr.enabled", true);
});

// Test for Bug 1579911: Check that download requests created by the
// downloads.download API can be observed by extensions.
// The webRequest version is in test_ext_webRequest_download.js.
add_task(async function test_download_api_can_be_blocked_by_dnr() {
  let extension = ExtensionTestUtils.loadExtension({
    manifest: {
      manifest_version: 3,
      permissions: ["declarativeNetRequest", "downloads"],
      // No host_permissions here because neither the downloads nor the DNR API
      // require host permissions to download and/or block the request.
    },
    // Not needed, but to rule out downloads being blocked by CSP:
    allowInsecureRequests: true,
    background: async function () {
      await browser.declarativeNetRequest.updateSessionRules({
        addRules: [
          {
            id: 1,
            condition: { urlFilter: "|http://example.com/downloadtest" },
            action: { type: "block" },
          },
        ],
      });

      browser.downloads.onChanged.addListener(delta => {
        browser.test.assertEq(delta.state.current, "interrupted");
        browser.test.sendMessage("done");
      });

      await browser.downloads.download({
        url: "http://example.com/downloadtest",
        filename: "example.txt",
      });
    },
  });

  await extension.startup();
  await extension.awaitMessage("done");
  await extension.unload();

  Assert.equal(downloadReqCount, 0, "Did not expect any download requests");
});

add_task(async function test_download_api_ignores_dnr_from_other_extension() {
  let extension = ExtensionTestUtils.loadExtension({
    manifest: {
      manifest_version: 3,
      permissions: ["declarativeNetRequest"],
    },
    background: async function () {
      await browser.declarativeNetRequest.updateSessionRules({
        addRules: [
          {
            id: 1,
            condition: { urlFilter: "|http://example.com/downloadtest" },
            action: { type: "block" },
          },
        ],
      });

      browser.test.sendMessage("dnr_registered");
    },
  });

  let otherExtension = ExtensionTestUtils.loadExtension({
    manifest: {
      permissions: ["downloads"],
    },
    background: async function () {
      let downloadDonePromise = new Promise(resolve => {
        browser.downloads.onChanged.addListener(delta => {
          if (delta.state.current === "interrupted") {
            browser.test.fail("Download was unexpectedly interrupted");
            browser.test.notifyFail("done");
          } else if (delta.state.current === "complete") {
            resolve();
          }
        });
      });

      // This download should not have been interrupted by the other extension,
      // because declarativeNetRequest cannot match requests from other
      // extensions.
      let downloadId = await browser.downloads.download({
        url: "http://example.com/downloadtest",
        filename: "example_from_other_ext.txt",
      });
      await downloadDonePromise;
      browser.test.log("Download completed, removing file...");
      // TODO bug 1654819: On Windows the file may be recreated.
      await browser.downloads.removeFile(downloadId);
      browser.test.notifyPass("done");
    },
  });

  await extension.startup();
  await extension.awaitMessage("dnr_registered");

  await otherExtension.startup();
  await otherExtension.awaitFinish("done");
  await otherExtension.unload();
  await extension.unload();

  Assert.equal(downloadReqCount, 1, "Expected one download request");
  downloadReqCount = 0;
});

add_task(
  {
    pref_set: [["extensions.dnr.match_requests_from_other_extensions", true]],
  },
  async function test_download_api_dnr_blocks_other_extension_with_pref() {
    let extension = ExtensionTestUtils.loadExtension({
      manifest: {
        manifest_version: 3,
        permissions: ["declarativeNetRequest"],
      },
      background: async function () {
        await browser.declarativeNetRequest.updateSessionRules({
          addRules: [
            {
              id: 1,
              condition: { urlFilter: "|http://example.com/downloadtest" },
              action: { type: "block" },
            },
          ],
        });

        browser.test.sendMessage("dnr_registered");
      },
    });
    let otherExtension = ExtensionTestUtils.loadExtension({
      manifest: {
        permissions: ["downloads"],
      },
      background: async function () {
        browser.downloads.onChanged.addListener(delta => {
          browser.test.assertEq(delta.state.current, "interrupted");
          browser.test.sendMessage("done");
        });
        await browser.downloads.download({
          url: "http://example.com/downloadtest",
          filename: "example_from_other_ext_with_pref.txt",
        });
      },
    });

    await extension.startup();
    await extension.awaitMessage("dnr_registered");
    await otherExtension.startup();
    await otherExtension.awaitMessage("done");
    await otherExtension.unload();
    await extension.unload();

    Assert.equal(downloadReqCount, 0, "Did not expect any download requests");
  }
);