"use strict"; Services.prefs.setBoolPref("extensions.manifestV3.enabled", true); const server = createHttpServer({ hosts: ["example.com"] }); server.registerPathHandler("/dummy", (request, response) => { response.setStatusLine(request.httpVersion, 200, "OK"); response.setHeader("Content-Type", "text/html", false); response.write(""); }); server.registerPathHandler("/worker.js", (request, response) => { response.setStatusLine(request.httpVersion, 200, "OK"); response.setHeader("Content-Type", "application/javascript", false); response.write("let x = true;"); }); const baseCSP = []; baseCSP[2] = { "object-src": ["blob:", "filesystem:", "moz-extension:", "'self'"], "script-src": [ "'unsafe-eval'", "'unsafe-inline'", "blob:", "filesystem:", "http://localhost:*", "http://127.0.0.1:*", "https://*", "moz-extension:", "'self'", ], }; baseCSP[3] = { "object-src": ["'self'"], "script-src": ["http://localhost:*", "http://127.0.0.1:*", "'self'"], "worker-src": ["http://localhost:*", "http://127.0.0.1:*", "'self'"], }; /** * Tests that content security policies for an add-on are actually applied to * * documents that belong to it. This tests both the base policies and add-on * specific policies, and ensures that the parsed policies applied to the * document's principal match what was specified in the policy string. * * @param {number} [manifest_version] * @param {object} [customCSP] */ async function testPolicy(manifest_version = 2, customCSP = null) { let baseURL; let addonCSP = { "object-src": ["'self'"], "script-src": ["'self'"], }; let content_security_policy = null; if (customCSP) { for (let key of Object.keys(customCSP)) { addonCSP[key] = customCSP[key].split(/\s+/); } content_security_policy = Object.keys(customCSP) .map(key => `${key} ${customCSP[key]}`) .join("; "); } function checkSource(name, policy, expected) { // fallback to script-src when comparing worker-src if policy does not include worker-src let policySrc = name != "worker-src" || policy[name] ? policy[name] : policy["script-src"]; equal( JSON.stringify(policySrc.sort()), JSON.stringify(expected[name].sort()), `Expected value for ${name}` ); } function checkCSP(csp, location) { let policies = csp["csp-policies"]; info(`Base policy for ${location}`); let base = baseCSP[manifest_version]; equal(policies[0]["report-only"], false, "Policy is not report-only"); for (let key in base) { checkSource(key, policies[0], base); } info(`Add-on policy for ${location}`); equal(policies[1]["report-only"], false, "Policy is not report-only"); for (let key in addonCSP) { checkSource(key, policies[1], addonCSP); } } function background() { browser.test.sendMessage( "base-url", browser.extension.getURL("").replace(/\/$/, "") ); browser.test.sendMessage("background-csp", window.getCSP()); } function tabScript() { browser.test.sendMessage("tab-csp", window.getCSP()); const worker = new Worker("worker.js"); worker.onmessage = event => { browser.test.sendMessage("worker-csp", event.data); }; worker.postMessage({}); } function testWorker(port) { this.onmessage = () => { try { // eslint-disable-next-line no-undef importScripts(`http://127.0.0.1:${port}/worker.js`); postMessage({ loaded: true }); } catch (e) { postMessage({ loaded: false }); } }; } let extension = ExtensionTestUtils.loadExtension({ background, files: { "tab.html": `