Sending messages from content to chrome (part 3)

UPDATE: This code has not been seriously audited for security holes, and may introduce vulnerabilities. Also, when I wrote it I did not take into account work on Gecko 1.9. Please be aware this code has not gone through rigourous testing.

Several months ago, I came around with a question: how should I send information from a content page to chrome. I wasn’t able to do it by DOM events as bz suggested, so when I did a little thinking, I came up with a solution for ManyOne Networks, Inc., my employer, that I wasn’t able to talk about at the time.

That time has passed. Regretfully, ManyOne has decided not to release the product I was working on, but they’ve no qualms about releasing the source code behind it. Including my special message-passing code.

dust-source.tar.bz2 > components/mnIChromeMessenger.idl and components/mnChromeMessenger.js .

How a webpage uses it:

  1. You create a JS-based object containing all the data you want passed upstairs.
  2. You include a window property, which is the top window you can reach.
  3. You wrap this object in another JS object (which I refer to as wrapper), as its wrappedJSObject:
    /**
    * Wrap a JavaScript object for passing to components code.
    */
    function ObjectWrapper(object) {
    this.wrappedJSObject = object;
    }
  4. Call chromeMessenger.send(wrapper).

This does some minor sanity-checking on the wrapped object (basically, making sure all but a couple properties are numbers, strings, boolean or undefined), and then dispatches a message to Mozilla’s observer service, with a topic of “content-message”.

Now, it’s entirely up to the chrome and XPCOM code to write observers to listen for this particular topic of message. One idea we had was to use this for opening new tabs by script. You’ll find in the tarball’s chrome/portlets/content/navigatorOverlay.js at line 448 a procedure by which we did this. There are some weaknesses in the scheme (notably, this code can’t be used to directly return a window object of the new browser to the caller, and there’s no concept of tabbrowser’s maximum tab count – thus inviting tabbrowser spam), but overall, it would do what we needed it to do.

Personally, I’d like to see mozilla.org review and adopt this code somewhere – say, in extensions/chrome-messenger, or perhaps in the toolkit if the Aviary or Firefox teams want it. I wrote this code for commercial use, and we tested it pretty thoroughly on our company’s product. It works beautifully.

I’m thinking seriously about submitting a bug to get this code checked in, but I’d like your feedback on where in the source it should live, and who wants this capability. If there’s not enough interest, then I won’t file a bug and we’ll just leave it on the sidelines, maybe as a XPI on addons.m.o.

P.S. This is my 300th blog entry. Nice coincidence that it should be a useful one.

5 thoughts on “Sending messages from content to chrome (part 3)”

  1. Wow, this is useful. I have run into the same situation, but never pursued a solution. Thanks for sharing.

  2. I’m using the following technique for quite some time now:
    To generate the event in the webpage:
    top.mydata = mydata //can be any object
    var event = document.createEvent(“Events”);
    event.initEvent(“myevent”, true, true);
    top.dispatchEvent(event);
    To catch the event in chrome:
    addEventListener(“myevent”,onMyEvent,false,true);
    function onMyEvent(event) {
    var target = event.target.wrappedJSObject;
    var mydata = target.mydata;
    //….
    }
    No need for a component
    (From Alex: Due to an ancient architectural bug in our software, we couldn’t do that. top.mydata would only allow one slot worth of data to be carried; it’s not OOP. The solution I came up with is more flexible. On top of that, events are a little expensive on the Mozilla code – there’s a lot of nodes which have to process the event, even if only to detect whether the event affects them or not.)

  3. Yeah – this could be really useful. I’ve needed something like this for a while, but wasn’t sure it was possible, so I didn’t spend a lot of time trying to figure it out. As a general capability, it could really open up the possibilities for cool extensions that do things with web pages. Firefox really needs something like that to really take off.

  4. what a beautiful man you are 🙂
    I had given up being able to send message from content to chrome. I basically had to create a div with a certain ID and on each page load my extension would watch for that id, then assign a certain onclick I needed for it.

  5. For people who find this page -and- read the comments, here’s the solution I’ve been recommending for people to use:
    http://forums.mozillazine.org/viewtopic.php?p=1005555#1005555
    Note that it’s slightly different from the solution in comment 2 – it doesn’t use wrappedJSObject, so it is generally safer. If you want to pass more complicated structures than just strings, you can pass the JSON representation of those structures.

Comments are closed.