1

Is there any way to implement nsICommandLineHandler in a restartless add-on?

It seems possible from https://addons.mozilla.org/en-US/developers/docs/sdk/latest/modules/sdk/platform/xpcom.html , but this code (run from within exports.main) is not working for me:

var { Class } = require('sdk/core/heritage');
var { Unknown, Factory } = require('sdk/platform/xpcom');
var { Cc, Ci } = require('chrome');

var contractId = '@mozilla.org/commandlinehandler/general-startup;1?type=webappfind';

// Define a component
var CommandLineHandler = Class({
  extends: Unknown,
  get wrappedJSObject() this,

  classDescription: "webAppFinder",
  /* Not used by SDK, so commenting out
  _xpcom_categories: [{  
    category: "command-line-handler",  
    // category names are sorted alphabetically. Typical command-line handlers use a  
    // category that begins with the letter "m".  
    entry: "m-webappfind"  
  }],
  */
  helpInfo : "  -webappfind               Open My Application\n",
  // nsICommandLineHandler
  handle : function clh_handle(cmdLine) {
    try {
        console.log('good so far'); // Doesn't actually reach here
        var fileStr = cmdLine.handleFlagWithParam("webappfind", false);
        if (fileStr) {
          console.log('made it');
        }
    }
    catch (e) {
        Cu.reportError("incorrect parameter passed to -webappfind on the command line.");
    }

    if (cmdLine.handleFlag("webappfind", false)) { // no argument
        cmdLine.preventDefault = true;
        throw 'A valid ID must be provided to webappfind';
    }
  },
  hello: function() {return 'Hello World';}
});

// Create and register the factory
var factory = Factory({
  contract: contractId,
//  id: '{7f397cba-7a9a-4a05-9ca7-a5b8d7438c6c}', // Despite the docs saying one can add both, this doesn't work
  Component: CommandLineHandler
});

I have the following code afterward which works...

// XPCOM clients can retrieve and use this new
// component in the normal way
var wrapper = Cc[contractId].createInstance(Ci.nsISupports);
var helloWorld = wrapper.wrappedJSObject;
console.log(helloWorld.hello());

...but Firefox is not accepting command line args as per this error:

Error: Warning: unrecognized command line flag -webappfind

Source file: resource://app/components/nsBrowserContentHandler.js Line: 765

UPDATE

I've now taken @nmaier's advice to add categories and therefore added these lines afterward:

var catMan = Cc['@mozilla.org/categorymanager;1'].getService(Ci.nsICategoryManager); //
catMan.addCategoryEntry('command-line-handler', 'm-webappfind' /*contractId*/, contractId, false, true);

But I'm getting these 3 errors when invoking from the command line:

Error: [Exception... "'Failure' when calling method: [nsIFactory::createInstance]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "native frame :: :: :: line 0" data: no]

Contract ID '@mozilla.org/commandlinehandler/general-startup;1?type=webappfind' was registered as a command line handler for entry 'm-webappfind', but could not be created.

Error: Warning: unrecognized command line flag -webappfind

Source file: resource://app/components/nsBrowserContentHandler.js Line: 765

Brett Zamir
  • 14,034
  • 6
  • 54
  • 77

1 Answers1

1

The SDK will not register categories for you.

Some remarks regarding categories can be found here: https://stackoverflow.com/a/18366485/484441

But still, I'm not sure if bootstrapped extensions are actually started before the initial command line is processed. Trial and error, I guess...

Edit: Your component does not specify any interfaces, hence it does only support nsISupports. The SDK module docs state that you should add an interfaces: [ 'nsICommandLineHandler' ] property.

Community
  • 1
  • 1
nmaier
  • 32,336
  • 5
  • 63
  • 78
  • Thanks...I've updated my main post to indicate the 3 errors I'm seeing. My guess based on these errors would be that the timing may be ok but something else is wrong, though I'm not sure. Any ideas? – Brett Zamir Aug 25 '13 at 01:26
  • Updated the answer, regarding missing `interfaces`. – nmaier Aug 25 '13 at 11:27
  • It works! When I update the add-on through the builder, even without a restart, it uses the latest handler implementation too. I see I got tripped missing that since the 2nd example didn't use an interface. I love you man! :) – Brett Zamir Aug 25 '13 at 12:18
  • As an FYI, per http://forums.mozillazine.org/viewtopic.php?p=2025775&sid=d0ee64ccb490e98d481b854cae0fec31#p2025775 , it seems `helpInfo` is not used by Firefox. Also, the extra category manager code is needed, but it may not appear so if you reinstall the add-on while Firefox is still open. But I've commented out the categories from my main post as that is not needed since as you say it is not used by the SDK. – Brett Zamir Aug 25 '13 at 13:06
  • As I wrote in http://stackoverflow.com/a/18366485/484441 you really need to remove the category yourself on unload, as your restartless add-on need to clean up after itself and you won't want to be leaking and left with the old implementation of your component after an update, and you need to do it in an awkward (delayed) fashion. You should test your code by disabling your add-on and checking that the comment is indeed gone from the nsICategoryManager enumeration. – nmaier Aug 25 '13 at 14:08