summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_secfetch.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /toolkit/components/extensions/test/xpcshell/test_ext_secfetch.js
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_secfetch.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_secfetch.js352
1 files changed, 352 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_secfetch.js b/toolkit/components/extensions/test/xpcshell/test_ext_secfetch.js
new file mode 100644
index 0000000000..e8b3dcfca8
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_secfetch.js
@@ -0,0 +1,352 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
+
+const server = createHttpServer({
+ // We need the 127.0.0.1 proxy because the sec-fetch headers are not sent to
+ // "127.0.0.1:<any port other than 80 or 443>".
+ hosts: ["127.0.0.1", "127.0.0.2"],
+});
+
+server.registerPathHandler("/page.html", (request, response) => {
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.setHeader("Access-Control-Allow-Origin", "*");
+});
+
+server.registerPathHandler("/return_headers", (request, response) => {
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "text/plain");
+ response.setHeader("Access-Control-Allow-Origin", "*");
+ if (request.method === "OPTIONS") {
+ // Handle CORS preflight request.
+ response.setHeader("Access-Control-Allow-Methods", "GET, PUT");
+ return;
+ }
+
+ let headers = {};
+ for (let header of [
+ "sec-fetch-site",
+ "sec-fetch-dest",
+ "sec-fetch-mode",
+ "sec-fetch-user",
+ ]) {
+ if (request.hasHeader(header)) {
+ headers[header] = request.getHeader(header);
+ }
+ }
+
+ if (request.hasHeader("origin")) {
+ headers.origin = request
+ .getHeader("origin")
+ .replace(/moz-extension:\/\/[^\/]+/, "moz-extension://<placeholder>");
+ }
+
+ response.write(JSON.stringify(headers));
+});
+
+async function contentScript() {
+ let content_fetch;
+ if (browser.runtime.getManifest().manifest_version === 2) {
+ content_fetch = content.fetch;
+ } else {
+ // In MV3, there is no content variable.
+ browser.test.assertEq(typeof content, "undefined", "no .content in MV3");
+ // In MV3, window.fetch is the original fetch with the page's principal.
+ content_fetch = window.fetch.bind(window);
+ }
+ let results = await Promise.allSettled([
+ // A cross-origin request from the content script.
+ fetch("http://127.0.0.1/return_headers").then(res => res.json()),
+ // A cross-origin request that behaves as if it was sent by the content it
+ // self.
+ content_fetch("http://127.0.0.1/return_headers").then(res => res.json()),
+ // A same-origin request that behaves as if it was sent by the content it
+ // self.
+ content_fetch("http://127.0.0.2/return_headers").then(res => res.json()),
+ // A same-origin request from the content script.
+ fetch("http://127.0.0.2/return_headers").then(res => res.json()),
+ // Non GET or HEAD request, triggers CORS preflight.
+ fetch("http://127.0.0.2/return_headers", { method: "PUT" }).then(res =>
+ res.json()
+ ),
+ ]);
+
+ results = results.map(({ value, reason }) => value ?? reason.message);
+
+ browser.test.sendMessage("content_results", results);
+}
+
+async function runSecFetchTest(test) {
+ let data = {
+ async background() {
+ let site = await new Promise(resolve => {
+ browser.test.onMessage.addListener(msg => {
+ resolve(msg);
+ });
+ });
+
+ let results = await Promise.all([
+ fetch(`${site}/return_headers`).then(res => res.json()),
+ // Non GET or HEAD request, triggers CORS preflight.
+ fetch(`${site}/return_headers`, { method: "PUT" }).then(res =>
+ res.json()
+ ),
+ ]);
+ browser.test.sendMessage("background_results", results);
+ },
+ manifest: {
+ manifest_version: test.manifest_version,
+ content_scripts: [
+ {
+ matches: ["http://127.0.0.2/*"],
+ js: ["content_script.js"],
+ },
+ ],
+ },
+ files: {
+ "content_script.js": contentScript,
+ },
+ };
+
+ if (data.manifest.manifest_version == 3) {
+ // Automatically grant permissions so that the content script can run.
+ data.manifest.granted_host_permissions = true;
+ // Needed to use granted_host_permissions in tests:
+ data.temporarilyInstalled = true;
+ // Work-around for bug 1766752:
+ data.manifest.host_permissions = ["http://127.0.0.2/*"];
+ // (note: ^ host_permissions may be replaced/extended below).
+ }
+
+ // The sec-fetch-* headers are only send to potentially trust worthy origins.
+ // We use 127.0.0.1 to avoid setting up an https server.
+ const site = "http://127.0.0.1";
+
+ if (test.permission) {
+ // MV3 requires permissions to be set in permissions. ExtensionTestCommon
+ // will replace host_permissions with permissions in MV2.
+ data.manifest.host_permissions = ["http://127.0.0.2/*", `${site}/*`];
+ }
+
+ let extension = ExtensionTestUtils.loadExtension(data);
+ await extension.startup();
+
+ extension.sendMessage(site);
+ let backgroundResults = await extension.awaitMessage("background_results");
+ Assert.deepEqual(backgroundResults, test.expectedBackgroundHeaders);
+
+ let contentPage = await ExtensionTestUtils.loadContentPage(
+ `http://127.0.0.2/page.html`
+ );
+ let contentResults = await extension.awaitMessage("content_results");
+ Assert.deepEqual(contentResults, test.expectedContentHeaders);
+ await contentPage.close();
+
+ await extension.unload();
+}
+
+add_task(async function test_fetch_without_permissions_mv2() {
+ await runSecFetchTest({
+ manifest_version: 2,
+ permission: false,
+ expectedBackgroundHeaders: [
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "moz-extension://<placeholder>",
+ },
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "moz-extension://<placeholder>",
+ },
+ ],
+ expectedContentHeaders: [
+ // TODO bug 1605197: Support cors without permissions in MV2.
+ "NetworkError when attempting to fetch resource.",
+ // Expectation:
+ // {
+ // "sec-fetch-site": "cross-site",
+ // "sec-fetch-mode": "cors",
+ // "sec-fetch-dest": "empty",
+ // },
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "http://127.0.0.2",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ ],
+ });
+});
+
+add_task(async function test_fetch_with_permissions_mv2() {
+ await runSecFetchTest({
+ manifest_version: 2,
+ permission: true,
+ expectedBackgroundHeaders: [
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "moz-extension://<placeholder>",
+ },
+ ],
+ expectedContentHeaders: [
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "http://127.0.0.2",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ ],
+ });
+});
+
+add_task(async function test_fetch_without_permissions_mv3() {
+ await runSecFetchTest({
+ manifest_version: 3,
+ permission: false,
+ expectedBackgroundHeaders: [
+ // Same as in test_fetch_without_permissions_mv2.
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "moz-extension://<placeholder>",
+ },
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "moz-extension://<placeholder>",
+ },
+ ],
+ expectedContentHeaders: [
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "http://127.0.0.2",
+ },
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "http://127.0.0.2",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "http://127.0.0.2",
+ },
+ ],
+ });
+});
+
+add_task(async function test_fetch_with_permissions_mv3() {
+ await runSecFetchTest({
+ manifest_version: 3,
+ permission: true,
+ expectedBackgroundHeaders: [
+ {
+ // Same as in test_fetch_with_permissions_mv2.
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "moz-extension://<placeholder>",
+ },
+ ],
+ expectedContentHeaders: [
+ // All expectations the same as in test_fetch_without_permissions_mv3.
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "http://127.0.0.2",
+ },
+ {
+ "sec-fetch-site": "cross-site",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "http://127.0.0.2",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ },
+ {
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-dest": "empty",
+ origin: "http://127.0.0.2",
+ },
+ ],
+ });
+});