Chrome: Command Line
From MDC
Extensions and XUL applications can modify the way command line parameters are handled by writing a component that implements nsICommandLineHandler and registering it in a category.
[edit] Overview
The attached code is a component written using the XPCOM framework, accessed from JavaScript via XPConnect
The official (terse) page for describing how Firefox handles command lines and initial startup can be found at the nsICommandLine documentation. There, you'll find links to the code for the XPIDL file defining the interface implemented below, and to other related .idl files.
The below example component will implement two command line parameters:
- firefox.exe -myapp
- Opens a chrome window for My Application.
- firefox.exe -viewapp url
- Opens a chrome window for My Application and passes it a nsIURI object.
For more clues on writing and registering XPCOM in Javascript, you can try the tutorial
In order to register the component illustrated in the Sample code section, save the JavaScript shown in the big box below into a file with the extension .js and drop it into one of the directories (see Bundles) that Firefox scans for extensions. A typical location in Windows would be "C:\Program Files\Mozilla Firefox\components" or your extension's components directory.
Then, (with Firefox shut down) delete the compreg.dat file, to force Firefox to rebuild its component list, and restart Firefox. You'll find the compreg.dat file in your profile directory, not to be confused with the file by the same name in your Firefox directory.
Your profile directory will be in your home directory (~/.mozilla/firefox under Linux) or in something like: "C:\Documents and Settings\(user-name)\Application Data\Mozilla\Firefox\Profiles\" under Windows.
After you have restarted Firefox, you should then see the component in the newly created compreg.dat file.
Its contract ID will look like: @mozilla.org/commandlinehandler/general-startup;1?type=myapp
If you have the Extension Developer's Extension installed, you should be able to access the component via the Javascript shell, by examining the Components.classes and Components.classesByID arrays. You'll find an example in the tutorial.
[edit] Sample Code
const nsIAppShellService = Components.interfaces.nsIAppShellService; const nsISupports = Components.interfaces.nsISupports; const nsICategoryManager = Components.interfaces.nsICategoryManager; const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar; const nsICommandLine = Components.interfaces.nsICommandLine; const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler; const nsIFactory = Components.interfaces.nsIFactory; const nsIModule = Components.interfaces.nsIModule; const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher; // CHANGEME: to the chrome URI of your extension or application const CHROME_URI = "chrome://myapp/content/"; // CHANGEME: change the contract id, CID, and category to be unique // to your application. const clh_contractID = "@mozilla.org/commandlinehandler/general-startup;1?type=myapp"; // use uuidgen to generate a unique ID const clh_CID = Components.ID("{2991c315-b871-42cd-b33f-bfee4fcbf682}"); // category names are sorted alphabetically. Typical command-line handlers use a // category that begins with the letter "m". const clh_category = "m-myapp"; /** * Utility functions */ /** * Opens a chrome window. * @param aChromeURISpec a string specifying the URI of the window to open. * @param aArgument an argument to pass to the window (may be null) */ function openWindow(aChromeURISpec, aArgument) { var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]. getService(Components.interfaces.nsIWindowWatcher); ww.openWindow(null, aChromeURISpec, "_blank", "chrome,menubar,toolbar,status,resizable,dialog=no", aArgument); } /** * The XPCOM component that implements nsICommandLineHandler. * It also implements nsIFactory to serve as its own singleton factory. */ const myAppHandler = { /* nsISupports */ QueryInterface : function clh_QI(iid) { if (iid.equals(nsICommandLineHandler) || iid.equals(nsIFactory) || iid.equals(nsISupports)) return this; throw Components.results.NS_ERROR_NO_INTERFACE; }, /* nsICommandLineHandler */ handle : function clh_handle(cmdLine) { try { // CHANGEME: change "viewapp" to your command line flag that takes an argument var uristr = cmdLine.handleFlagWithParam("viewapp", false); if (uristr) { // convert uristr to an nsIURI var uri = cmdLine.resolveURI(uristr); openWindow(CHROME_URI, uri); cmdLine.preventDefault = true; } } catch (e) { Components.utils.reportError("incorrect parameter passed to -viewapp on the command line."); } // CHANGEME: change "myapp" to your command line flag (no argument) if (cmdLine.handleFlag("myapp", false)) { openWindow(CHROME_URI, null); cmdLine.preventDefault = true; } }, // CHANGEME: change the help info as appropriate, but // follow the guidelines in nsICommandLineHandler.idl // specifically, flag descriptions should start at // character 24, and lines should be wrapped at // 72 characters with embedded newlines, // and finally, the string should end with a newline helpInfo : " -myapp Open My Application\n" + " -viewapp <uri> View and edit the URI in My Application,\n" + " wrapping this description\n", /* nsIFactory */ createInstance : function clh_CI(outer, iid) { if (outer != null) throw Components.results.NS_ERROR_NO_AGGREGATION; return this.QueryInterface(iid); }, lockFactory : function clh_lock(lock) { /* no-op */ } }; /** * The XPCOM glue that implements nsIModule */ const myAppHandlerModule = { /* nsISupports */ QueryInterface : function mod_QI(iid) { if (iid.equals(nsIModule) || iid.equals(nsISupports)) return this; throw Components.results.NS_ERROR_NO_INTERFACE; }, /* nsIModule */ getClassObject : function mod_gch(compMgr, cid, iid) { if (cid.equals(clh_CID)) return myAppHandler.QueryInterface(iid); throw Components.results.NS_ERROR_NOT_REGISTERED; }, registerSelf : function mod_regself(compMgr, fileSpec, location, type) { compMgr.QueryInterface(nsIComponentRegistrar); compMgr.registerFactoryLocation(clh_CID, "myAppHandler", clh_contractID, fileSpec, location, type); var catMan = Components.classes["@mozilla.org/categorymanager;1"]. getService(nsICategoryManager); catMan.addCategoryEntry("command-line-handler", clh_category, clh_contractID, true, true); }, unregisterSelf : function mod_unreg(compMgr, location, type) { compMgr.QueryInterface(nsIComponentRegistrar); compMgr.unregisterFactoryLocation(clh_CID, location); var catMan = Components.classes["@mozilla.org/categorymanager;1"]. getService(nsICategoryManager); catMan.deleteCategoryEntry("command-line-handler", clh_category); }, canUnload : function (compMgr) { return true; } }; /* The NSGetModule function is the magic entry point that XPCOM uses to find what XPCOM objects * this component provides */ function NSGetModule(comMgr, fileSpec) { return myAppHandlerModule; }