如何从 Firefox 扩展覆盖 JavaScript 函数?

发布于 2024-09-03 11:55:24 字数 1481 浏览 5 评论 0原文

我试图拦截所有页面对 document.write 的调用。通过注入像这样的脚本在页面内设置拦截

function overrideDocWrite() {
 alert("Override called");
 document.write = function(w) {
  return function(s) {
   alert("special dom");
   w.call(this, wrapString(s));
  };
 }(document.write);
 alert("Override finished");
}

很简单并且有效,但我希望我的扩展能够从扩展内部为每个文档对象设置拦截。我找不到办法做到这一点。我尝试监听“load”事件并在那里设置拦截,但它也失败了。如何从扩展中挂钩对 doc.write 的调用?

我取得了一些进展:

var myExtension = {
  init: function() {
    var appcontent = document.getElementById("appcontent"); // browser
    if (appcontent)
      appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad,
        true);
  },

  onPageLoad: function(aEvent) {
    var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
    // do something with the loaded page.
    // doc.location is a Location object (see below for a link).
    // You can use it to make your code executed on certain pages only.
    alert("Override called");
    alert(doc);
    alert(doc.write);
    alert(doc.wrappedJSObject);
    alert(doc.wrappedJSObject.write);
    doc.wrappedJSObject.write = function(w) {
      return function(s) {
        alert("special dom");
        w.call(this, "(" + s + ")");
      };
    }(doc.write);
    alert("Override finished");
  }
}

这似乎有效,但 DOMContentLoaded 是该作业的错误事件,因为它被触发得太晚了!有更早的活动可以听吗?

I am trying to intercept calls to document.write for all pages. Setting up the interception inside the page by injecting a script like

function overrideDocWrite() {
 alert("Override called");
 document.write = function(w) {
  return function(s) {
   alert("special dom");
   w.call(this, wrapString(s));
  };
 }(document.write);
 alert("Override finished");
}

Is easy and works, but I would like my extension to setup the interception for each document object from inside the extension. I couldn't find a way to do this. I tried to listen for the "load" event and set up the interception there but it also fails. How do I hook calls to doc.write from an extension?

I made some progress:

var myExtension = {
  init: function() {
    var appcontent = document.getElementById("appcontent"); // browser
    if (appcontent)
      appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad,
        true);
  },

  onPageLoad: function(aEvent) {
    var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
    // do something with the loaded page.
    // doc.location is a Location object (see below for a link).
    // You can use it to make your code executed on certain pages only.
    alert("Override called");
    alert(doc);
    alert(doc.write);
    alert(doc.wrappedJSObject);
    alert(doc.wrappedJSObject.write);
    doc.wrappedJSObject.write = function(w) {
      return function(s) {
        alert("special dom");
        w.call(this, "(" + s + ")");
      };
    }(doc.write);
    alert("Override finished");
  }
}

This seem to work, but DOMContentLoaded is the wrong event for the job, because it is fired too late! Is there an earlier event to listen to?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最丧也最甜 2024-09-10 11:55:24

复活的问题!我得到了答案。以下是示例代码:

const os    = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);

os.addObserver({
    observe : function(aWindow, aTopic, aData) {
        if (aWindow instanceof Ci.nsIDOMWindow && aTopic == 'content-document-global-created') {
            aWindow.wrappedJSObject.myfunction = function(){
                // Do some stuff . . .
            }
        }
    }
}, 'content-document-global-created', false);

从 gecko 2.0 开始,具有事件 document-element-inserted 的文档也是如此。

Ressurection of the question ! I got the answer. Here is a sample code :

const os    = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);

os.addObserver({
    observe : function(aWindow, aTopic, aData) {
        if (aWindow instanceof Ci.nsIDOMWindow && aTopic == 'content-document-global-created') {
            aWindow.wrappedJSObject.myfunction = function(){
                // Do some stuff . . .
            }
        }
    }
}, 'content-document-global-created', false);

The same goes for document with the event document-element-inserted as of gecko 2.0 .

氛圍 2024-09-10 11:55:24

JavaScript 使用原型继承系统,对象没有类,而是有原型。原型是真实的对象,用作对其他对象的引用以继承方法和属性。

最好的策略是重写“文档”原型中写入的方法(对于 HTML 文档来说是 HTMLDocument)。这应该有效地包装浏览器中加载的页面内“文档”的所有实例的方法,因为它们都使用相同的原型。

而不是

document.write = function() { ... }

尝试这样的事情:

HTMLDocument.prototype.write= function() { ... }

更新:它似乎并不像我最初想象的那么容易,这似乎在第一次尝试时不起作用。

JavaScript uses a prototypical inheritance system, instead of having classes, objects have prototypes. Prototypes are real objects that are used as a reference to other objects for inheritance of methods and attributes.

The best strategy would be to override the method write in the prototype of "document" (which for the HTML document is HTMLDocument). This should effectively wrap the method for all instances of "document" inside the pages loaded in the browser since they all use the same prototype.

Instead of

document.write = function() { ... }

try something like this:

HTMLDocument.prototype.write= function() { ... }

UPDATE: It does not seem to be as easy as I initially thought, this does not seem to work at first try.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文