Search code examples
firefox-addonxulxpcom

How to manipulate window prototype in a <browser> element?


What I'm doing right now is:

When <browser src="..." /> loads, I attach data into its .contentWindow:

frame.addEventListener("load",function(){
    this.contentWindow.someMethod = function(){};
},true);

Now I want to know if there is a way to do this earlier, into the <browser>'s window prototype, or any Window prototype, as for example I can do in the "current" window:

// [W]indow is the constructor
Window.prototype.test = function(){ alert("hello"); };
// [w]indow is the instance
window.test();

Solution

  • There are currently two ways to inject properties into a window before any JavaScript code runs. Usually, content-document-global-created notification is simpler. The other is implementing nsIDOMGlobalPropertyInitializer interface. Both allow you to get notified when a new window loads and before that window runs JavaScript code.

    Here is the approximate code for doing it with the observer notification:

    const Cc = Components.classes;
    const Ci = Components.interfaces;
    const Cu = Components.utils;
    Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    
    var myObserver =
    {
      QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
    
      observe: function(subject, topic, data)
      {
        if (topic == "content-document-global-created" &&
            subject instanceof Ci.nsIDOMWindow &&
            subject.location.hostname == "example.com")
        {
          XPCNativeWrapper.unwrap(subject).someMethod = function() {};
        }
      }
    };
    
    var observerService = Cc["@mozilla.org/observer-service;1"]
                            .getService(Ci.nsIObserverService);
    observerService.addObserver(myObserver, "content-document-global-created", true);