summaryrefslogtreecommitdiff
path: root/src/content
diff options
context:
space:
mode:
Diffstat (limited to 'src/content')
-rw-r--r--src/content/content.js77
-rw-r--r--src/content/media.js103
-rw-r--r--src/content/webglHook.js10
3 files changed, 130 insertions, 60 deletions
diff --git a/src/content/content.js b/src/content/content.js
index 886c363..8f772b1 100644
--- a/src/content/content.js
+++ b/src/content/content.js
@@ -1,7 +1,81 @@
'use strict';
// debug = () => {}; // REL_ONLY
-
+{
+ let listenersMap = new Map();
+ let backlog = new Set();
+ var ns = {
+ on(eventName, listener) {
+ let listeners = listenersMap.get(eventName);
+ if (!listeners) listenersMap.set(eventName, listeners = new Set());
+ listeners.add(listener);
+ if (backlog.has(eventName)) this.fire(eventName, listener);
+ },
+ detach(eventName, listener) {
+ let listeners = listenersMap.get(eventName);
+ if (listeners) listeners.delete(listener);
+ },
+ fire(eventName, listener = null) {
+ if (listener) {
+ listener({type:eventName, source: this});
+ return;
+ }
+ let listeners = listenersMap.get(eventName);
+ if (listeners) {
+ for (let l of listeners) {
+ this.fire(eventName, l);
+ }
+ }
+ backlog.add(eventName);
+ },
+ setup(DEFAULT, MARKER) {
+ this.perms.DEFAULT = DEFAULT;
+ if(!this.perms.CURRENT) this.perms.CURRENT = DEFAULT;
+
+ // ugly hack: since now we use registerContentScript instead of the
+ // filterRequest dynamic script injection hack, we use top.name
+ // to store per-tab information. We don't want web content to
+ // mess with it, though, so we wrap it around auto-hiding accessors
+ this.perms.MARKER = MARKER;
+ let eraseTabInfoRx = new RegExp(`[^]*${MARKER},?`);
+ if (eraseTabInfoRx.test(top.name)) {
+ let _name = top.name;
+ let tabInfoRx = new RegExp(`^${MARKER}\\[([^]*?)\\]${MARKER},`);
+ if (top === window) { // wrap to hide
+ Reflect.defineProperty(top.wrappedJSObject, "name", {
+ get: exportFunction(() => top.name.replace(eraseTabInfoRx, ""), top.wrappedJSObject),
+ set: exportFunction(value => {
+ let preamble = top.name.match(tabInfoRx);
+ top.name = `${preamble && preamble[0] || ""}${value}`;
+ return value;
+ }, top.wrappedJSObject)
+ });
+ }
+ let tabInfoMatch = _name.match(tabInfoRx);
+ if (tabInfoMatch) try {
+ this.perms.tabInfo = JSON.parse(tabInfoMatch[1]);
+ } catch (e) {
+ error(e);
+ }
+ }
+
+ if (!this.perms.DEFAULT || this.perms.tabInfo.unrestricted) {
+ this.allows = () => true;
+ }
+ ns.fire("perms");
+ },
+ perms: { DEFAULT: null, CURRENT: null, tabInfo: {}, MARKER: "" },
+ allows(cap) {
+ let perms = this.perms.CURRENT;
+ return perms && perms.capabilities.includes(cap);
+ },
+ getWindowName() {
+ return top !== window || !this.perms.MARKER ? window.name
+ : window.name.split(this.perms.MARKER + ",").pop();
+ }
+ }
+}
+
var canScript = true, shouldScript = false;
let now = () => performance.now() + performance.timeOrigin;
@@ -24,7 +98,6 @@ function probe() {
var _ = browser.i18n.getMessage;
-
var embeddingDocument = false;
var seen = {
diff --git a/src/content/media.js b/src/content/media.js
index ffa67e0..910fd27 100644
--- a/src/content/media.js
+++ b/src/content/media.js
@@ -1,60 +1,57 @@
-{
- debug("Media Hook (blocked %s)", !!window.mediaBlocker, document.URL, document.documentElement && document.documentElement.innerHTML); // DEV_ONLY
- (() => {
- let unpatched = new Map();
- function patch(obj, methodName, replacement) {
- let methods = unpatched.get(obj) || {};
- methods[methodName] = obj[methodName];
- exportFunction(replacement, obj, {defineAs: methodName});
- unpatched.set(obj, methods);
+ns.on("perms", event => {
+ debug("Media Hook", document.URL, document.documentElement && document.documentElement.innerHTML, ns.perms.CURRENT); // DEV_ONLY
+ let mediaBlocker = !ns.allows("media");
+ let unpatched = new Map();
+ function patch(obj, methodName, replacement) {
+ let methods = unpatched.get(obj) || {};
+ methods[methodName] = obj[methodName];
+ exportFunction(replacement, obj, {defineAs: methodName});
+ unpatched.set(obj, methods);
+ }
+ let urlMap = new WeakMap();
+ patch(window.URL, "createObjectURL", function(o, ...args) {
+ let url = unpatched.get(window.URL).createObjectURL.call(this, o, ...args);
+ if (o instanceof MediaSource) {
+ let urls = urlMap.get(o);
+ if (!urls) urlMap.set(o, urls = new Set());
+ urls.add(url);
}
- let urlMap = new WeakMap();
- patch(window.URL, "createObjectURL", function(o, ...args) {
- let url = unpatched.get(window.URL).createObjectURL.call(this, o, ...args);
- if (o instanceof MediaSource) {
- let urls = urlMap.get(o);
- if (!urls) urlMap.set(o, urls = new Set());
- urls.add(url);
- }
- return url;
- });
+ return url;
+ });
- patch(window.MediaSource.prototype, "addSourceBuffer", function(mime, ...args) {
- let ms = this;
- let urls = urlMap.get(ms);
+ patch(window.MediaSource.prototype, "addSourceBuffer", function(mime, ...args) {
+ let ms = this;
+ let urls = urlMap.get(ms);
- let request = {
- id: "noscript-media",
- type: "media",
- url: document.URL,
- documentUrl: document.URL,
- embeddingDocument: true,
- };
- seen.record({policyType: "media", request, allowed: false});
- notifyPage();
+ let request = {
+ id: "noscript-media",
+ type: "media",
+ url: document.URL,
+ documentUrl: document.URL,
+ embeddingDocument: true,
+ };
+ seen.record({policyType: "media", request, allowed: false});
+ notifyPage();
- if (window.mediaBlocker) {
- (async () => {
- let me = Array.from(document.querySelectorAll("video,audio"))
- .find(e => e.srcObject === ms || urls && urls.has(e.src));
+ if (mediaBlocker) {
+ (async () => {
+ let me = Array.from(document.querySelectorAll("video,audio"))
+ .find(e => e.srcObject === ms || urls && urls.has(e.src));
- if (!me) return;
- let exposedMime = `${mime} (MSE)`;
+ if (!me) return;
+ let exposedMime = `${mime} (MSE)`;
- try {
- let ph = PlaceHolder.create("media", request);
- ph.replace(me);
- PlaceHolder.listen();
- } catch (e) {
- error(e);
- }
- })();
- throw new Error(`${exposedMime} blocked by NoScript`);
- }
-
- return unpatched.get(window.MediaSource.prototype).addSourceBuffer.call(ms, mime, ...args);
- });
+ try {
+ let ph = PlaceHolder.create("media", request);
+ ph.replace(me);
+ PlaceHolder.listen();
+ } catch (e) {
+ error(e);
+ }
+ })();
+ throw new Error(`${exposedMime} blocked by NoScript`);
+ }
- })();
- document.URL;
-}
+ return unpatched.get(window.MediaSource.prototype).addSourceBuffer.call(ms, mime, ...args);
+ });
+});
diff --git a/src/content/webglHook.js b/src/content/webglHook.js
index d4c064a..efafcd5 100644
--- a/src/content/webglHook.js
+++ b/src/content/webglHook.js
@@ -1,5 +1,6 @@
-{
- debug("WebGL Hook", document.URL, document.documentElement && document.documentElement.innerHTML); // DEV_ONLY
+ns.on("perms", event => {
+ debug("WebGL Hook", document.URL, document.documentElement && document.documentElement.innerHTML, ns.perms.CURRENT); // DEV_ONLY
+ if (ns.allows("webgl")) return;
let proto = HTMLCanvasElement.prototype;
let getContext = proto.getContext;
exportFunction(function(type, ...rest) {
@@ -23,6 +24,5 @@
return {};
}
return getContext.call(this, type, ...rest);
- }, proto, {defineAs: "getContext"});
- document.URL;
-}
+ }, proto, {defineAs: "getContext"});
+});