summaryrefslogtreecommitdiff
path: root/src/content
diff options
context:
space:
mode:
authorhackademix2018-09-03 19:20:39 +0200
committerhackademix2018-09-04 00:22:39 +0200
commit81ac052e1d1b0db924c9ef14a90bf22ce1dc4d8b (patch)
tree8e3f904e4cec2c0c8f6132dc0760994baae9fa65 /src/content
parent16cdbbe1cb7402ed795923128a4bc7bfb4415f1e (diff)
downloadnoscript-81ac052e1d1b0db924c9ef14a90bf22ce1dc4d8b.tar.gz
noscript-81ac052e1d1b0db924c9ef14a90bf22ce1dc4d8b.tar.xz
noscript-81ac052e1d1b0db924c9ef14a90bf22ce1dc4d8b.zip
Better file: protocol support.
Diffstat (limited to 'src/content')
-rw-r--r--src/content/PlaceHolder.js25
-rw-r--r--src/content/content.js22
-rw-r--r--src/content/embeddingDocument.js23
-rw-r--r--src/content/onScriptDisabled.js16
4 files changed, 66 insertions, 20 deletions
diff --git a/src/content/PlaceHolder.js b/src/content/PlaceHolder.js
index f32c812..ac4dc14 100644
--- a/src/content/PlaceHolder.js
+++ b/src/content/PlaceHolder.js
@@ -1,6 +1,6 @@
var PlaceHolder = (() => {
const HANDLERS = new Map();
-
+
let checkStyle = async () => {
checkStyle = () => {};
if (!ns.embeddingDocument) return;
@@ -11,7 +11,7 @@ var PlaceHolder = (() => {
(await fetch(browser.extension.getURL("/content/content.css"))).text();
}
}
-
+
class Handler {
constructor(type, selector) {
this.type = type;
@@ -20,10 +20,16 @@ var PlaceHolder = (() => {
HANDLERS.set(type, this);
}
filter(element, request) {
- if (request.embeddingDocument) return true;
+ if (request.embeddingDocument) {
+ return document.URL === request.url;
+ }
let url = request.initialUrl || request.url;
return "data" in element ? element.data === url : element.src === url;
}
+ selectFor(request) {
+ return [...document.querySelectorAll(this.selector)]
+ .filter(element => this.filter(element, request))
+ }
}
new Handler("frame", "iframe");
@@ -59,6 +65,9 @@ var PlaceHolder = (() => {
static canReplace(policyType) {
return HANDLERS.has(policyType);
}
+ static handlerFor(policyType) {
+ return HANDLERS.get(policyType);
+ }
static listen() {
PlaceHolder.listen = () => {};
@@ -83,7 +92,7 @@ var PlaceHolder = (() => {
this.policyType = policyType;
this.request = request;
this.replacements = new Set();
- this.handler = HANDLERS.get(policyType);
+ this.handler = PlaceHolder.handlerFor(policyType);
if (this.handler) {
[...document.querySelectorAll(this.handler.selector)]
.filter(element => this.handler.filter(element, request))
@@ -100,7 +109,11 @@ var PlaceHolder = (() => {
let {
url
} = this.request;
- this.origin = new URL(url).origin;
+ let objUrl = new URL(url)
+ this.origin = objUrl.origin;
+ if (this.origin === "null") {
+ this.origin = objUrl.protocol;
+ }
let TYPE = `<${this.policyType.toUpperCase()}>`;
let replacement = createHTMLElement("a");
@@ -129,7 +142,7 @@ var PlaceHolder = (() => {
replacement._placeHolderObj = this;
replacement._placeHolderElement = element;
-
+
element.parentNode.replaceChild(replacement, element);
this.replacements.add(replacement);
diff --git a/src/content/content.js b/src/content/content.js
index e73feb6..fb68ae4 100644
--- a/src/content/content.js
+++ b/src/content/content.js
@@ -1,6 +1,5 @@
'use strict';
// debug = () => {}; // REL_ONLY
-
var _ = browser.i18n.getMessage;
function createHTMLElement(name) {
@@ -50,7 +49,7 @@ var notifyPage = async () => {
if (document.readyState === "complete") {
try {
if (!("canScript" in ns)) {
- let childPolicy = await Messages.send("fetchChildPolicy", {url: document.URL, contextUrl: top.location.href});
+ let childPolicy = await Messages.send("fetchChildPolicy", {url: document.URL});
ns.config.CURRENT = childPolicy.CURRENT;
ns.setup(childPolicy.DEFAULT, childPolicy.MARKER);
return;
@@ -82,11 +81,22 @@ ns.on("capabilities", () => {
},
allowed: ns.canScript
});
-
- if (!ns.canScript) {
+ if (!ns.canScript) {
+ addEventListener("beforescriptexecute", e => e.preventDefault());
+ let mo = new MutationObserver(mutations => {
+ for (let m of mutations) {
+ console.log(`Mutation `, m);
+ if (m.type !== "attribute") continue;
+ if (/^on\w+/i.test(m.attributeName)) {
+ m.target.removeAttribute(m.attributeName);
+ } else if (/^\s*(javascript|data):/i.test(m.target.attributes[m.attributeName])) {
+ m.target.setAttribute(m.attributeName, "#");
+ }
+ }
+ });
+ // mo.observe(document.documentElement, {attributes: true, subtree: true});
if ("serviceWorker" in navigator && navigator.serviceWorker.controller) {
- addEventListener("beforescriptexecute", e => e.preventDefault());
(async () => {
for (let r of await navigator.serviceWorker.getRegistrations()) {
await r.unregister();
@@ -97,6 +107,6 @@ ns.on("capabilities", () => {
if (document.readyState !== "loading") onScriptDisabled();
window.addEventListener("DOMContentLoaded", onScriptDisabled);
}
-
+
notifyPage();
});
diff --git a/src/content/embeddingDocument.js b/src/content/embeddingDocument.js
index 75b0db0..eed04b1 100644
--- a/src/content/embeddingDocument.js
+++ b/src/content/embeddingDocument.js
@@ -1,18 +1,25 @@
if (ns.embeddingDocument) {
ns.on("capabilities", () => {
for (let policyType of ["object", "media"]) {
- if (!ns.allows(policyType)) {
- let request = {
- id: `noscript-${policyType}-doc`,
- type: policyType,
- url: document.URL,
- documentUrl: document.URL,
- embeddingDocument: true,
- };
+ let request = {
+ id: `noscript-${policyType}-doc`,
+ type: policyType,
+ url: document.URL,
+ documentUrl: document.URL,
+ embeddingDocument: true,
+ };
+
+ if (ns.allows(policyType)) {
+ let handler = PlaceHolder.handlerFor(policyType);
+ if (handler && handler.selectFor(request).length > 0) {
+ seen.record({policyType, request, allowed: true});
+ }
+ } else {
let ph = PlaceHolder.create(policyType, request);
if (ph.replacements.size > 0) {
debug(`Created placeholder for ${policyType} at ${document.URL}`);
seen.record({policyType, request, allowed: false});
+ break;
}
}
}
diff --git a/src/content/onScriptDisabled.js b/src/content/onScriptDisabled.js
index 3606ede..79912c9 100644
--- a/src/content/onScriptDisabled.js
+++ b/src/content/onScriptDisabled.js
@@ -1,4 +1,20 @@
function onScriptDisabled() {
+ if (document.URL.startsWith("file:")) {
+ // file: documents are loaded synchronously and may not be affected by
+ // CSP. We already intercept onbeforeexecutescript event, let's cope with
+ // event and URL attributes.
+ for (let e of document.all) {
+ for (let a of e.attributes) {
+ if (/^on\w+/i.test(a.name)) {
+ debug(`Removed %s.%sevent`, e.tagName, a.name);
+ a.value = "";
+ } else if (/^\s*(?:data|javascript):/i.test(unescape(a.value))) {
+ debug(`Neutralized %s.%s="%s" attribute`, e.tagName, a.name, a.value);
+ a.value = "data:";
+ }
+ }
+ }
+ }
for (let noscript of document.querySelectorAll("noscript")) {
// force show NOSCRIPT elements content
let replacement = createHTMLElement("span");