views:

938

answers:

2

I am developing a web-based javascript/html application with a sister firefox-extension.

The application's page-javascript performs a few XHR calls immediately after page-load, in order to bring in and display all the content that the page requires.

Is there a way, without polling the DOM, that my extension can know that the page's initialisation procedures are complete?

+1  A: 

You could hook into the XMLHttpRequest object from your extension and monitor the requests, similar to what this GreaseMonkey script does (description). Add a wrapper to onreadystatechange in the same way he's added a wrapper to open which notifies the extension when complete. Probably also want some code which makes sure you're only doing this when visiting your own page.

Firebug does similar stuff for its Net panel, the codebase for that is a bit more intimidating though :) I also had a look at the Firebug Lite watchXHR function, but that code is a bit too cunning for me, if you can work it out let me know.

robertc
+5  A: 

Interesting question indeed..

I've just found out through this post on MozillaZine's forum an easy way to accomplish this. The technique basically consists in defining a custom DOM element within the web page, filling it with some arbitrary attributes, and then using it as the target of a custom event. The event can than be captured and used to pass values from the webpage to the extension.

Web page (assumes jquery is available)

<script type="text/javascript">
    $(document).ready(function(){

    $.get("http://mywebsite.net/ajax.php",function(data){
         //[...]process data

        //define a custom element and append it to the document

         var element = document.createElement("MyExtensionDataElement");
         element.setAttribute("application_state", "ready");
         document.documentElement.appendChild(element);

         //create a custom event and dispatch it 
         // using the custom element as its target

         var ev = document.createEvent("Events");
         ev.initEvent("MyExtensionEvent", true, false);
         element.dispatchEvent(ev);
    });             
  });
</script>

Chrome code:

function myListener(e) {
   alert("data:" + e.target.getAttribute("application_state"));
}

function on_specialpage_load(event) {
  if (event.originalTarget instanceof HTMLDocument && 
      event.originalTarget.location.href == "http://mywebsite.net/myspecialpage.html") {

    var doc=event.originalTarget;
    doc.addEventListener("MyExtensionEvent", myListener, false, true);
  }
}
gBrowser.addEventListener("DOMContentLoaded",on_specialpage_load,false);

Notice that doc.addEventListener has a fourth parameter, indicating that it will accept events coming from untrusted code. However you can add this event listener selectively, so that only trusted pages from your site will be able to pass values to the extension.

And
... and a very interesting answer indeed. I'm really intrigued by the custom event and listener technique. Do you think this would be the best way for page-javascript to be able to "call" a function in the extension. e.g. to implement cross-site XHR on-click (within my own trusted app and domains).
Cheekysoft
Not sure if this is *the best* way, but it seems to be efficient and fairly safe. I've just tried to wrap into the listener a XHR request to an external site and it worked fine!
And
This is the recommended technique, yes: <https://developer.mozilla.org/en/Code_snippets/Interaction_between_privileged_and_non-privileged_pages>.
Nickolay