home *** CD-ROM | disk | FTP | other *** search
/ Freelog 112 / FreelogNo112-NovembreDecembre2012.iso / Multimedia / Songbird / Songbird_2.0.0-2311_windows-i686-msvc8.exe / components / sbCommandLine.js < prev    next >
Text File  |  2012-06-08  |  16KB  |  469 lines

  1. /**
  2. //
  3. // BEGIN SONGBIRD GPL
  4. //
  5. // This file is part of the Songbird web player.
  6. //
  7. // Copyright(c) 2005-2008 POTI, Inc.
  8. // http://songbirdnest.com
  9. //
  10. // This file may be licensed under the terms of of the
  11. // GNU General Public License Version 2 (the "GPL").
  12. //
  13. // Software distributed under the License is distributed
  14. // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
  15. // express or implied. See the GPL for the specific language
  16. // governing rights and limitations.
  17. //
  18. // You should have received a copy of the GPL along with this
  19. // program. If not, go to http://www.gnu.org/licenses/gpl.html
  20. // or write to the Free Software Foundation, Inc.,
  21. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22. //
  23. // END SONGBIRD GPL
  24. //
  25.  */
  26.  
  27. /**
  28.  * \file sbCommandLine.js
  29.  * \brief Implementation of the interface nsICommandLine
  30.  * \todo Implement the -play functionality
  31.  */
  32.  
  33. const Cc = Components.classes;
  34. const Ci = Components.interfaces;
  35. const Cr = Components.results;
  36. const Cu = Components.utils;
  37.  
  38. const SONGBIRD_CLH_CONTRACTID = "@songbirdnest.com/commandlinehandler/general-startup;1?type=songbird";
  39. const SONGBIRD_CLH_CID = Components.ID("{128badd1-aa05-4508-87cc-f3cb3e9b5499}");
  40. const SONGBIRD_CLH_CLASSNAME = "Songbird Command Line Handler";
  41. // "m" for ordinary priority see sbICommandLineHandler.idl
  42. const SONGBIRD_CLH_CATEGORY= "m-songbird-clh";
  43.  
  44. // Command Line Startup Topic that's used to notify that the application
  45. // has parsed the command line. This enables the Application Startup Service
  46. // to initialize the application after we've parsed out the command line.
  47. const COMMAND_LINE_TOPIC  = "sb-command-line-startup";
  48.  
  49. function _debugPrint(msg) {
  50.   if (/@ 0x/(__LOCATION__)) {
  51.     dump(msg + "\n");
  52.   }
  53. }
  54.  
  55. function resolveURIInternal(aCmdLine, aArgument) {
  56.   var uri = aCmdLine.resolveURI(aArgument);
  57.  
  58.   if (!(uri instanceof Components.interfaces.nsIFileURL)) {
  59.     return uri;
  60.   }
  61.  
  62.   return checkUri(uri, aArgument);
  63. }
  64.  
  65. function checkUri(aURI, aURL) {
  66.   try {
  67.     if (aURI instanceof Components.interfaces.nsIFileURL)
  68.       if (aURI.file.exists())
  69.         return aURI;
  70.   }
  71.   catch (e) {
  72.     Cu.reportError(e);
  73.   }
  74.  
  75.   // We have interpreted the argument as a relative file URI, but the file
  76.   // doesn't exist. Try URI fixup heuristics: see bug 290782.
  77.  
  78.   try {
  79.     var urifixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
  80.                               .getService(Ci.nsIURIFixup);
  81.  
  82.     aURI = urifixup.createFixupURI(aURL, 0);
  83.   }
  84.   catch (e) {
  85.     Cu.reportError(e);
  86.   }
  87.  
  88.   return aURI;
  89. }
  90.  
  91. function shouldLoadURI(aURI) {
  92.   if (!aURI || aURI == "") return false;
  93.   if (aURI && !aURI.schemeIs("chrome"))
  94.     return true;
  95.  
  96.   dump("*** Preventing external load of chrome URI into browser window (" + aURI.spec + ")\n");
  97.   dump("    Use -chrome <uri> instead\n");
  98.   return false;
  99. }
  100.  
  101. /**
  102.  * /brief Songbird commandline handler
  103.  */
  104. function sbCommandLineHandler() {
  105.   this.itemHandlers = []; // array of handlers
  106.   this.itemUriSpecs = []; // array of uri specs
  107.   this.flagHandlers = []; // array of arrays (handler, flag)
  108.   this.flags = [];        // array of arrays (flag, param)
  109. }
  110.  
  111. sbCommandLineHandler.prototype = {
  112.   // there are specific formatting guidelines for help test, see nsICommandLineHandler
  113.   helpInfo : "  -test [tests]        Run tests on the components listed in the\n" +
  114.              "                       optional comma-separated list of tests.\n" +
  115.              "                       If no tests are passed in ALL tests will be run.\n\n" +
  116.              "  [url|path]           Local path/filename to media items to import and play,\n" +
  117.              "                       or URL to load in the browser.\n\n" +
  118.              "  -register-extensions Registers extensions and then quits.\n\n",
  119.   itemHandlers: null,
  120.   itemUriSpecs: null,
  121.   flagHandlers: null,
  122.   flags: null,
  123.  
  124.   handle : function (cmdLine) {
  125.  
  126.     var urilist = [];
  127.     var oldlength = this.itemUriSpecs.length;
  128.  
  129.     if (cmdLine.handleFlag("register-extensions", false)) {
  130.       _debugPrint("aborting due to handle of register-extensions");
  131.       throw Cr.NS_ERROR_ABORT;
  132.     }
  133.  
  134.     try {
  135.       var ar;
  136.       while ((ar = cmdLine.handleFlagWithParam("url", false))) {
  137.         urilist.push(resolveURIInternal(cmdLine, ar));
  138.       }
  139.     }
  140.     catch (e) {
  141.       Cu.reportError(e);
  142.     }
  143.  
  144.     // Notify observers of COMMAND_LINE_TOPIC that the command line
  145.     // has been parsed and the application is ready to be started up.
  146.     var observerService = Cc["@mozilla.org/observer-service;1"]
  147.                             .getService(Ci.nsIObserverService);
  148.     try {
  149.       observerService.notifyObservers (cmdLine, COMMAND_LINE_TOPIC, null);
  150.     } 
  151.     catch (e) {
  152.       Cu.reportError(e);
  153.     }
  154.  
  155.     var tests = null;
  156.     var emptyParam = false;
  157.     try {
  158.       tests = cmdLine.handleFlagWithParam("test", false);
  159.     }
  160.     catch (e) {
  161.       // cmdLine throws if there is no param for the flag, but we want the
  162.       // parameter to be optional, so catch the exception and let ourselves
  163.       // know that things are okay. The flag existed without a param.
  164.       emptyParam = true;
  165.     }
  166.  
  167.     // if there was a parameter or if we had a flag and no param
  168.     if (tests != null || emptyParam) {
  169.       // we're running tests, make sure we don't open a window
  170.       cmdLine.preventDefault = true;
  171.       var testHarness = Cc["@songbirdnest.com/Songbird/TestHarness;1"].getService(Ci.sbITestHarness);
  172.  
  173.       var exception;
  174.       try {
  175.         testHarness.init(tests);
  176.         testHarness.run();
  177.       }
  178.       catch (e) {
  179.         exception = e;
  180.       }
  181.       
  182.  
  183.       var platformStr = Cc["@mozilla.org/system-info;1"]
  184.                         .getService(Ci.nsIPropertyBag2).getProperty("name");
  185.       
  186.       // If we are on Mac, unfortunately the event-queue slows down to slug
  187.       // speed when there isn't a window open and we are shutting down. Since 
  188.       // there isn't a window being used on these unit tests - the hybrid
  189.       // Cocoa/Gecko event loop takes a long time (over 20 minutes) to kill the
  190.       // 100 or so threads that get spooled up during the test cases.
  191.       
  192.       // Unfortunately, this also happens on Windows :(
  193.  
  194.       // To fix this problem, we will use a nasty little hack. Open up the a
  195.       // plain window that closes itself after a couple of seconds. This fires
  196.       // the application shutdown procedure just as if we had closed the main
  197.       // Songbird window.
  198.       //
  199.       // Yes - I know this sucks, I hate myself a little more for doing this.
  200.       if (platformStr == "Darwin" ||
  201.           platformStr == "Windows_NT") {
  202.         var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
  203.                  .getService(Ci.nsIWindowWatcher);
  204.         
  205.         ww.openWindow(null, 
  206.                       "chrome://songbird/content/xul/unitTestShutdownWin.xul", 
  207.                       "shutdownwin", "chrome", null);
  208.       }
  209.       else {
  210.         // Linux can follow this 'standard' shutdown procedure:
  211.         //
  212.         // Fake the sequence of observer notifications for app shutdown. This
  213.         // sequence should match that of canQuitApplication (from
  214.         // globalOverlay.js) and nsAppStartup::Quit (from nsAppStartup.cpp).
  215.         var os = Cc["@mozilla.org/observer-service;1"].
  216.                  getService(Ci.nsIObserverService);
  217.  
  218.         // We don't care if anyone tries to cancel quit...
  219.         var dummyCancelQuit = Cc["@mozilla.org/supports-PRBool;1"].
  220.                               createInstance(Ci.nsISupportsPRBool);
  221.         os.notifyObservers(dummyCancelQuit, "quit-application-requested", null);
  222.  
  223.         os.notifyObservers(null, "quit-application-granted", null);
  224.  
  225.         var appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
  226.                            .getService(Ci.nsIAppStartup);
  227.         appStartup.quit(Ci.nsIAppStartup.eAttemptQuit);
  228.       }
  229.  
  230.       if (exception) {
  231.         throw Cr.NS_ERROR_ABORT;
  232.       }
  233.     }
  234.  
  235.     // XXX bug 2186
  236.     var count = cmdLine.length;
  237.       for (var i = 0; i < count; ++i) {
  238.         // getArgument sometimes causes an exception for the last parameter, 
  239.         // even tho i is always below cmdLine.length ! This doesn't seem to
  240.         // ever happen when the commandline is starting the app, but seems to
  241.         // always do when the app is already started, and the commandline is
  242.         // received from another instance.
  243.         try {
  244.           var curarg = cmdLine.getArgument(i);
  245.         } catch (e) {
  246.           Components.utils.reportError(e);
  247.           // try next argument. there shouldn't be any, but just in case...
  248.           continue
  249.         }
  250.  
  251.         if (curarg == "") continue;
  252.         if (curarg.match(/^-/)) {
  253.           // Components.utils.reportError("Warning: unrecognized command line flag " + curarg + "\n");
  254.           // To emulate the pre-nsICommandLine behavior, we ignore
  255.           // the argument after an unrecognized flag.
  256.           ++i;
  257.         } else {
  258.           try {
  259.             cmdLine.removeArguments(i, i);
  260.             urilist.push(resolveURIInternal(cmdLine, curarg));
  261.           }
  262.           catch (e) {
  263.             Components.utils.reportError("Error opening URI '" + curarg + "' from the command line: " + e + "\n");
  264.           }
  265.         }
  266.       }
  267.  
  268.     for (var uri in urilist) {
  269.       if (shouldLoadURI(urilist[uri])) {
  270.         this.itemUriSpecs.push(urilist[uri].spec);
  271.       }
  272.     }
  273.  
  274.     if (this.itemUriSpecs.length > oldlength)
  275.       this.dispatchItems();
  276.  
  277.     this.handleRemainingFlags(cmdLine);
  278.     this.dispatchFlags();
  279.   },
  280.  
  281.   handleURL: function(aURL) {
  282.     var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  283.                               .getService(Components.interfaces.nsIIOService);
  284.     var uri = ioService.newURI(aURL, null, null);
  285.     uri = checkUri(uri, aURL);
  286.     if (shouldLoadURI(uri)) {
  287.       this.itemUriSpecs.push(uri.spec);
  288.       this.dispatchItems();
  289.     }
  290.   },
  291.  
  292.   handleRemainingFlags: function(cmdLine) {
  293.     while (cmdLine.length) {
  294.       var curarg = cmdLine.getArgument(0);
  295.       if (curarg.match(/^-/)) {
  296.         var flag = curarg.slice(1);
  297.  
  298.         var param;
  299.  
  300.         var emptyParam = false;
  301.         try {
  302.           param = cmdLine.handleFlagWithParam(flag, false);
  303.         }
  304.         catch (e) {
  305.           // cmdLine throws if there is no param for the flag, but we want the
  306.           // parameter to be optional, so catch the exception and let ourselves
  307.           // know that things are okay. The flag existed without a param.
  308.           emptyParam = true;
  309.           cmdLine.handleFlag(flag, false);
  310.         }
  311.  
  312.         // if there was a parameter or if we had a flag and no param
  313.         if (param != null || emptyParam) {
  314.           // record the flag for handling by flag handlers
  315.           this.flags.push([flag, param]);
  316.         }
  317.       } else {
  318.         // this should really not occur, because the case should have
  319.         // been handled as a play item earlier. however, if for some reason
  320.         // it does occur, not doing the following would cause an infinite loop,
  321.         // so do it just in case.
  322.         cmdLine.removeArguments(0, 0);
  323.       }
  324.     }
  325.   },
  326.  
  327.   addItemHandler: function (aHandler) {
  328.     this.itemHandlers.push(aHandler);
  329.     // dispatch unhandled items immediatly to this handler
  330.     this.dispatchItemsToHandler(aHandler);
  331.   },
  332.  
  333.   removeItemHandler: function(aHandler) {
  334.     var index = this.itemHandlers.indexOf(aHandler);
  335.     if (index != -1) this.itemHandlers.splice(index, 1);
  336.   },
  337.  
  338.   dispatchItemsToHandler: function(aHandler) {
  339.     var count = 0;
  340.     var total = this.itemUriSpecs.length;
  341.     for (var i=0; i < this.itemUriSpecs.length; i++) {
  342.       if (aHandler.handleItem(this.itemUriSpecs[i], count++, total)) {
  343.         this.itemUriSpecs.splice(i--, 1);
  344.       }
  345.     }
  346.   },
  347.  
  348.   dispatchItems: function() {
  349.     // The last handler to get registered gets
  350.     // priority over the first ones, so that if
  351.     // there are several instances of the main window,
  352.     // the items open in the one created last.
  353.     for (var handleridx = this.itemHandlers.length-1; handleridx >= 0; handleridx--) {
  354.       this.dispatchItemsToHandler(this.itemHandlers[handleridx]);
  355.       if (this.itemUriSpecs.length == 0) break;
  356.     }
  357.   },
  358.  
  359.   addFlagHandler: function (aHandler, aFlag) {
  360.     var entry = [aHandler, aFlag];
  361.     this.flagHandlers.push(entry);
  362.     // dispatch unhandled flags immediatly to this handler
  363.     this.dispatchFlagsToHandler(entry);
  364.   },
  365.  
  366.   removeFlagHandler: function(aHandler, aFlag) {
  367.     this.flagHandlers = this.flagHandlers.filter(function(entry) {
  368.       return !(entry[0] == aHandler && entry[1] == aFlag);
  369.     });
  370.   },
  371.  
  372.   dispatchFlagsToHandler: function(aHandlerEntry) {
  373.     var handler = aHandlerEntry[0];
  374.     var flag = aHandlerEntry[1];
  375.     for (var i=0; i < this.flags.length; i++) {
  376.       if (this.flags[i][0] == flag) {
  377.         if (handler.handleFlag(this.flags[i][0], this.flags[i][1])) {
  378.           this.flags.splice(i--, 1);
  379.         }
  380.       }
  381.     }
  382.   },
  383.  
  384.   dispatchFlags: function() {
  385.     // The last handler to get registered gets
  386.     // priority over the first ones, so that if
  387.     // there are several instances of the main window,
  388.     // the flags are handled by the one created last.
  389.     for (var handleridx = this.flagHandlers.length-1; handleridx >= 0; handleridx--) {
  390.       this.dispatchFlagsToHandler(this.flagHandlers[handleridx]);
  391.       if (this.flags.length == 0) break;
  392.     }
  393.   },
  394.  
  395.   QueryInterface : function clh_QI(iid) {
  396.     if (iid.equals(Ci.nsICommandLineHandler) ||
  397.         iid.equals(Ci.sbICommandLineManager) ||
  398.         iid.equals(Ci.nsISupports))
  399.       return this;
  400.  
  401.     throw Cr.NS_ERROR_NO_INTERFACE;
  402.   }
  403. }; // sbCommandeLineHandler
  404.  
  405. /**
  406.  * /brief The module for getting the commandline handler
  407.  */
  408. const sbCommandLineHandlerModule = {
  409.   registerSelf : function (compMgr, fileSpec, location, type) {
  410.     compMgr.QueryInterface(Ci.nsIComponentRegistrar);
  411.     compMgr.registerFactoryLocation(SONGBIRD_CLH_CID,
  412.                                     SONGBIRD_CLH_CLASSNAME,
  413.                                     SONGBIRD_CLH_CONTRACTID,
  414.                                     fileSpec,
  415.                                     location,
  416.                                     type);
  417.  
  418.     var catMan = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
  419.     catMan.addCategoryEntry("command-line-handler",
  420.                             SONGBIRD_CLH_CATEGORY,
  421.                             SONGBIRD_CLH_CONTRACTID,
  422.                             true,
  423.                             true);
  424.   },
  425.  
  426.   getClassObject : function (compMgr, cid, iid) {
  427.     if (!cid.equals(SONGBIRD_CLH_CID))
  428.       throw Cr.NS_ERROR_NO_INTERFACE;
  429.  
  430.     if (!iid.equals(Ci.nsIFactory))
  431.       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  432.  
  433.     return this.mFactory;
  434.   },
  435.  
  436.   mFactory : {
  437.     createInstance : function (outer, iid) {
  438.       if (outer != null)
  439.         throw Cr.NS_ERROR_NO_AGGREGATION;
  440.       return (new sbCommandLineHandler()).QueryInterface(iid);
  441.     }
  442.   },
  443.  
  444.   unregisterSelf : function (compMgr, location, type) {
  445.     compMgr.QueryInterface(Ci.nsIComponentRegistrar);
  446.     compMgr.unregisterFactoryLocation(SONGBIRD_CLH_CID, location);
  447.  
  448.     var catMan = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
  449.     catMan.deleteCategoryEntry("command-line-handler", SONGBIRD_CLH_CATEGORY);
  450.   },
  451.  
  452.   canUnload : function (compMgr) {
  453.     return true;
  454.   },
  455.  
  456.   QueryInterface : function (iid) {
  457.     if ( !iid.equals(Ci.nsIModule) ||
  458.          !iid.equals(Ci.nsISupports) )
  459.       throw Cr.NS_ERROR_NO_INTERFACE;
  460.     return this;
  461.   }
  462.  
  463. }; // sbCommandLineHandlerModule
  464.  
  465. function NSGetModule(comMgr, fileSpec)
  466. {
  467.   return sbCommandLineHandlerModule;
  468. }
  469.