views:

190

answers:

3

I want my Firefox extension to add an object to the content window of the browsed page. I want it to have the same effect as running:

top.myobj = {val : 3};

inside a script element in the page.

Any ideas?

I don't think there is a security risk here as I only add an object with a single integer property. Is there a simple way to get the content window object from within the extension code?

A: 

Does it need to be the window, or can it be the document itself? You can always use content.document reference the page itself. Or window.content for the primary content window.

Chris Doggett
That doesn't let you set properties in the content window, though.
Nickolay
A: 

use

var mainWindow = window
 .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
 .getInterface(Components.interfaces.nsIWebNavigation)
 .QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem
 .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
 .getInterface(Components.interfaces.nsIDOMWindow);

mainWindow.getBrowser().addEventListener("DOMContentLoaded",
      youreventhandler, true);

function youreventhandler(event) {
    if (event.originalTarget instanceof HTMLDocument) {

        var doc = event.originalTarget;
        //doc = the document in the just loaded window

        var win = doc.defaultView;

        // if it's just a frame element, then return and wait for the   
        // main event to fire.
        if (win.frameElement)
            return;
        else {
            win.myobj = { val: 3};
            //your other code here
        }
    }
}
Jonathan Fingland
That's probably way more code than needed. If the add-on is already in the browser scope, like most add-ons, then getBrowser() can be called to get the browser object:getBrowser().addEventListener(...)
sdwilsh
Unfortunately the OP didn't provide much detail on the circumstances. In this case I figured too much was better than too little.
Jonathan Fingland
The problem is that someone landing on this page might just copy this "much" without understanding any of it. So please don't do this :)
Nickolay
@Nikolay, are you saying the answer is not useful? Down votes aren't intended to enforce your personal preference of answer length. Is the answer helpful or not?
Jonathan Fingland
+1  A: 

You should use evalInSandbox to execute the assignment in the context of window.content similarly to this code:

// |content| refers to the current tab's |window| object
var s = new Components.utils.Sandbox(content);
s.window = content;
Components.utils.evalInSandbox(
   "window.wrappedJSObject.test = function() { } ", s)

BTW, re "I don't think there is a security risk here" - adding a property to an object may result in executing code (since JS has setters), so touching the content is always dangerous. The example above only touches insecure object (content.wrappedJSObject) in a sandbox without chrome permissions, so it's OK.

Nickolay