summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_cached.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_webRequest_cached.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_webRequest_cached.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_webRequest_cached.js311
1 files changed, 311 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_cached.js b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_cached.js
new file mode 100644
index 0000000000..c18c75a580
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_cached.js
@@ -0,0 +1,311 @@
+"use strict";
+
+const BASE_URL = "http://example.com";
+const FETCH_ORIGIN = "http://example.com/data/file_sample.html";
+
+const server = createHttpServer({ hosts: ["example.com"] });
+server.registerDirectory("/data/", do_get_file("data"));
+server.registerPathHandler("/status", (request, response) => {
+ let IfNoneMatch = request.hasHeader("If-None-Match")
+ ? request.getHeader("If-None-Match")
+ : "";
+
+ switch (IfNoneMatch) {
+ case "1234567890":
+ response.setStatusLine("1.1", 304, "Not Modified");
+ response.setHeader("Content-Type", "text/html", false);
+ response.setHeader("Etag", "1234567890", false);
+ break;
+ case "":
+ response.setStatusLine("1.1", 200, "OK");
+ response.setHeader("Content-Type", "text/html", false);
+ response.setHeader("Etag", "1234567890", false);
+ response.write("ok");
+ break;
+ default:
+ throw new Error(`Unexpected If-None-Match: ${IfNoneMatch}`);
+ }
+});
+
+// This test initialises a cache entry with a CSP header, then
+// loads the cached entry and replaces the CSP header with
+// a new one. We test in onResponseStarted that the header
+// is what we expect.
+add_task(async function test_replaceResponseHeaders() {
+ Services.prefs.setBoolPref("network.http.rcwn.enabled", false);
+
+ let extension = ExtensionTestUtils.loadExtension({
+ background() {
+ function replaceHeader(headers, newHeader) {
+ headers = headers.filter(header => header.name !== newHeader.name);
+ headers.push(newHeader);
+ return headers;
+ }
+ let testHeaders = [
+ {
+ name: "Content-Security-Policy",
+ value: "object-src 'none'; script-src 'none'",
+ },
+ {
+ name: "Content-Security-Policy",
+ value: "object-src 'none'; script-src https:",
+ },
+ ];
+ browser.webRequest.onHeadersReceived.addListener(
+ details => {
+ if (!details.fromCache) {
+ // Add a CSP header on the initial request
+ details.responseHeaders.push(testHeaders[0]);
+ return {
+ responseHeaders: details.responseHeaders,
+ };
+ }
+ // Test that the header added during the initial request is
+ // now in the cached response.
+ let header = details.responseHeaders.filter(header => {
+ browser.test.log(`header ${header.name} = ${header.value}`);
+ return header.name == "Content-Security-Policy";
+ });
+ browser.test.assertEq(
+ header[0].value,
+ testHeaders[0].value,
+ "pre-cached header exists"
+ );
+ // Replace the cached value so we can test overriding the header that was cached.
+ return {
+ responseHeaders: replaceHeader(
+ details.responseHeaders,
+ testHeaders[1]
+ ),
+ };
+ },
+ {
+ urls: ["http://example.com/*/file_sample.html?r=*"],
+ },
+ ["blocking", "responseHeaders"]
+ );
+ browser.webRequest.onResponseStarted.addListener(
+ details => {
+ let needle = details.fromCache ? testHeaders[1] : testHeaders[0];
+ let header = details.responseHeaders.filter(header => {
+ browser.test.log(`header ${header.name} = ${header.value}`);
+ return header.name == needle.name && header.value == needle.value;
+ });
+ browser.test.assertEq(
+ header.length,
+ 1,
+ "header exists with correct value"
+ );
+ if (details.fromCache) {
+ browser.test.sendMessage("from-cache");
+ }
+ },
+ {
+ urls: ["http://example.com/*/file_sample.html?r=*"],
+ },
+ ["responseHeaders"]
+ );
+ },
+
+ manifest: {
+ permissions: ["webRequest", "webRequestBlocking", "http://example.com/"],
+ },
+ });
+
+ await extension.startup();
+
+ let url = `${BASE_URL}/data/file_sample.html?r=${Math.random()}`;
+ await ExtensionTestUtils.fetch(FETCH_ORIGIN, url);
+ await ExtensionTestUtils.fetch(FETCH_ORIGIN, url);
+ await extension.awaitMessage("from-cache");
+
+ await extension.unload();
+});
+
+// This test initialises a cache entry with a CSP header, then
+// loads the cached entry and adds a second CSP header. We also
+// test that the browser has the CSP entries we expect.
+add_task(async function test_addCSPHeaders() {
+ Services.prefs.setBoolPref("network.http.rcwn.enabled", false);
+
+ let extension = ExtensionTestUtils.loadExtension({
+ background() {
+ let testHeaders = [
+ {
+ name: "Content-Security-Policy",
+ value: "object-src 'none'; script-src 'none'",
+ },
+ {
+ name: "Content-Security-Policy",
+ value: "object-src 'none'; script-src https:",
+ },
+ ];
+ browser.webRequest.onHeadersReceived.addListener(
+ details => {
+ if (!details.fromCache) {
+ details.responseHeaders.push(testHeaders[0]);
+ return {
+ responseHeaders: details.responseHeaders,
+ };
+ }
+ browser.test.log("cached request received");
+ details.responseHeaders.push(testHeaders[1]);
+ return {
+ responseHeaders: details.responseHeaders,
+ };
+ },
+ {
+ urls: ["http://example.com/*/file_sample.html?r=*"],
+ },
+ ["blocking", "responseHeaders"]
+ );
+ browser.webRequest.onCompleted.addListener(
+ details => {
+ let { name, value } = testHeaders[0];
+ if (details.fromCache) {
+ value = `${value}, ${testHeaders[1].value}`;
+ }
+ let header = details.responseHeaders.filter(header => {
+ browser.test.log(`header ${header.name} = ${header.value}`);
+ return header.name == name && header.value == value;
+ });
+ browser.test.assertEq(
+ header.length,
+ 1,
+ "header exists with correct value"
+ );
+ if (details.fromCache) {
+ browser.test.sendMessage("from-cache");
+ }
+ },
+ {
+ urls: ["http://example.com/*/file_sample.html?r=*"],
+ },
+ ["responseHeaders"]
+ );
+ },
+
+ manifest: {
+ permissions: ["webRequest", "webRequestBlocking", "http://example.com/"],
+ },
+ });
+
+ await extension.startup();
+
+ let url = `${BASE_URL}/data/file_sample.html?r=${Math.random()}`;
+ let contentPage = await ExtensionTestUtils.loadContentPage(url);
+ equal(contentPage.browser.csp.policyCount, 1, "expected 1 policy");
+ equal(
+ contentPage.browser.csp.getPolicy(0),
+ "object-src 'none'; script-src 'none'",
+ "expected policy"
+ );
+ await contentPage.close();
+
+ contentPage = await ExtensionTestUtils.loadContentPage(url);
+ equal(contentPage.browser.csp.policyCount, 2, "expected 2 policies");
+ equal(
+ contentPage.browser.csp.getPolicy(0),
+ "object-src 'none'; script-src 'none'",
+ "expected first policy"
+ );
+ equal(
+ contentPage.browser.csp.getPolicy(1),
+ "object-src 'none'; script-src https:",
+ "expected second policy"
+ );
+
+ await extension.awaitMessage("from-cache");
+ await contentPage.close();
+
+ await extension.unload();
+});
+
+// This test verifies that a content type changed during
+// onHeadersReceived is cached. We initialize the cache,
+// then load against a url that will specifically return
+// a 304 status code.
+add_task(async function test_addContentTypeHeaders() {
+ Services.prefs.setBoolPref("network.http.rcwn.enabled", false);
+
+ let extension = ExtensionTestUtils.loadExtension({
+ background() {
+ browser.webRequest.onBeforeSendHeaders.addListener(
+ details => {
+ browser.test.log(`onBeforeSendHeaders ${JSON.stringify(details)}\n`);
+ },
+ {
+ urls: ["http://example.com/status*"],
+ },
+ ["blocking", "requestHeaders"]
+ );
+ browser.webRequest.onHeadersReceived.addListener(
+ details => {
+ browser.test.log(`onHeadersReceived ${JSON.stringify(details)}\n`);
+ if (!details.fromCache) {
+ browser.test.sendMessage("statusCode", details.statusCode);
+ const mime = details.responseHeaders.find(header => {
+ return header.value && header.name === "content-type";
+ });
+ if (mime) {
+ mime.value = "text/plain";
+ } else {
+ details.responseHeaders.push({
+ name: "content-type",
+ value: "text/plain",
+ });
+ }
+ return {
+ responseHeaders: details.responseHeaders,
+ };
+ }
+ },
+ {
+ urls: ["http://example.com/status*"],
+ },
+ ["blocking", "responseHeaders"]
+ );
+ browser.webRequest.onCompleted.addListener(
+ details => {
+ browser.test.log(`onCompleted ${JSON.stringify(details)}\n`);
+ const mime = details.responseHeaders.find(header => {
+ return header.value && header.name === "content-type";
+ });
+ browser.test.sendMessage("contentType", mime.value);
+ },
+ {
+ urls: ["http://example.com/status*"],
+ },
+ ["responseHeaders"]
+ );
+ },
+
+ manifest: {
+ permissions: ["webRequest", "webRequestBlocking", "http://example.com/"],
+ },
+ });
+
+ await extension.startup();
+
+ let contentPage = await ExtensionTestUtils.loadContentPage(
+ `${BASE_URL}/status`
+ );
+ equal(await extension.awaitMessage("statusCode"), "200", "status OK");
+ equal(
+ await extension.awaitMessage("contentType"),
+ "text/plain",
+ "plain text header"
+ );
+ await contentPage.close();
+
+ contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/status`);
+ equal(await extension.awaitMessage("statusCode"), "304", "not modified");
+ equal(
+ await extension.awaitMessage("contentType"),
+ "text/plain",
+ "plain text header"
+ );
+ await contentPage.close();
+
+ await extension.unload();
+});