Search code examples
javascriptfirefox-addondocument.write

How to override JavaScript function from a Firefox extension?


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?


Solution

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