最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How to override JavaScript function from a Firefox extension? - Stack Overflow

programmeradmin3浏览0评论

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");
  }
}

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?

Share Improve this question edited Apr 19, 2019 at 18:02 double-beep 5,53719 gold badges40 silver badges49 bronze badges asked Jun 1, 2010 at 4:47 BruceBerryBruceBerry 1,1861 gold badge9 silver badges21 bronze badges 2
  • I came up a different approach to sidestep having to interpose on document.write. It doesn't necessary mean that it's impossible though :-) – BruceBerry Commented Jul 12, 2011 at 0:31
  • Actually, I was expecting to override window.print but the problem is the same. – deadalnix Commented Jul 12, 2011 at 8:39
Add a ment  | 

2 Answers 2

Reset to default 4

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

const os    = Components.classes["@mozilla/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 .

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.

发布评论

评论列表(0)

  1. 暂无评论