aboutsummaryrefslogtreecommitdiff
path: root/content
diff options
context:
space:
mode:
authorWojtek Kosior <wk@koszkonutek-tmp.pl.eu.org>2021-05-10 18:07:05 +0200
committerWojtek Kosior <wk@koszkonutek-tmp.pl.eu.org>2021-05-10 18:18:52 +0200
commit01937dc9d5215ef96ce756e3ccda51bf29032f58 (patch)
tree609ec5bb48c692796520f7982c06b30633038588 /content
downloadbrowser-extension-01937dc9d5215ef96ce756e3ccda51bf29032f58.tar.gz
browser-extension-01937dc9d5215ef96ce756e3ccda51bf29032f58.zip
initial commit
Diffstat (limited to 'content')
-rw-r--r--content/main.js95
-rw-r--r--content/page_actions.mjs58
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});
+}