From 118eb535aaa6c16270ff3cb90fb947e8fb61274a Mon Sep 17 00:00:00 2001 From: hackademix Date: Mon, 11 Nov 2019 10:29:36 +0100 Subject: Placeholders for MSE on Chromium too. --- src/content/media.js | 116 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/content/media.js b/src/content/media.js index 687b9c3..ae438f9 100644 --- a/src/content/media.js +++ b/src/content/media.js @@ -1,28 +1,5 @@ -if (typeof exportFunction === "function" && "MediaSource" in window) ns.on("capabilities", event => { - debug("Media Hook", document.URL, document.documentElement && document.documentElement.innerHTML, ns.capabilities); // 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); - } - return url; - }); - - patch(window.MediaSource.prototype, "addSourceBuffer", function(mime, ...args) { - let ms = this; - let urls = urlMap.get(ms); - +if ("MediaSource" in window) { + let notify = allowed => { let request = { id: "noscript-media", type: "media", @@ -30,26 +7,77 @@ if (typeof exportFunction === "function" && "MediaSource" in window) ns.on("capa documentUrl: document.URL, embeddingDocument: true, }; - seen.record({policyType: "media", request, allowed: false}); + seen.record({policyType: "media", request, allowed}); + debug("MSE notification", document.URL); // DEV_ONLY notifyPage(); + return request; + }; + let createPlaceholder = (mediaElement, request) => { + try { + let ph = PlaceHolder.create("media", request); + ph.replace(mediaElement); + PlaceHolder.listen(); + debug("MSE placeholder for %o", mediaElement); // DEV_ONLY + } catch (e) { + error(e); + } + }; - if (mediaBlocker) { - let exposedMime = `${mime} (MSE)`; - setTimeout(() => { - let me = Array.from(document.querySelectorAll("video,audio")) - .find(e => e.srcObject === ms || urls && urls.has(e.src)); - if (!me) return; - try { - let ph = PlaceHolder.create("media", request); - ph.replace(me); - PlaceHolder.listen(); - } catch (e) { - error(e); - } - }, 0); - throw new Error(`${exposedMime} blocked by NoScript`); + if (typeof exportFunction === "function") { + // Mozilla + let mediablocker = true; + ns.on("capabilities", e => { + 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); + } + return url; + }); + + patch(window.MediaSource.prototype, "addSourceBuffer", function(mime, ...args) { + let ms = this; + let urls = urlMap.get(ms); + let request = notify(!mediaBlocker); + if (mediaBlocker) { + let exposedMime = `${mime} (MSE)`; + setTimeout(() => { + let me = Array.from(document.querySelectorAll("video,audio")) + .find(e => e.srcObject === ms || urls && urls.has(e.src)); + if (me) createPlaceholder(me, request); + }, 0); + throw new Error(`${exposedMime} blocked by NoScript`); + } + + return unpatched.get(window.MediaSource.prototype).addSourceBuffer.call(ms, mime, ...args); + }); - return unpatched.get(window.MediaSource.prototype).addSourceBuffer.call(ms, mime, ...args); - }); -}); + } else if ("SecurityPolicyViolationEvent" in window) { + // Chromium + addEventListener("securitypolicyviolation", e => { + if (!e.isTrusted || ns.allows("media")) return; + let {blockedURI, violatedDirective} = e; + if (blockedURI.startsWith("blob") && violatedDirective.startsWith("media-src")) { + let request = notify(false); + for (let me of document.querySelectorAll("video,audio")) { + if (!(me.src || me.currentSrc) || me.src.startsWith("blob")) { + createPlaceholder(me, request); + } + } + } + }, true); + } +} -- cgit v1.2.3