Skip to content

Commit 9639ea4

Browse files
committed
Webgl hook refactored on nscl/content/patchWindow.js and made Chromium-compatibile.
1 parent ab3eab6 commit 9639ea4

2 files changed

Lines changed: 29 additions & 79 deletions

File tree

src/content/webglHook.js

Lines changed: 24 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,41 @@
1-
if (typeof exportFunction === "function") ns.on("capabilities", event => {
1+
// depends on nscl/content/patchWindow.js
2+
"use strict";
3+
ns.on("capabilities", event => {
24
debug("WebGL Hook", document.URL, document.documentElement && document.documentElement.innerHTML, ns.capabilities); // DEV_ONLY
35
if (ns.allows("webgl")) return;
4-
5-
// win: window object to modify.
6-
// modifyTarget: callback to function that modifies the desired properties
7-
// or methods. Callback must take target window as argument.
8-
function modifyWindow(win, modifyTarget) {
6+
let env = {eventName: `nsWebgl:${uuid()}`};
7+
window.addEventListener(env.eventName, e => {
8+
let canvas = e.target;
9+
if (!(canvas instanceof HTMLCanvasElement)) return;
10+
let request = {
11+
id: "noscript-webgl",
12+
type: "webgl",
13+
url: document.URL,
14+
documentUrl: document.URL,
15+
embeddingDocument: true,
16+
};
17+
seen.record({policyType: "webgl", request, allowed: false});
918
try {
10-
modifyTarget(win);
11-
modifyWindowOpenMethod(win, modifyTarget);
12-
modifyFramingElements(win, modifyTarget);
19+
let ph = PlaceHolder.create("webgl", request);
20+
ph.replace(canvas);
21+
PlaceHolder.listen();
1322
} catch (e) {
14-
if (e instanceof DOMException && e.name === "SecurityError") {
15-
// In case someone tries to access SOP restricted window.
16-
// We can just ignore this.
17-
} else throw e;
23+
error(e);
1824
}
19-
}
20-
21-
function modifyWindowOpenMethod(win, modifyTarget) {
22-
let windowOpen = win.wrappedJSObject ? win.wrappedJSObject.open : win.open;
23-
exportFunction(function(...args) {
24-
let newWin = windowOpen.call(this, ...args);
25-
if (newWin) modifyWindow(newWin, modifyTarget);
26-
return newWin;
27-
}, win, {defineAs: "open"});
28-
}
29-
30-
function modifyFramingElements(win, modifyTarget) {
31-
for (let property of ["contentWindow", "contentDocument"]) {
32-
for (let interface of ["Frame", "IFrame", "Object"]) {
33-
let proto = win[`HTML${interface}Element`].prototype;
34-
modifyContentProperties(proto, property, modifyTarget)
35-
}
36-
}
37-
}
25+
notifyPage();
26+
}, true);
3827

39-
function modifyContentProperties(proto, property, modifyTarget) {
40-
let descriptor = Object.getOwnPropertyDescriptor(proto, property);
41-
let origGetter = descriptor.get;
42-
let replacementFn;
43-
44-
if (property === "contentWindow") { replacementFn = function() {
45-
let win = origGetter.call(this);
46-
if (win) modifyWindow(win, modifyTarget);
47-
return win;
48-
}}
49-
if (property === "contentDocument") { replacementFn = function() {
50-
let document = origGetter.call(this);
51-
if (document && document.defaultView) modifyWindow(document.defaultView, modifyTarget);
52-
return document;
53-
}}
54-
55-
descriptor.get = exportFunction(replacementFn, proto, {defineAs: `get $property`});
56-
let wrappedProto = proto.wrappedJSObject || proto;
57-
Object.defineProperty(wrappedProto, property, descriptor);
58-
}
59-
60-
//
61-
62-
function modifyGetContext(win) {
28+
function modifyGetContext(win, env) {
6329
let proto = win.HTMLCanvasElement.prototype;
6430
let getContext = proto.getContext;
6531
exportFunction(function(type, ...rest) {
6632
if (type && type.toLowerCase().includes("webgl")) {
67-
let request = {
68-
id: "noscript-webgl",
69-
type: "webgl",
70-
url: document.URL,
71-
documentUrl: document.URL,
72-
embeddingDocument: true,
73-
};
74-
seen.record({policyType: "webgl", request, allowed: false});
75-
try {
76-
let ph = PlaceHolder.create("webgl", request);
77-
ph.replace(this);
78-
PlaceHolder.listen();
79-
} catch (e) {
80-
error(e);
81-
}
82-
notifyPage();
33+
this.dispatchEvent(new Event(env.eventName));
8334
return null;
8435
}
8536
return getContext.call(this, type, ...rest);
8637
}, proto, {defineAs: "getContext"});
8738
}
8839

89-
modifyWindow(window, modifyGetContext);
90-
40+
patchWindow(modifyGetContext, env);
9141
});

src/nscl/content/patchWindow.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use strict";
22

3-
function patchWindow(patchingCallback, targetWindow = window) {
3+
function patchWindow(patchingCallback, env = {}) {
44
let nativeExport = this && this.exportFunction || typeof exportFunction == "function";
55
if (!nativeExport) {
66
// Chromium
@@ -26,7 +26,7 @@ function patchWindow(patchingCallback, targetWindow = window) {
2626
patchWindow,
2727
exportFunction,
2828
cloneInto,
29-
}).patchWindow(${patchingCallback});
29+
}).patchWindow(${patchingCallback}, ${JSON.stringify(env)});
3030
})();
3131
`;
3232
document.documentElement.insertBefore(script, document.documentElement.firstChild);
@@ -39,7 +39,7 @@ function patchWindow(patchingCallback, targetWindow = window) {
3939
// or methods. Callback must take target window as argument.
4040
function modifyWindow(win, modifyTarget) {
4141
try {
42-
modifyTarget(win.wrappedJSObject || win);
42+
modifyTarget(win.wrappedJSObject || win, env);
4343
modifyWindowOpenMethod(win, modifyTarget);
4444
modifyFramingElements(win, modifyTarget);
4545
} catch (e) {
@@ -88,6 +88,6 @@ function patchWindow(patchingCallback, targetWindow = window) {
8888
let wrappedProto = proto.wrappedJSObject || proto;
8989
Object.defineProperty(wrappedProto, property, descriptor);
9090
}
91-
92-
return modifyWindow(targetWindow, patchingCallback);
91+
92+
return modifyWindow(window, patchingCallback);
9393
}

0 commit comments

Comments
 (0)