| 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 |