Bug 1254194: [webext] Test that content security policies are applied to WebExtension documents. r?aswan
MozReview-Commit-ID: J9EPSdyrlsk
--- a/toolkit/components/extensions/test/mochitest/mochitest.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest.ini
@@ -25,16 +25,17 @@ support-files =
file_permission_xhr.html
file_download.txt
[test_ext_extension.html]
[test_ext_simple.html]
[test_ext_schema.html]
skip-if = e10s # Uses a console montitor. Actual code does not depend on e10s.
[test_ext_geturl.html]
+[test_ext_content_security_policy.html]
[test_ext_contentscript.html]
skip-if = buildapp == 'b2g' # runat != document_idle is not supported.
[test_ext_contentscript_create_iframe.html]
[test_ext_contentscript_api_injection.html]
[test_ext_downloads.html]
[test_ext_exclude_include_globs.html]
[test_ext_i18n_css.html]
[test_ext_generate.html]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_content_security_policy.html
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>WebExtension CSP test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+ <script type="text/javascript" src="head.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="text/javascript">
+"use strict";
+
+function* testPolicy(customCSP = null) {
+ let baseURL;
+
+ let baseCSP = {
+ "object-src": ["blob:", "filesystem:", "https://*", "moz-extension:", "'self'"],
+ "script-src": ["'unsafe-eval'", "blob:", "filesystem:", "https://*", "moz-extension:", "'self'"],
+ };
+
+ 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 filterSelf(sources) {
+ return sources.map(src => src == "'self'" ? baseURL : src);
+ }
+
+ function checkSource(name, policy, expected) {
+ is(JSON.stringify(policy[name].sort()),
+ JSON.stringify(filterSelf(expected[name]).sort()),
+ `Expected value for ${name}`);
+ }
+
+ function checkCSP(csp, location) {
+ let policies = csp["csp-policies"];
+
+ info(`Base policy for ${location}`);
+
+ checkSource("object-src", policies[0], baseCSP);
+ checkSource("script-src", policies[0], baseCSP);
+
+ info(`Add-on policy for ${location}`);
+
+ checkSource("object-src", policies[1], addonCSP);
+ checkSource("script-src", policies[1], addonCSP);
+ }
+
+
+ function getCSP(window) {
+ let {cspJSON} = SpecialPowers.Cu.getObjectPrincipal(window);
+ return JSON.parse(cspJSON);
+ }
+
+ function background(getCSP) {
+ browser.test.sendMessage("base-url", browser.extension.getURL("").replace(/\/$/, ""));
+
+ browser.test.sendMessage("background-csp", getCSP(window));
+ }
+
+ function tabScript(getCSP) {
+ browser.test.sendMessage("tab-csp", getCSP(window));
+ }
+
+ let extension = ExtensionTestUtils.loadExtension({
+ background: `(${background})(${getCSP})`,
+
+ files: {
+ "tab.html": `<html><head><meta charset="utf-8">
+ <script src="tab.js"></${"script"}></head></html>`,
+
+ "tab.js": `(${tabScript})(${getCSP})`,
+
+ "content.html": `<html><head><meta charset="utf-8"></head></html>`,
+ },
+
+ manifest: {
+ content_security_policy,
+
+ web_accessible_resources: ["content.html", "tab.html"],
+ },
+ });
+
+
+ info(`Testing CSP for policy: ${content_security_policy}`);
+
+ yield extension.startup();
+
+ baseURL = yield extension.awaitMessage("base-url");
+
+
+ let win1 = window.open(`${baseURL}/tab.html`);
+
+ let frame = document.createElement("iframe");
+ frame.src = `${baseURL}/content.html`;
+ document.body.appendChild(frame);
+
+ yield new Promise(resolve => {
+ frame.onload = resolve;
+ });
+
+
+ let backgroundCSP = yield extension.awaitMessage("background-csp");
+ checkCSP(backgroundCSP, "background page");
+
+ let tabCSP = yield extension.awaitMessage("tab-csp");
+ checkCSP(tabCSP, "tab page");
+
+ let contentCSP = getCSP(frame.contentWindow);
+ checkCSP(contentCSP, "content frame");
+
+
+ win1.close();
+ frame.remove();
+
+ yield extension.unload();
+}
+
+add_task(function* testCSP() {
+ yield testPolicy(null);
+
+ let hash = "'sha256-NjZhMDQ1YjQ1MjEwMmM1OWQ4NDBlYzA5N2Q1OWQ5NDY3ZTEzYTNmMzRmNjQ5NGU1MzlmZmQzMmMxYmIzNWYxOCAgLQo='";
+
+ yield testPolicy({
+ "object-src": "'self' https://*.example.com",
+ "script-src": `'self' https://*.example.com 'unsafe-eval' ${hash}`,
+ });
+
+ yield testPolicy({
+ "object-src": "'none'",
+ "script-src": `'self'`,
+ });
+});
+</script>
+</body>