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

const HOSTS = new Set(["example.com", "example.org"]);

const server = createHttpServer({ hosts: HOSTS });

const BASE_URL = "http://example.com";

server.registerDirectory("/data/", do_get_file("data"));

server.registerPathHandler("/dummy", (request, response) => {
  response.setStatusLine(request.httpVersion, 200, "OK");
  response.setHeader("Content-Type", "text/html", false);
  response.write("<!DOCTYPE html><html></html>");
});

function sendMessage(page, msg, data) {
  return MessageChannel.sendMessage(page.browser.messageManager, msg, data);
}

add_setup(() => {
  // Make sure to invalidate WebExtensions API schemas that may be cached
  // in the StartupCache when this test runs with conditioned-profiles.
  //
  // These tests are subject to be hitting failures consistently on
  // landing API schema changes to the WebExtensions API permissions.
  // or other API schema properties that are explicitly covered by
  // this tests (e.g. errors expected to be emitted by postprocess
  // helper functions).
  Services.obs.notifyObservers(null, "startupcache-invalidate");
});

add_task(async function test_permissions() {
  function background() {
    browser.webRequest.onBeforeRequest.addListener(
      details => {
        if (details.url.includes("_original")) {
          let redirectUrl = details.url
            .replace("example.org", "example.com")
            .replace("_original", "_redirected");
          return { redirectUrl };
        }
        return {};
      },
      { urls: ["<all_urls>"] },
      ["blocking"]
    );
  }

  let extensionData = {
    manifest: {
      permissions: ["webRequest", "webRequestBlocking", "<all_urls>"],
    },
    background,
  };

  let extension = ExtensionTestUtils.loadExtension(extensionData);
  await extension.startup();

  const frameScript = () => {
    const messageListener = {
      async receiveMessage() {
        /* globals content */
        let doc = content.document;
        let iframe = doc.createElement("iframe");
        doc.body.appendChild(iframe);

        let promise = new Promise(resolve => {
          let listener = event => {
            content.removeEventListener("message", listener);
            resolve(event.data);
          };
          content.addEventListener("message", listener);
        });

        iframe.setAttribute(
          "src",
          "http://example.com/data/file_WebRequest_permission_original.html"
        );
        let result = await promise;
        doc.body.removeChild(iframe);
        return result;
      },
    };

    const { MessageChannel } = ChromeUtils.importESModule(
      "resource://testing-common/MessageChannel.sys.mjs"
    );
    MessageChannel.addListener(this, "Test:Check", messageListener);
  };

  let contentPage = await ExtensionTestUtils.loadContentPage(
    `${BASE_URL}/dummy`
  );
  await contentPage.loadFrameScript(frameScript);

  let results = await sendMessage(contentPage, "Test:Check", {});
  equal(
    results.page,
    "redirected",
    "Regular webRequest redirect works on an unprivileged page"
  );
  equal(
    results.script,
    "redirected",
    "Regular webRequest redirect works from an unprivileged page"
  );

  Services.prefs.setBoolPref("extensions.webapi.testing", true);
  Services.prefs.setBoolPref("extensions.webapi.testing.http", true);

  results = await sendMessage(contentPage, "Test:Check", {});
  equal(
    results.page,
    "original",
    "webRequest redirect fails on a privileged page"
  );
  equal(
    results.script,
    "original",
    "webRequest redirect fails from a privileged page"
  );

  await extension.unload();
  await contentPage.close();
});

add_task(async function test_missing_required_perm_for_blocking_error() {
  function background() {
    const expectedError =
      "Using webRequest.addListener with the blocking option " +
      "requires the 'webRequestBlocking' permission.";
    const expectedErrorOnAuthRequired =
      "Using webRequest.onAuthRequired.addListener with the blocking option " +
      "requires either the 'webRequestBlocking' or 'webRequestAuthProvider' permission.";

    const blockingEvents = [
      "onBeforeRequest",
      "onBeforeSendHeaders",
      "onHeadersReceived",
      "onAuthRequired",
    ];

    for (let eventName of blockingEvents) {
      browser.test.assertThrows(
        () => {
          browser.webRequest[eventName].addListener(
            () => {},
            { urls: ["<all_urls>"] },
            ["blocking"]
          );
        },
        eventName === "onAuthRequired"
          ? expectedErrorOnAuthRequired
          : expectedError,
        `Got the expected exception for a blocking webRequest.${eventName} listener`
      );
    }
  }

  const extensionData = {
    manifest: { permissions: ["webRequest", "<all_urls>"] },
    background,
  };

  const extension = ExtensionTestUtils.loadExtension(extensionData);

  await extension.startup();
  await extension.unload();
});