diff options
Diffstat (limited to 'content')
-rw-r--r-- | content/main.js | 95 | ||||
-rw-r--r-- | content/page_actions.mjs | 58 |
2 files changed, 153 insertions, 0 deletions
diff --git a/content/main.js b/content/main.js new file mode 100644 index 0000000..12a94c9 --- /dev/null +++ b/content/main.js @@ -0,0 +1,95 @@ +/** +* Myext main content script run in all frames +* +* Copyright (C) 2021 Wojtek Kosior +* +* Dual-licensed under: +* - 0BSD license +* - GPLv3 or (at your option) any later version +*/ + +var url_re = /^([^#]*)((#[^#]*)(#.*)?)?$/; +var match = url_re.exec(document.URL); +var base_url = match[1]; +var first_target = match[3]; +var second_target = match[4]; + +var block = true; +if (first_target !== undefined && + first_target === "#myext-allow") { + block = false; + console.log(["allowing", document.URL]); + if (second_target !== undefined) + window.location.href = base_url + second_target; + else + history.replaceState(null, "", base_url); +} else { + console.log(["not allowing", document.URL]); +} + +function handle_mutation(mutations, observer) +{ + if (document.readyState === 'complete') { + console.log("complete"); + observer.disconnect(); + return; + } + for (let mutation of mutations) { + for (let node of mutation.addedNodes) { + if (node.tagName === "SCRIPT") + block_script(node); + else + sanitize_attributes(node); + } + } +} + +function block_script(node) +{ + console.log(node); + + /* + * Disabling scripts this way allows them to still be relatively accessed + * in case they contain some useful data. + */ + if (node.hasAttribute("type")) + node.setAttribute("blocked-type", node.getAttribute("type")); + node.setAttribute("type", "application/json"); +} + +function sanitize_attributes(node) +{ + if (node.attributes === undefined) + return; + + /* We have to do it in 2 loops, removing attribute modifies our iterator */ + let attr_names = []; + for (let attr of node.attributes) { + let attr_name = attr.localName; + if (attr_name.startsWith("on")) + attr_names.push(attr_name); + } + + for (let attr_name of attr_names) { + node.removeAttribute(attr_name); + console.log("sanitized", attr_name); + } +} + +async function run_module() +{ + let src = chrome.runtime.getURL("content/page_actions.mjs"); + let module = await import(src); + module.default(); +} + +if (block) { + var observer = new MutationObserver(handle_mutation); + observer.observe(document.documentElement, { + attributes: true, + childList: true, + subtree: true + }); +} + +run_module(); diff --git a/content/page_actions.mjs b/content/page_actions.mjs new file mode 100644 index 0000000..3ce5b73 --- /dev/null +++ b/content/page_actions.mjs @@ -0,0 +1,58 @@ +/** +* Myext handling of page actions in content scripts +* +* Copyright (C) 2021 Wojtek Kosior +* +* Dual-licensed under: +* - 0BSD license +* - GPLv3 or (at your option) any later version +*/ + +import CONNECTION_TYPE from '/common/connection_types.mjs'; +import make_once from '/common/once.mjs'; +import browser from '/common/browser.mjs'; + +var port; +var loaded = false; +var scripts_awaiting = []; + +function handle_message(message) +{ + console.log(["message", message]); + + if (message.inject === undefined) + return; + + for (let script_text of message.inject) { + if (loaded) + add_script(script_text); + else + scripts_awaiting.push(script_text); + } +} + +function document_loaded(event) +{ + console.log("loaded"); + + loaded = true; + + for (let script_text of scripts_awaiting) + add_script(script_text); + + scripts_awaiting = undefined; +} + +function add_script(script_text) +{ + let script = document.createElement("script"); + script.textContent = script_text; + document.body.appendChild(script); +} + +export default function main() { + document.addEventListener("DOMContentLoaded", document_loaded); + port = browser.runtime.connect({name : CONNECTION_TYPE.PAGE_ACTIONS}); + port.onMessage.addListener(handle_message); + port.postMessage({url: document.URL}); +} |