I just landed the patch for bug 512784 on mozilla-central. It adds a new module to the toolkit whose sole purpose is to expose memoized getters for common XPCOM services on a simple “Services” JS object. The first pass involved adding getters for the prefs service, observer service, window mediator, permission manager, IO Service, prompt service, and search service. This patch also updates Firefox’s browser.js to make use of the module, which means that trunk-based extensions that run code in Firefox chrome windows can start making use of it if they’d like.

Here’s an example of one of the changes:

+// Services = object with smart getters for common XPCOM services
 function getTopWin()
-  var windowManager = Components.classes[';1']
-                                .getService(Components.interfaces.nsIWindowMediator);
-  return windowManager.getMostRecentWindow("navigator:browser");
+  return Services.wm.getMostRecentWindow("navigator:browser");

I expect to add some other services to it as I look at expanding use of the module (Mossop has some suggestions in the bug). We might also add an equivalent in Firefox for browser-specific services, if that proves to be useful. The end goal is to remove a lot of the XPCOM boilerplate junk we see spread around our front-end JS code, and a side benefit is the reduction of unnecessary getService() calls for services that are already guaranteed to be otherwise instantiated and kept around for the app’s lifetime. This necessarily implies that JS scopes where the module was imported will now have permanent references to services after their first use, which is worth keeping in mind, both when making use of of the module and when adding additional getters to it.

7 thoughts on “Services.jsm

  1. AndersH

    Would it be silly to use something like __noSuchMethod__ to add the shorthand for all (or most) classes at once. Also this way the new names are guessable and documented since they are the same as the old. Pseudo-code (I hope it doesn’t turn up to garbled):

    var Services = {
    __noSuchMethod__: function(id, args) {
    var cName = id.replace(/([A-Z])/, “-$1”).toLowerCase();
    var iName = “nsI” + id.substring(0, 1).toUpperCase() + id.substring(1);
    var c = Components.classes[‘” + cName + “;1’];
    var i = Components.interfaces[iName];
    return c.getService(i);

    function getTopWin() {
    return Services.windowMediator().getMostRecentWindow(“navigator:browser”);

  2. AndersH

    Sorry, I overlooked the “appshell” part. And doing something like …appshell$windowMediator() will probably be to long.

  3. Pingback: Home of KaiRo: Weekly Status Report, W08/2010

  4. Pingback: Gavin’s blog » browser.js cleanup ideas

  5. Pingback: Taras’ Blog » Blog Archive » mozilla::services

Leave a Reply

Your email address will not be published. Required fields are marked *