Oct 09 2009
Implementing an XPCOM Firefox Interface and Creating Observers
There are lots of cases when it is desirable to implement one of the XPCOM interfaces in use by Firefox, or other mozilla-based browsers. There are three cases where PirateQuesting does so, but once you see the concept, it should be easy to adapt to your situation.
-
You must have a QueryInterface to enjoy this ride
First off, all XPCOM interfaces in Firefox inherit from
nsISupports(Also see details on oxymoronical.com here). Only one method is scriptable and part of XPCOM —QueryInterface— and it must be present in all implementations of XPCOM interfaces.//"implements" nsISupports var InterfaceImplementation = function() { QueryInterface: function (aIID) { if (aIID.equals(Components.interfaces.nsISupports)) { return this; } throw Components.results.NS_NOINTERFACE; } }The above is an example of the very minimum required to support any interface.
QueryInterfacerequires a first parameter which is an aIID fromComponents.interfaces.*. There is also a second, optional, parameter, but as I have never come across this in use, it’s not worth pursuing here. -
Now what?
A very common (and useful) use of XPCOM interface implementation is creating your own observers, for example:
var myObserver = { observe: function(request, aTopic, aData){ if (aTopic == "http-on-examine-response") { //response has come back, now what? } else if (aTopic == "http-on-modify-request") { //opportunity to modify headers on request } }, QueryInterface: function(aIID){ if (aIID.equals(Components.interfaces.nsIObserver) || aIID.equals(Components.interfaces.nsISupports)) { return this; } throw Components.results.NS_NOINTERFACE; }, };The nsIObserver interface is fairly simple as it only adds one new method. As you can see now, though,
QueryInterfacenow checks for bothnsIObserverandnsISupports. Remember: any interface you implement must have aQueryInterfacesupporting all interfaces in the inheritance chain. -
Observer registration
If you then wanted to register your observer, it’s as easy as:
var observerService = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService); observerService.addObserver(myObserver,"http-on-examine-response", false); observerService.addObserver(myObserver,"http-on-modify-request", false);Then to unregister, you do:
observerService.removeObserver(myObserver, "http-on-examine-response"); observerService.removeObserver(myObserver, "http-on-modify-request");When I have a chance, I’ll add a more complete example of using observers to watch http requests, but in the meantime check out the list of Observer Notifications at MDC.
