Recursive webgl context monkeypatching across same origin windows (concept/patch by skriptimaahinen).
This commit is contained in:
parent
fcd7c4aef0
commit
9e4c03060a
|
@ -1,28 +1,91 @@
|
|||
ns.on("capabilities", event => {
|
||||
debug("WebGL Hook", document.URL, document.documentElement && document.documentElement.innerHTML, ns.capabilities); // DEV_ONLY
|
||||
if (ns.allows("webgl")) return;
|
||||
let proto = HTMLCanvasElement.prototype;
|
||||
let getContext = proto.getContext;
|
||||
exportFunction(function(type, ...rest) {
|
||||
if (type && type.toLowerCase().includes("webgl")) {
|
||||
let request = {
|
||||
id: "noscript-webgl",
|
||||
type: "webgl",
|
||||
url: document.URL,
|
||||
documentUrl: document.URL,
|
||||
embeddingDocument: true,
|
||||
};
|
||||
seen.record({policyType: "webgl", request, allowed: false});
|
||||
try {
|
||||
let ph = PlaceHolder.create("webgl", request);
|
||||
ph.replace(this);
|
||||
PlaceHolder.listen();
|
||||
} catch (e) {
|
||||
error(e);
|
||||
}
|
||||
notifyPage();
|
||||
return {};
|
||||
|
||||
// win: window object to modify.
|
||||
// modifyTarget: callback to function that modifies the desired properties
|
||||
// or methods. Callback must take target window as argument.
|
||||
function modifyWindow(win, modifyTarget) {
|
||||
try {
|
||||
modifyTarget(win);
|
||||
modifyWindowOpenMethod(win, modifyTarget);
|
||||
modifyFramingElements(win, modifyTarget);
|
||||
} catch (e) {
|
||||
if (e instanceof DOMException && e.name === "SecurityError") {
|
||||
// In case someone tries to access SOP restricted window.
|
||||
// We can just ignore this.
|
||||
} else throw e;
|
||||
}
|
||||
return getContext.call(this, type, ...rest);
|
||||
}, proto, {defineAs: "getContext"});
|
||||
}
|
||||
|
||||
function modifyWindowOpenMethod(win, modifyTarget) {
|
||||
let windowOpen = win.wrappedJSObject ? win.wrappedJSObject.open : win.open;
|
||||
exportFunction(function(...args) {
|
||||
let newWin = windowOpen.call(this, ...args);
|
||||
if (newWin) modifyWindow(newWin, modifyTarget);
|
||||
return newWin;
|
||||
}, win, {defineAs: "open"});
|
||||
}
|
||||
|
||||
function modifyFramingElements(win, modifyTarget) {
|
||||
for (let property of ["contentWindow", "contentDocument"]) {
|
||||
for (let interface of ["Frame", "IFrame", "Object"]) {
|
||||
let proto = win[`HTML${interface}Element`].prototype;
|
||||
modifyContentProperties(proto, property, modifyTarget)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function modifyContentProperties(proto, property, modifyTarget) {
|
||||
let descriptor = Object.getOwnPropertyDescriptor(proto, property);
|
||||
let origGetter = descriptor.get;
|
||||
let replacementFn;
|
||||
|
||||
if (property === "contentWindow") { replacementFn = function() {
|
||||
let win = origGetter.call(this);
|
||||
if (win) modifyWindow(win, modifyTarget);
|
||||
return win;
|
||||
}}
|
||||
if (property === "contentDocument") { replacementFn = function() {
|
||||
let document = origGetter.call(this);
|
||||
if (document && document.defaultView) modifyWindow(document.defaultView, modifyTarget);
|
||||
return document;
|
||||
}}
|
||||
|
||||
descriptor.get = exportFunction(replacementFn, proto, {defineAs: `get $property`});
|
||||
let wrappedProto = proto.wrappedJSObject || proto;
|
||||
Object.defineProperty(wrappedProto, property, descriptor);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
function modifyGetContext(win) {
|
||||
let proto = win.HTMLCanvasElement.prototype;
|
||||
let getContext = proto.getContext;
|
||||
exportFunction(function(type, ...rest) {
|
||||
if (type && type.toLowerCase().includes("webgl")) {
|
||||
let request = {
|
||||
id: "noscript-webgl",
|
||||
type: "webgl",
|
||||
url: document.URL,
|
||||
documentUrl: document.URL,
|
||||
embeddingDocument: true,
|
||||
};
|
||||
seen.record({policyType: "webgl", request, allowed: false});
|
||||
try {
|
||||
let ph = PlaceHolder.create("webgl", request);
|
||||
ph.replace(this);
|
||||
PlaceHolder.listen();
|
||||
} catch (e) {
|
||||
error(e);
|
||||
}
|
||||
notifyPage();
|
||||
return {};
|
||||
}
|
||||
return getContext.call(this, type, ...rest);
|
||||
}, proto, {defineAs: "getContext"});
|
||||
}
|
||||
|
||||
modifyWindow(window, modifyGetContext);
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue