summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_permissions_fetch.js
blob: f9c1b360a032ee295d64d427deb936afa58ea5cc (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
"use strict";

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

const server = createHttpServer({ hosts: ["example.com", "example.net"] });
server.registerDirectory("/data/", do_get_file("data"));

const { ExtensionPermissions } = ChromeUtils.importESModule(
  "resource://gre/modules/ExtensionPermissions.sys.mjs"
);

function grantOptional({ extension: ext }, origins) {
  return ExtensionPermissions.add(ext.id, { origins, permissions: [] }, ext);
}

function revokeOptional({ extension: ext }, origins) {
  return ExtensionPermissions.remove(ext.id, { origins, permissions: [] }, ext);
}

// Test granted optional permissions work with XHR/fetch in new processes.
add_task(
  {
    pref_set: [["dom.ipc.keepProcessesAlive.extension", 0]],
  },
  async function test_fetch_origin_permissions_change() {
    let extension = ExtensionTestUtils.loadExtension({
      manifest: {
        host_permissions: ["http://example.com/*"],
        optional_permissions: ["http://example.net/*"],
      },
      files: {
        "page.js"() {
          fetch("http://example.net/data/file_sample.html")
            .then(req => req.text())
            .then(text => browser.test.sendMessage("done", { text }))
            .catch(e => browser.test.sendMessage("done", { error: e.message }));
        },
        "page.html": `<!DOCTYPE html><meta charset="utf-8"><script src="page.js"></script>`,
      },
    });

    await extension.startup();

    let osPid;
    {
      // Grant permissions before extension process exists.
      await grantOptional(extension, ["http://example.net/*"]);

      let page = await ExtensionTestUtils.loadContentPage(
        extension.extension.baseURI.resolve("page.html")
      );

      let { text } = await extension.awaitMessage("done");
      ok(text.includes("Sample text"), "Can read from granted optional host.");

      osPid = page.browsingContext.currentWindowGlobal.osPid;
      await page.close();
    }

    // Release the extension process so that next part starts a new one.
    Services.ppmm.releaseCachedProcesses();

    {
      // Revoke permissions and confirm fetch fails.
      await revokeOptional(extension, ["http://example.net/*"]);

      let page = await ExtensionTestUtils.loadContentPage(
        extension.extension.baseURI.resolve("page.html")
      );

      let { error } = await extension.awaitMessage("done");
      ok(error.includes("NetworkError"), `Expected error: ${error}`);

      if (WebExtensionPolicy.useRemoteWebExtensions) {
        notEqual(
          osPid,
          page.browsingContext.currentWindowGlobal.osPid,
          "Second part of the test used a new process."
        );
      }

      await page.close();
    }

    await extension.unload();
  }
);