views:

225

answers:

1

Hello,

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?

Update: 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?

+1  A: 

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.

fms
it doesn't seem to work :-/the assignment is correct:if i do: HTMLDocument.prototype.write = function (str) { alert(str) };then alert(HTMLDocument.prototype.write) shows my function. But document.write in pages doesn't call my custom function.
BruceBerry
@BruceBerry. Sorry, you are right, I just tested it. I was confident it was going to work, although I had never used it in this way. I tried accessing HTMLDocument.prototype from different contexts within the browser. The only way it worked is when the HTMLDocument.write = function(){..} was in the page itself, but that goes back to your original problem, how to put it there before the page loads. I will try a couple of other ideas... in the meanwhile, if you figure out a solution, post it here!
fms