1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
if ("MediaSource" in window) {
let notify = allowed => {
let request = {
id: "noscript-media",
type: "media",
url: document.URL,
documentUrl: document.URL,
embeddingDocument: true,
};
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 (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);
});
} else if ("SecurityPolicyViolationEvent" in window) {
// Chromium
let createPlaceholders = () => {
let request = notify(false);
for (let me of document.querySelectorAll("video,audio")) {
if (!(me.src || me.currentSrc) || me.src.startsWith("blob")) {
createPlaceholder(me, request);
}
}
}
let processedURIs = new Set();
let whenReady = false;
addEventListener("securitypolicyviolation", e => {
if (!e.isTrusted || ns.allows("media")) return;
let {blockedURI, violatedDirective} = e;
if (blockedURI.startsWith("blob") &&
violatedDirective.startsWith("media-src") &&
!processedURIs.has(blockedURI)) {
processedURIs.add(blockedURI);
setTimeout(createPlaceholders, 0);
}
}, true);
}
}
|