Revision d09b7ee1
Added by koszko about 2 years ago
| content/main.js | ||
|---|---|---|
| 11 | 11 |
* IMPORT handle_page_actions |
| 12 | 12 |
* IMPORT extract_signed |
| 13 | 13 |
* IMPORT gen_nonce |
| 14 |
* IMPORT csp_rule |
|
| 15 | 14 |
* IMPORT is_privileged_url |
| 16 |
* IMPORT sanitize_attributes |
|
| 17 | 15 |
* IMPORT mozilla_suppress_scripts |
| 18 | 16 |
* IMPORT is_chrome |
| 19 | 17 |
* IMPORT is_mozilla |
| 20 | 18 |
* IMPORT start_activity_info_server |
| 19 |
* IMPORT modify_on_the_fly |
|
| 21 | 20 |
* IMPORTS_END |
| 22 | 21 |
*/ |
| 23 | 22 |
|
| 24 |
/* |
|
| 25 |
* Due to some technical limitations the chosen method of whitelisting sites |
|
| 26 |
* is to smuggle whitelist indicator in page's url as a "magical" string |
|
| 27 |
* after '#'. Right now this is only supplemental in HTTP(s) pages where |
|
| 28 |
* blocking of native scripts also happens through CSP header injection but is |
|
| 29 |
* necessary for protocols like ftp:// and file://. |
|
| 30 |
* |
|
| 31 |
* The code that actually injects the magical string into ftp:// and file:// |
|
| 32 |
* urls has not yet been added to the extension. |
|
| 33 |
*/ |
|
| 34 |
|
|
| 35 |
var nonce = undefined; |
|
| 36 |
|
|
| 37 |
function handle_mutation(mutations, observer) |
|
| 38 |
{
|
|
| 39 |
if (document.readyState === 'complete') {
|
|
| 40 |
console.log("mutation handling complete");
|
|
| 41 |
observer.disconnect(); |
|
| 42 |
return; |
|
| 43 |
} |
|
| 44 |
for (const mutation of mutations) {
|
|
| 45 |
for (const node of mutation.addedNodes) |
|
| 46 |
block_node(node); |
|
| 47 |
} |
|
| 48 |
} |
|
| 49 |
|
|
| 50 |
function block_nodes_recursively(node) |
|
| 51 |
{
|
|
| 52 |
block_node(node); |
|
| 53 |
for (const child of node.children) |
|
| 54 |
block_nodes_recursively(child); |
|
| 55 |
} |
|
| 56 |
|
|
| 57 |
function block_node(node) |
|
| 23 |
function accept_node(node, parent) |
|
| 58 | 24 |
{
|
| 25 |
const clone = document.importNode(node, false); |
|
| 26 |
node.hachette_corresponding = clone; |
|
| 59 | 27 |
/* |
| 60 |
* Modifying <script> element doesn't always prevent its execution in some
|
|
| 61 |
* Mozilla browsers. This is Chromium-specific code.
|
|
| 28 |
* TODO: Stop page's own issues like "Error parsing a meta element's
|
|
| 29 |
* content:" from appearing as extension's errors.
|
|
| 62 | 30 |
*/ |
| 63 |
if (node.tagName === "SCRIPT") {
|
|
| 64 |
block_script(node); |
|
| 65 |
return; |
|
| 66 |
} |
|
| 67 |
|
|
| 68 |
sanitize_attributes(node); |
|
| 69 |
|
|
| 70 |
if (node.tagName === "HEAD") |
|
| 71 |
inject_csp(node); |
|
| 72 |
} |
|
| 73 |
|
|
| 74 |
function block_script(node) |
|
| 75 |
{
|
|
| 76 |
/* |
|
| 77 |
* Disabling scripts this way allows them to still be relatively |
|
| 78 |
* easily accessed in case they contain some useful data. |
|
| 79 |
*/ |
|
| 80 |
if (node.hasAttribute("type"))
|
|
| 81 |
node.setAttribute("blocked-type", node.getAttribute("type"));
|
|
| 82 |
node.setAttribute("type", "application/json");
|
|
| 83 |
} |
|
| 84 |
|
|
| 85 |
function inject_csp(head) |
|
| 86 |
{
|
|
| 87 |
let meta = document.createElement("meta");
|
|
| 88 |
meta.setAttribute("http-equiv", "Content-Security-Policy");
|
|
| 89 |
meta.setAttribute("content", csp_rule(nonce));
|
|
| 90 |
|
|
| 91 |
if (head.firstElementChild === null) |
|
| 92 |
head.appendChild(meta); |
|
| 93 |
else |
|
| 94 |
head.insertBefore(meta, head.firstElementChild); |
|
| 31 |
parent.hachette_corresponding.appendChild(clone); |
|
| 95 | 32 |
} |
| 96 | 33 |
|
| 97 | 34 |
if (!is_privileged_url(document.URL)) {
|
| ... | ... | |
| 110 | 47 |
|
| 111 | 48 |
handle_page_actions(policy.nonce); |
| 112 | 49 |
|
| 113 |
if (!policy.allow) {
|
|
| 114 |
block_nodes_recursively(document.documentElement);
|
|
| 50 |
if (!policy.allow && is_mozilla)
|
|
| 51 |
addEventListener('beforescriptexecute', mozilla_suppress_scripts, true);
|
|
| 115 | 52 |
|
| 116 |
if (is_chrome) {
|
|
| 117 |
var observer = new MutationObserver(handle_mutation); |
|
| 118 |
observer.observe(document.documentElement, {
|
|
| 119 |
attributes: true, |
|
| 120 |
childList: true, |
|
| 121 |
subtree: true |
|
| 122 |
}); |
|
| 123 |
} |
|
| 53 |
if (!policy.allow && is_chrome) {
|
|
| 54 |
const old_html = document.documentElement; |
|
| 55 |
const new_html = document.createElement("html");
|
|
| 56 |
old_html.replaceWith(new_html); |
|
| 57 |
old_html.hachette_corresponding = new_html; |
|
| 124 | 58 |
|
| 125 |
if (is_mozilla) |
|
| 126 |
addEventListener('beforescriptexecute', mozilla_suppress_scripts, true);
|
|
| 59 |
const modify_end = |
|
| 60 |
modify_on_the_fly(old_html, policy, {node_eater: accept_node});
|
|
| 61 |
document.addEventListener("DOMContentLoaded", modify_end);
|
|
| 127 | 62 |
} |
| 128 | 63 |
|
| 129 | 64 |
start_activity_info_server(); |
Also available in: Unified diff
sanitize `' tags containing CSP rules under Chromium
This commit adds a mechanism of hijacking document when it loads and injecting sanitized nodes to the DOM from the level of content script.