diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /toolkit/components/extensions/test/xpcshell/test_ext_webRequest_cached.js | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.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.js | 311 |
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(); +}); |