home *** CD-ROM | disk | FTP | other *** search
/ Freelog 100 / FreelogNo100-NovembreDecembre2010.iso / Multimedia / Songbird / Songbird_1.8.0-1800_windows-i686-msvc8.exe / jsmodules / AddOnUtils.jsm next >
Text File  |  2010-08-30  |  15KB  |  493 lines

  1. /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* vim: set sw=2 :miv */
  3. /*
  4. //
  5. // BEGIN SONGBIRD GPL
  6. //
  7. // This file is part of the Songbird web player.
  8. //
  9. // Copyright(c) 2005-2008 POTI, Inc.
  10. // http://songbirdnest.com
  11. //
  12. // This file may be licensed under the terms of of the
  13. // GNU General Public License Version 2 (the "GPL").
  14. //
  15. // Software distributed under the License is distributed
  16. // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
  17. // express or implied. See the GPL for the specific language
  18. // governing rights and limitations.
  19. //
  20. // You should have received a copy of the GPL along with this
  21. // program. If not, go to http://www.gnu.org/licenses/gpl.html
  22. // or write to the Free Software Foundation, Inc.,
  23. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  24. //
  25. // END SONGBIRD GPL
  26. //
  27. */
  28.  
  29. /**
  30.  * \file  AddOnUtils.jsm
  31.  * \brief Javascript source for the add-on utilities.
  32.  */
  33.  
  34. //------------------------------------------------------------------------------
  35. //
  36. // Add-on utilities configuration.
  37. //
  38. //------------------------------------------------------------------------------
  39.  
  40. EXPORTED_SYMBOLS = [ "AddOnBundleLoader" ];
  41.  
  42. //
  43. // addOnBundleURLPref           Preference with the add-on bundle URL.
  44. // addOnBundleDataLoadTimeout   Timeout in milliseconds for loading the add-on
  45. //                              bundle data.
  46. // addOnBundleCacheFileName     Add-on bundle cache file name.
  47. //
  48.  
  49. var AddOnUtilsCfg = {
  50.   addOnBundleURLPref: "songbird.url.firstrun",
  51.   addOnBundleBlacklistPref: "songbird.recommended_addons.update.blacklist",
  52.   addOnBundleDataLoadTimeout: 15000,
  53.   addOnBundleCacheFileName: "recommendedAddOnBundle.xml"
  54. };
  55.  
  56.  
  57. //------------------------------------------------------------------------------
  58. //
  59. // Add-on utilities imported services.
  60. //
  61. //------------------------------------------------------------------------------
  62.  
  63. Components.utils.import("resource://app/jsmodules/RDFHelper.jsm");
  64.  
  65.  
  66. //------------------------------------------------------------------------------
  67. //
  68. // Add-on utilities defs.
  69. //
  70. //------------------------------------------------------------------------------
  71.  
  72. const Cc = Components.classes;
  73. const Ci = Components.interfaces;
  74. const Cr = Components.results;
  75. const Cu = Components.utils;
  76.  
  77. const DEFAULT_IO_FLAGS = -1;
  78. const DEFAULT_PERMISSIONS = -1;
  79.  
  80.  
  81. //------------------------------------------------------------------------------
  82. //
  83. // Add-on bundle loader services.
  84. //
  85. //   These services may be used to load add-on bundles.
  86. //
  87. //------------------------------------------------------------------------------
  88.  
  89. /**
  90.  * Construct an add-on bundle loader object.
  91.  */
  92.  
  93. function AddOnBundleLoader()
  94. {
  95. }
  96.  
  97.  
  98. /**
  99.  * Add all currently installed add-ons to the recommended add-on black list.
  100.  */
  101.  
  102. AddOnBundleLoader.addInstalledAddOnsToBlacklist =
  103.   function AddOnBundleLoader_addInstalledAddOnsToBlacklist() {
  104.   // Get the list of installed add-ons.
  105.   var installedAddOnList = RDFHelper.help("rdf:addon-metadata",
  106.                                           "urn:songbird:addon:root",
  107.                                           RDFHelper.DEFAULT_RDF_NAMESPACES);
  108.  
  109.   // Add each installed add-on to the blacklist.
  110.   for (var i = 0; i < installedAddOnList.length; i++) {
  111.     this.addAddOnToBlacklist(installedAddOnList[i].id);
  112.   }
  113. }
  114.  
  115.  
  116. /**
  117.  * Add the add-on specified by aAddOnID to the recommended add-on black list.
  118.  *
  119.  * \param aAddOnID            ID of add-on to add to black list.
  120.  */
  121.  
  122. AddOnBundleLoader.addAddOnToBlacklist =
  123.   function AddOnBundleLoader_addAddOnToBlacklist(aAddOnID) {
  124.   // Do nothing if no ID.
  125.   if (!aAddOnID)
  126.     return;
  127.  
  128.   // Get the add-on blacklist.
  129.   var Application = Cc["@mozilla.org/fuel/application;1"]
  130.                       .getService(Ci.fuelIApplication);
  131.   var blacklist =
  132.         Application.prefs.getValue(AddOnUtilsCfg.addOnBundleBlacklistPref, "");
  133.   if (blacklist.length > 0)
  134.     blacklist = blacklist.split(",");
  135.   else
  136.     blacklist = [];
  137.  
  138.   // Do nothing if add-on is already in the blacklist.
  139.   for (var i = 0; i < blacklist.length; i++) {
  140.     if (blacklist[i] == aAddOnID)
  141.       return;
  142.   }
  143.  
  144.   // Add the add-on to the blacklist.
  145.   blacklist.push(aAddOnID);
  146.   Application.prefs.setValue(AddOnUtilsCfg.addOnBundleBlacklistPref,
  147.                              blacklist.join(","));
  148. }
  149.  
  150.  
  151. // Define the class.
  152. AddOnBundleLoader.prototype = {
  153.   // Set the constructor.
  154.   constructor: AddOnBundleLoader,
  155.  
  156.  
  157.   //
  158.   // Public object fields.
  159.   //
  160.   //   filterInstalledAddOns    Filter out from the add-on bundle the set of
  161.   //                            already installed add-ons.
  162.   //   filterBlacklistedAddOns  Filter out from the add-on bundle the set of
  163.   //                            blacklisted add-ons.
  164.   //   readFromCache            If true, read add-on bundle from cache.
  165.   //   addOnBundle              Loaded add-on bundle.
  166.   //   complete                 True if add-on bundle loading is complete.
  167.   //   result                   Result of add-on bundle loading.  A value of
  168.   //                            Cr.NS_OK indicates a successful load.
  169.   //
  170.  
  171.   filterInstalledAddOns: false,
  172.   filterBlacklistedAddOns: false,
  173.   readFromCache: false,
  174.   addOnBundle: null,
  175.   complete: false,
  176.   result: Cr.NS_OK,
  177.  
  178.  
  179.   //
  180.   // Internal object fields.
  181.   //
  182.   //   _cfg                     Configuration settings.
  183.   //   _completionCallback      Completion callback function.
  184.   //   _cancelled               True if add-on loading was cancelled.
  185.   //
  186.  
  187.   _cfg: AddOnUtilsCfg,
  188.   _completionCallback: null,
  189.   _cancelled: false,
  190.  
  191.  
  192.   //----------------------------------------------------------------------------
  193.   //
  194.   // Public services.
  195.   //
  196.   //----------------------------------------------------------------------------
  197.  
  198.   /**
  199.    * Start loading the add-on bundle.  Call the completion callback function
  200.    * specified by aCompletionCallback upon completion of the add-on bundle
  201.    * loading.
  202.    *
  203.    * \param aCompletionCallback Completion callback function.
  204.    */
  205.  
  206.   start: function AddOnBundleLoader_start(aCompletionCallback) {
  207.     this._completionCallback = aCompletionCallback;
  208.     this._loadAddOnBundle();
  209.   },
  210.  
  211.  
  212.   /**
  213.    * Cancel loading of the add-on bundle.
  214.    */
  215.  
  216.   cancel: function AddOnBundleLoader_cancel() {
  217.     //XXXeps a way should be provided to cancel the bundle loading.
  218.     // Mark add-on bundle loading as cancelled.
  219.     this._cancelled = true;
  220.  
  221.     // Clear object references.
  222.     this.addOnBundle = null;
  223.     this._completionCallback = null;
  224.   },
  225.  
  226.  
  227.   //----------------------------------------------------------------------------
  228.   //
  229.   // Add-on bundle update service sbIBundleDataListener services.
  230.   //
  231.   //----------------------------------------------------------------------------
  232.  
  233.   /**
  234.    * \brief Bundle download completion callback
  235.    * This method is called upon completion of the bundle data download
  236.    * \param bundle An interface to the bundle manager that triggered the event
  237.    * \sa onError, sbIBundle
  238.    */
  239.  
  240.   onDownloadComplete: function AddOnBundleLoader_onDownloadComplete(aBundle) {
  241.     this.complete = true;
  242.     this._loadAddOnBundle();
  243.   },
  244.  
  245.  
  246.   /**
  247.    * \brief Bundle download error callback
  248.    * This method is called upon error while downloading the bundle data
  249.    * \param bundle An interface to the bundle manager that triggered the event
  250.    * \sa onDownloadComplete, sbIBundle
  251.    */
  252.  
  253.   onError: function AddOnBundleLoader_onDownloadComplete_onError(aBundle) {
  254.     this.result = Cr.NS_ERROR_FAILURE;
  255.     this.complete = true;
  256.     this._loadAddOnBundle();
  257.   },
  258.  
  259.  
  260.   //----------------------------------------------------------------------------
  261.   //
  262.   // Internal services.
  263.   //
  264.   //----------------------------------------------------------------------------
  265.  
  266.   /**
  267.    * Load the add-on bundle.
  268.    */
  269.  
  270.   _loadAddOnBundle: function AddOnBundleLoader__loadAddOnBundle() {
  271.     // Do nothing if add-on bundle loading has been cancelled.
  272.     if (this._cancelled)
  273.       return;
  274.  
  275.     // Start loading the add-on bundle data.
  276.     if (!this.addOnBundle) {
  277.       // Set up the add-on bundle for loading.
  278.       this.addOnBundle = Cc["@songbirdnest.com/Songbird/Bundle;1"]
  279.                            .createInstance(Ci.sbIBundle);
  280.       this.addOnBundle.bundleId = "firstrun";
  281.  
  282.       // Start loading the add-on bundle data.
  283.       if (this.readFromCache)
  284.         this._readAddOnBundleFromCache();
  285.       else
  286.         this._readAddOnBundleFromServer();
  287.     }
  288.  
  289.     // Do nothing more until bundle loading is complete.
  290.     if (!this.complete)
  291.       return;
  292.  
  293.     // Post-process the add-on bundle.
  294.     if (Components.isSuccessCode(this.result)) {
  295.       // Write the add-on bundle to the add-on bundle cache file.
  296.       if (!this.readFromCache)
  297.         this._writeAddOnBundleToCache();
  298.  
  299.       // If filtering out blacklisted add-ons, remove them.
  300.       if (this.filterBlacklistedAddOns)
  301.         this._removeBlacklistedAddOns();
  302.  
  303.       // If filtering out installed add-ons, remove them.
  304.       if (this.filterInstalledAddOns)
  305.         this._removeInstalledAddOns();
  306.     }
  307.  
  308.     // Call the completion callback function.
  309.     if (this._completionCallback)
  310.       this._completionCallback(this);
  311.   },
  312.  
  313.  
  314.   /**
  315.    * Read the add-on bundle from the add-on bundle server.
  316.    */
  317.  
  318.   _readAddOnBundleFromServer:
  319.     function AddOnBundleLoader__readAddOnBundleFromServer() {
  320.     // Set the add-on bundle URL.
  321.     var Application = Cc["@mozilla.org/fuel/application;1"]
  322.                         .getService(Ci.fuelIApplication);
  323.     this.addOnBundle.bundleURL = Application.prefs.getValue
  324.                                    (this._cfg.addOnBundleURLPref,
  325.                                     "default");
  326.  
  327.     // Start loading the add-on bundle data and listen for add-on bundle events.
  328.     try {
  329.       this.addOnBundle.addBundleDataListener(this);
  330.       this.addOnBundle.retrieveBundleData
  331.                          (this._cfg.addOnBundleDataLoadTimeout);
  332.     } catch (ex) {
  333.       // Report the exception as an error.
  334.       Cu.reportError(ex);
  335.  
  336.       // Indicate that the add-on bundle loading failed.
  337.       this.result = Cr.NS_ERROR_FAILURE;
  338.       this.complete = true;
  339.     }
  340.   },
  341.  
  342.  
  343.   /**
  344.    * Read the add-on bundle from the add-on bundle cache file.
  345.    */
  346.  
  347.   _readAddOnBundleFromCache:
  348.     function AddOnBundleLoader__readAddOnBundleFromCache() {
  349.     // Get the recommended add-on bundle cache file.
  350.     var recommendedAddOnBundleFile = this._getRecommendedAddOnCacheFile();
  351.  
  352.     // Check if cache file exists.
  353.     if (!recommendedAddOnBundleFile.exists()) {
  354.       this.result = Cr.NS_ERROR_FAILURE;
  355.       this.complete = true;
  356.     }
  357.  
  358.     // Set the add-on bundle URL.
  359.     var ioService = Cc["@mozilla.org/network/io-service;1"]
  360.                       .getService(Ci.nsIIOService);
  361.     var fileURI = ioService.newFileURI(recommendedAddOnBundleFile);
  362.     this.addOnBundle.bundleURL = fileURI.spec;
  363.  
  364.     // Load the add-on bundle data.
  365.     try {
  366.       this.addOnBundle.retrieveLocalBundleData();
  367.       this.complete = true;
  368.     } catch (ex) {
  369.       // Report the exception as an error.
  370.       Cu.reportError(ex);
  371.  
  372.       // Indicate that the add-on bundle loading failed.
  373.       this.result = Cr.NS_ERROR_FAILURE;
  374.       this.complete = true;
  375.     }
  376.   },
  377.  
  378.  
  379.   /**
  380.    * Write the add-on bundle to the add-on bundle cache file.
  381.    */
  382.  
  383.   _writeAddOnBundleToCache:
  384.     function AddOnBundleLoader__writeAddOnBundleToCache() {
  385.     // Get the recommended add-on bundle cache file.
  386.     var recommendedAddOnBundleFile = this._getRecommendedAddOnCacheFile();
  387.  
  388.     // Open an output stream to the file.
  389.     var outputStream = Cc["@mozilla.org/network/file-output-stream;1"]
  390.                          .createInstance(Ci.nsIFileOutputStream);
  391.     outputStream.init(recommendedAddOnBundleFile,
  392.                       DEFAULT_IO_FLAGS,
  393.                       DEFAULT_PERMISSIONS,
  394.                       0);
  395.  
  396.     // Write the add-on bundle data to the file.
  397.     try {
  398.       outputStream.write(this.addOnBundle.bundleDataText,
  399.                          this.addOnBundle.bundleDataText.length);
  400.     } catch (ex) {
  401.       Cu.reportError(ex);
  402.     } finally {
  403.       outputStream.close();
  404.     }
  405.   },
  406.  
  407.  
  408.   /**
  409.    * Return the recommended add-on bundle cache file.
  410.    *
  411.    * \return                    Recommended add-on bundle cache file.
  412.    */
  413.  
  414.   _getRecommendedAddOnCacheFile:
  415.     function AddOnBundleLoader__getRecommendedAddOnCacheFile() {
  416.     // Get the recommended add-on bundle cache file.
  417.     var recommendedAddOnBundleFile =
  418.           Cc["@mozilla.org/file/directory_service;1"]
  419.             .getService(Ci.nsIProperties)
  420.             .get("ProfD", Ci.nsIFile);
  421.     recommendedAddOnBundleFile.append(this._cfg.addOnBundleCacheFileName);
  422.  
  423.     return recommendedAddOnBundleFile;
  424.   },
  425.  
  426.  
  427.   /**
  428.    * Remove add-ons from the loaded bundle that are already installed.
  429.    */
  430.  
  431.   _removeInstalledAddOns: function AddOnBundleLoader__removeInstalledAddOns() {
  432.     // Get the list of installed add-ons.
  433.     var installedAddOnList = RDFHelper.help("rdf:addon-metadata",
  434.                                             "urn:songbird:addon:root",
  435.                                             RDFHelper.DEFAULT_RDF_NAMESPACES);
  436.  
  437.     // Create a table of installed add-ons, indexed by add-on ID.
  438.     var installedAddOnTable = {};
  439.     for (var i = 0; i < installedAddOnList.length; i++) {
  440.       var installedAddOn = installedAddOnList[i];
  441.       installedAddOnTable[installedAddOn.id] = installedAddOn;
  442.     }
  443.  
  444.     // Remove bundle add-ons that are already installed.
  445.     var extensionCount = this.addOnBundle.bundleExtensionCount;
  446.     for (var i = extensionCount - 1; i >= 0; i--) {
  447.       // Get the bundle add-on ID.
  448.       var addOnID = this.addOnBundle.getExtensionAttribute(i, "id");
  449.  
  450.       // Remove bundle add-on if it's already installed.
  451.       if (installedAddOnTable[addOnID])
  452.         this.addOnBundle.removeExtension(i);
  453.     }
  454.   },
  455.  
  456.  
  457.   /**
  458.    * Remove add-ons from the loaded bundle that are blacklisted.
  459.    */
  460.  
  461.   _removeBlacklistedAddOns:
  462.     function AddOnBundleLoader__removeBlacklistedAddOns() {
  463.     // Get the add-on blacklist.
  464.     var Application = Cc["@mozilla.org/fuel/application;1"]
  465.                         .getService(Ci.fuelIApplication);
  466.     var blacklist =
  467.           Application.prefs.getValue(this._cfg.addOnBundleBlacklistPref, "");
  468.     if (blacklist.length > 0)
  469.       blacklist = blacklist.split(",");
  470.     else
  471.       blacklist = [];
  472.  
  473.     // Create a table of blacklisted add-ons, indexed by add-on ID.
  474.     var blacklistedAddOnTable = {};
  475.     for (var i = 0; i < blacklist.length; i++) {
  476.       var blacklistedAddOnID = blacklist[i];
  477.       blacklistedAddOnTable[blacklistedAddOnID] = true;
  478.     }
  479.  
  480.     // Remove bundle add-ons that are blacklisted.
  481.     var extensionCount = this.addOnBundle.bundleExtensionCount;
  482.     for (var i = extensionCount - 1; i >= 0; i--) {
  483.       // Get the bundle add-on ID.
  484.       var addOnID = this.addOnBundle.getExtensionAttribute(i, "id");
  485.  
  486.       // Remove bundle add-on if it's blacklisted.
  487.       if (blacklistedAddOnTable[addOnID])
  488.         this.addOnBundle.removeExtension(i);
  489.     }
  490.   }
  491. }
  492.  
  493.