【问题标题】:How to override JavaScript function from a Firefox extension?如何覆盖 Firefox 扩展中的 JavaScript 函数?
【发布时间】:2011-02-26 04:49:36
【问题描述】:

我正在尝试拦截所有页面对 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");
}

简单且有效,但我希望我的扩展程序能够从扩展程序内部为每个文档对象设置拦截。我找不到办法做到这一点。我试图监听“加载”事件并在那里设置拦截,但它也失败了。如何将分机的呼叫挂接到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 是该作业的错误事件,因为它被触发得太晚了!有没有更早的事件可以收听?

【问题讨论】:

  • 我想出了一种不同的方法来回避不得不介入 document.write。但这并不意味着它是不可能的:-)
  • 其实,我期待覆盖 window.print 但问题是一样的。

标签: javascript firefox-addon document.write


【解决方案1】:

问题的复现!我得到了答案。这是一个示例代码:

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 的文档也是如此。

【讨论】:

  • 大多数 DOM 提供的函数是不可写的,包括document.write。 Firefox 会给你一个错误,告诉你只提供了一个 getter。
  • 我没有对 document.write 进行测试,但它对实际项目中的许多其他人都有效。我在 Firefox 3.6 和 4.0 上使用它。从那以后它可能已经改变了。
【解决方案2】:

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

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

代替

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

试试这样的:

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

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

【讨论】:

  • 它似乎不起作用:-/ 分配是正确的:如果我这样做:HTMLDocument.prototype.write = function (str) { alert(str) };然后 alert(HTMLDocument.prototype.write) 显示我的功能。但是页面中的 document.write 不会调用我的自定义函数。
  • @BruceBerry。对不起,你是对的,我刚刚测试过。我确信它会起作用,尽管我从未以这种方式使用它。我尝试从浏览器中的不同上下文访问 HTMLDocument.prototype。它起作用的唯一方法是 HTMLDocument.write = function(){..} 位于页面本身中,但这又回到了您最初的问题,即如何在页面加载之前将其放在那里。我会尝试其他一些想法......同时,如果你找到解决方案,请在此处发布!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多