Communication between an HTML page and and extension
After building a sample extension by reading carefully and following the complete instructions for Building an Extension I was able to get an extension that could display something on the status bar. What I wanted to do was have an extension "look" for something on an HTML page and if it found that something perform some operation on the found thing and then update the status bar with the results of the operation. With a lot of help from irc://irc.mozilla.org#js and irc://irc.mozilla.org#extdev I was able to get it running pretty well, but I still would rather have the client less responsible for pinging the extension to "look" for what is on the page.
What I tried
- My first attempt was trying to create an XBL component. From what I gather, XBL components are more designed for creating custom components and their specific component behavior rather than trying to impose some kind of messaging on existing components.
- Next I started investigating events, there are only a handful of events and the W3C documentation is pretty complete.
The problem with the events is the timing. I wasn't sure about the difference between the capture or bubbling flag that you pass to addEventListener but every time I would catch the event in the extension, the element from the AJAX request wasn't fully updated into the HTML page. What that meant is that everytime the extension went looking for the element, it wasn't there yet.
As a last ditch effort I tried setting a timeout using
setTimeout when I got the event in the extension to wait a few milliseconds before looking for the desired element. This was non-optimal and the timeout wasn't very reliable for some reason. Sometimes I would get the timeout, sometimes I would'nt.
What I ended up with
Some helpful information on the irc channel led me to believe that a custom event might help. I started to research custom events on Google but everything that I found was far too complicated for what I wanted to achieve. Eventually I put the creation of the custom event into the stateChanged function that was handling the receipt of the AJAX request. After the HTML component was update with the result of the AJAX request, I created and dispatched the event like this:
var event = document.createEvent("Events"); event.initEvent("my-custom-event", true, true); document.body.dispatchEvent(event);
In the code of the extension that catches the loading of a new page I added this code:
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. if (doc && doc.addEventListener) doc.addEventListener("my-custom-event", myExtension.customReceived, false);
Since the event is dispatched after the element in the HTML is updated by the statusChanged function, the element that extension is looking for is there to find.