Index: inject.preload.js |
=================================================================== |
--- a/inject.preload.js |
+++ b/inject.preload.js |
@@ -67,53 +67,67 @@ |
"(" + injectedToString() + ")('" + eventName + "', true);" |
); |
delete contentWindow[eventName]; |
} |
catch (e) {} |
} |
} |
- for (let element of [HTMLFrameElement, HTMLIFrameElement, HTMLObjectElement]) |
+ function injectIntoAllFrames() |
+ { |
+ for (let i = 0; i < window.length; i++) |
+ injectIntoContentWindow(window[i]); |
+ } |
+ |
+ function wrapAPIForInjection(object, api, callback) |
{ |
- let contentDocumentDesc = Object.getOwnPropertyDescriptor( |
- element.prototype, "contentDocument" |
- ); |
- let contentWindowDesc = Object.getOwnPropertyDescriptor( |
- element.prototype, "contentWindow" |
- ); |
- |
- // Apparently in HTMLObjectElement.prototype.contentWindow does not exist |
- // in older versions of Chrome such as 42. |
- if (!contentWindowDesc) |
- continue; |
+ let func = object[api]; |
+ if (!func || typeof func != "function") |
+ return; |
+ let applyFunc = Function.prototype.apply.bind(func); |
+ Object.defineProperty(object, api, { |
+ value(...args) |
+ { |
+ let returnValue = applyFunc(this, args); |
+ callback(returnValue); |
+ return returnValue; |
+ } |
+ }); |
+ } |
- let getContentDocument = Function.prototype.call.bind( |
- contentDocumentDesc.get |
- ); |
- let getContentWindow = Function.prototype.call.bind( |
- contentWindowDesc.get |
- ); |
+ function wrapPropertyAPIForInjection(object, api, method, callback) |
+ { |
+ let descriptor = Object.getOwnPropertyDescriptor(object, api); |
+ // Apparently HTMLObjectElement.prototype.contentWindow does not exist in |
+ // older versions of Chrome such as 42. |
+ if (!descriptor) |
+ return; |
+ wrapAPIForInjection(descriptor, method, callback); |
+ Object.defineProperty(object, api, descriptor); |
+ } |
- contentWindowDesc.get = function() |
+ wrapAPIForInjection(Node.prototype, "appendChild", injectIntoAllFrames); |
+ wrapAPIForInjection(Node.prototype, "insertBefore", injectIntoAllFrames); |
+ wrapAPIForInjection(Node.prototype, "replaceChild", injectIntoAllFrames); |
+ |
+ wrapPropertyAPIForInjection(Element.prototype, |
+ "innerHTML", "set", injectIntoAllFrames); |
+ |
+ wrapPropertyAPIForInjection(HTMLObjectElement.prototype, |
+ "contentWindow", "get", injectIntoContentWindow); |
+ wrapPropertyAPIForInjection( |
+ HTMLObjectElement.prototype, |
+ "contentDocument", "get", |
+ contentDocument => |
{ |
- let contentWindow = getContentWindow(this); |
- injectIntoContentWindow(contentWindow); |
- return contentWindow; |
- }; |
- contentDocumentDesc.get = function() |
- { |
- injectIntoContentWindow(getContentWindow(this)); |
- return getContentDocument(this); |
- }; |
- Object.defineProperty(element.prototype, "contentWindow", |
- contentWindowDesc); |
- Object.defineProperty(element.prototype, "contentDocument", |
- contentDocumentDesc); |
- } |
+ if (contentDocument) |
+ injectIntoContentWindow(contentDocument.defaultView); |
+ } |
+ ); |
/* |
* Shadow root getter wrapper |
* |
* After creating our shadowRoot we must wrap the getter to prevent the |
* website from accessing it (#4191, #4298). This is required as a |
* workaround for the lack of user style support in Chrome. |
* See https://bugs.chromium.org/p/chromium/issues/detail?id=632009&desc=2 |