aboutsummaryrefslogtreecommitdiff
path: root/content/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'content/main.js')
-rw-r--r--content/main.js57
1 files changed, 31 insertions, 26 deletions
diff --git a/content/main.js b/content/main.js
index fb334dd..a26f72d 100644
--- a/content/main.js
+++ b/content/main.js
@@ -16,9 +16,8 @@
* IMPORT is_chrome
* IMPORT is_mozilla
* IMPORT start_activity_info_server
- * IMPORT csp_rule
- * IMPORT is_csp_header_name
- * IMPORT sanitize_csp_header
+ * IMPORT make_csp_rule
+ * IMPORT csp_header_regex
* IMPORTS_END
*/
@@ -172,22 +171,20 @@ function block_attribute(node, attr, ns=null)
const name = construct_name.join("");
seta(node, `${blocked_str}-${name}`, geta(node, name));
}
-}
-
-function sanitize_meta(meta, policy)
-{
- const value = meta.content || "";
- if (!value || !is_csp_header_name(meta.httpEquiv || "", true))
- return;
-
- block_attribute(meta, "content");
+ rema(node, attr);
}
/*
- * Used to disable <script> that has not yet been added to live DOM (doesn't
- * work for those already added).
+ * Used to disable `<script>'s and `<meta>'s that have not yet been added to
+ * live DOM (doesn't work for those already added).
*/
+function sanitize_meta(meta)
+{
+ if (csp_header_regex.test(meta.httpEquiv) && meta.content)
+ block_attribute(meta, "content");
+}
+
function sanitize_script(script)
{
script.hachette_blocked_type = script.getAttribute("type");
@@ -195,14 +192,14 @@ function sanitize_script(script)
}
/*
- * Executed after script has been connected to the DOM, when it is no longer
- * eligible for being executed by the browser
+ * Executed after `<script>' has been connected to the DOM, when it is no longer
+ * eligible for being executed by the browser.
*/
-function desanitize_script(script, policy)
+function desanitize_script(script)
{
script.setAttribute("type", script.hachette_blocked_type);
- if (script.hachette_blocked_type === null)
+ if ([null, undefined].includes(script.hachette_blocked_type))
script.removeAttribute("type");
delete script.hachette_blocked_type;
@@ -233,13 +230,18 @@ function start_data_urls_sanitizing(doc)
* cause part of the DOM to be loaded when our content scripts get to run. Thus,
* before the CSP rules we inject (for non-HTTP pages) become effective, we need
* to somehow block the execution of `<script>'s and intrinsics that were
- * already there.
+ * already there. Additionally, some browsers (IceCat 60) seem to have problems
+ * applying this CSP to non-inline `<scripts>' in certain scenarios.
*/
+function prevent_script_execution(event)
+{
+ if (!event.target._hachette_payload)
+ event.preventDefault();
+}
+
function mozilla_initial_block(doc)
{
- const blocker = e => e.preventDefault();
- doc.addEventListener("beforescriptexecute", blocker);
- setTimeout(() => doc.removeEventListener("beforescriptexecute", blocker));
+ doc.addEventListener("beforescriptexecute", prevent_script_execution);
[...doc.all].flatMap(ele => [...ele.attributes].map(attr => [ele, attr]))
.map(([ele, attr]) => [ele, attr.localName])
@@ -273,7 +275,7 @@ async function sanitize_document(doc, policy)
* non-HTML documents.
*/
const html = new DOMParser().parseFromString(`<html><head><meta \
-http-equiv="Content-Security-Policy" content="${csp_rule(policy.nonce)}"\
+http-equiv="Content-Security-Policy" content="${make_csp_rule(policy)}"\
/></head><body>Loading...</body></html>`, "text/html").documentElement;
/*
@@ -284,10 +286,10 @@ http-equiv="Content-Security-Policy" content="${csp_rule(policy.nonce)}"\
root.replaceWith(html);
/*
- * For XML documents, we don't intend to inject payload, so we neither block
- * document's CSP `<meta>' tags nor wait for `<head>' to be parsed.
+ * When we don't inject payload, we neither block document's CSP `<meta>'
+ * tags nor wait for `<head>' to be parsed.
*/
- if (document instanceof HTMLDocument) {
+ if (policy.has_payload) {
await wait_for_head(doc, root);
root.querySelectorAll("head meta")
@@ -333,6 +335,9 @@ if (!is_privileged_url(document.URL)) {
policy = {allow: false, nonce: gen_nonce()};
}
+ if (!(document instanceof HTMLDocument))
+ policy.has_payload = false;
+
console.debug("current policy", policy);
const doc_ready = Promise.all([