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

  1. /*
  2.  *=BEGIN SONGBIRD GPL
  3.  *
  4.  * This file is part of the Songbird web player.
  5.  *
  6.  * Copyright(c) 2005-2010 POTI, Inc.
  7.  * http://www.songbirdnest.com
  8.  *
  9.  * This file may be licensed under the terms of of the
  10.  * GNU General Public License Version 2 (the ``GPL'').
  11.  *
  12.  * Software distributed under the License is distributed
  13.  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
  14.  * express or implied. See the GPL for the specific language
  15.  * governing rights and limitations.
  16.  *
  17.  * You should have received a copy of the GPL along with this
  18.  * program. If not, go to http://www.gnu.org/licenses/gpl.html
  19.  * or write to the Free Software Foundation, Inc.,
  20.  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21.  *
  22.  *=END SONGBIRD GPL
  23.  */
  24.  
  25. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  26. Components.utils.import("resource://app/jsmodules/SBJobUtils.jsm");
  27. Components.utils.import("resource://app/jsmodules/sbLocalDatabaseMigrationUtils.jsm");
  28. Components.utils.import("resource://app/jsmodules/sbProperties.jsm");
  29.  
  30. const Cc = Components.classes;
  31. const Ci = Components.interfaces;
  32. const Cr = Components.results;
  33.  
  34. const FROM_VERSION = 24;
  35. const TO_VERSION = 25;
  36.  
  37. function LOG(s) {
  38.   dump("----++++----++++sbLibraryMigration " +
  39.        FROM_VERSION + " to " + TO_VERSION + ": " +
  40.        s +
  41.        "\n----++++----++++\n");
  42. }
  43.  
  44. function sbLibraryMigration()
  45. {
  46.   SBLocalDatabaseMigrationUtils.BaseMigrationHandler.call(this);
  47.   this._errors = [];
  48. }
  49.  
  50. //-----------------------------------------------------------------------------
  51. //
  52. // sbLocalDatabaseMigration Implementation
  53. //
  54. //   Mac OS/X stores file paths using unicode normalization form D (NFD).
  55. // However, when creating an nsIFile in xulrunner 1.9.0 using
  56. // nsIFile.initWithPath, the nsIFile keeps the path in unicode normalization
  57. // form C (NFC).  When such an nsIFile is converted to a local file URL, the URL
  58. // encoding is NFC.
  59. //   xulrunner 1.9.2 changed nsIFile so that the file path is maintained using
  60. // the OS format, NFD on Mac OS/X.  In addition, in both xulrunner 1.9.0 and
  61. // 1.9.2, enumerating files with nsIFile.directoryEntries produces file paths
  62. // in the OS format, NFD on Mac OS/X.
  63. //   Thus, in Songbird 1.8.0 and earlier, importing a playlist file (e.g., M3U)
  64. // containing local files results in media items with content URLs in NFC format
  65. // since the playlist importers use nsIFile.initWithPath for local files.
  66. // However, importing via directory scan or importing playlists with Songbird
  67. // 1.9.0 and later results in media items with local file content URLs in NFD
  68. // format on Mac OS/X.
  69. //   This migration fixes local file URLs by converting them to nsIFiles and
  70. // back to URLs.  Doing so ensures that they're encoded in the native OS format
  71. // (NFD on Mac OS/X).  The migration could directly do an NFC to NFD conversion,
  72. // but converting them via nsIFile should better ensure that the final result is
  73. // correct in case other conversions are required.
  74. //   Since the content URL is copied to the origin URL when media items are
  75. // copied to a device, the origin URL property is migrated as well as the
  76. // content URL.
  77. //   The album artwork uses nsIFile.initWithPath for local artwork files (e.g.,
  78. // folder.jpg), so the primaryImageURL property needs to be migrated.
  79. //   See http://bugzilla.songbirdnest.com/show_bug.cgi?id=21568 and
  80. //   http://bugzilla.songbirdnest.com/show_bug.cgi?id=21612 for reference.
  81. //
  82. //-----------------------------------------------------------------------------
  83.  
  84. sbLibraryMigration.prototype = {
  85.   __proto__: SBLocalDatabaseMigrationUtils.BaseMigrationHandler.prototype,
  86.   classDescription: 'Songbird Migration Handler, version ' +
  87.                      FROM_VERSION + ' to ' + TO_VERSION,
  88.   classID: Components.ID("{d460596d-aa22-4bd4-ae83-e82fb5a70019}"),
  89.   contractID: SBLocalDatabaseMigrationUtils.baseHandlerContractID +
  90.               FROM_VERSION + 'to' + TO_VERSION,
  91.  
  92.   _errors: [],
  93.   _progress: 0,
  94.   _total: 0,
  95.  
  96.   fromVersion: FROM_VERSION,
  97.   toVersion: TO_VERSION,
  98.  
  99.   batchSize: 1000,
  100.  
  101.   migrate: function sbLibraryMigration_migrate(aLibrary) {
  102.     try {
  103.       // Get the platform.
  104.       var sysInfo = Cc["@mozilla.org/system-info;1"]
  105.                       .getService(Ci.nsIPropertyBag2);
  106.       var platform = sysInfo.getProperty("name");
  107.  
  108.       // Get the database GUID and location.
  109.       this._databaseGUID = aLibrary.databaseGuid;
  110.       this._databaseLocation = aLibrary.databaseLocation;
  111.  
  112.       // Convert URL property values on Mac OS/X.
  113.       if (platform == "Darwin") {
  114.         this._convertTopLevelURLPropertyValues(aLibrary, "content_url");
  115.         this._convertNonTopLevelURLPropertyValues(aLibrary,
  116.                                                   SBProperties.originURL);
  117.         this._convertNonTopLevelURLPropertyValues(aLibrary,
  118.                                                   SBProperties.primaryImageURL);
  119.       }
  120.  
  121.       // Run a query that will mark the library as migrated
  122.       var query = this.createMigrationQuery(aLibrary);
  123.       query.addQuery("commit");
  124.       query.setAsyncQuery(false);
  125.       query.execute();
  126.  
  127.       // Raise a flag indicating that this library will need all
  128.       // sort info to be recomputed.
  129.       // Normally we'd call propertyCache.invalidateSortData(), but
  130.       // at this point in startup the property cache does not exist yet.
  131.       var prefs = Cc["@mozilla.org/preferences-service;1"]
  132.                     .getService(Ci.nsIPrefBranch);
  133.       prefs.setBoolPref("songbird.propertycache." +
  134.                           this._databaseGUID + ".invalidSortData",
  135.                         true);
  136.       prefs.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
  137.     }
  138.     catch (e) {
  139.       LOG("Exception occured: " + e);
  140.       throw e;
  141.     }
  142.   },
  143.  
  144.  
  145.   /**
  146.    * Convert all local file values for the top level URL property specified by
  147.    * aPropertyName in the library specified by aLibrary.
  148.    *
  149.    * \param aLibrary            Library in which to convert property values.
  150.    * \param aPropertyName       Name of property for which to convert values.
  151.    */
  152.  
  153.   _convertTopLevelURLPropertyValues: function
  154.     sbLibraryMigration__convertTopLevelURLPropertyValues(aLibrary,
  155.                                                          aPropertyName) {
  156.     // Set up the query strings.
  157.     var selectQueryStr = <>SELECT guid, {aPropertyName} FROM media_items
  158.                              WHERE {aPropertyName} LIKE "file:%"</>;
  159.     var updatePreparedQueryStr = <>UPDATE media_items
  160.                                      SET {aPropertyName} = ?
  161.                                      WHERE guid = ?</>;
  162.  
  163.     // Convert the URL property values.
  164.     this._convertURLPropertyValues(aLibrary,
  165.                                    selectQueryStr,
  166.                                    updatePreparedQueryStr);
  167.   },
  168.  
  169.  
  170.   /**
  171.    * Convert all local file values for the non-top level URL property specified
  172.    * by aPropertyName in the library specified by aLibrary.
  173.    *
  174.    * \param aLibrary            Library in which to convert property values.
  175.    * \param aPropertyName       Name of property for which to convert values.
  176.    */
  177.  
  178.   _convertNonTopLevelURLPropertyValues: function
  179.     sbLibraryMigration__convertNonTopLevelURLPropertyValues(aLibrary,
  180.                                                             aPropertyName) {
  181.     // Get the property ID from the property name.
  182.     var propertyID = this._getPropertyID(aLibrary, aPropertyName);
  183.  
  184.     // Set up the query strings.
  185.     var selectQueryStr = <>SELECT media_item_id, obj
  186.                              FROM resource_properties
  187.                              WHERE property_id = "{propertyID}" AND
  188.                                    obj LIKE "file:%"</>;
  189.     var updatePreparedQueryStr = <>UPDATE resource_properties
  190.                                      SET obj = ?
  191.                                      WHERE media_item_id = ? AND
  192.                                            property_id = "{propertyID}"</>;
  193.  
  194.     // Convert the URL property values.
  195.     this._convertURLPropertyValues(aLibrary,
  196.                                    selectQueryStr,
  197.                                    updatePreparedQueryStr);
  198.   },
  199.  
  200.  
  201.   /**
  202.    *   Convert all local file URL property values in the library specified by
  203.    * aLibrary using the selection query string specified by aSelectionQueryStr
  204.    * and the update prepared query string specified by aUpdatePreparedQueryStr.
  205.    *   The selection query result should return an ID string (e.g., guid or
  206.    * media item ID) in column 0 and the URL property value in column 1.
  207.    *   The prepared query string should take the converted URL as parameter 0
  208.    * and the ID string as parameter 1.
  209.    *
  210.    * \param aLibrary            Library in which to convert property values.
  211.    * \param aSelectQueryStr     Item selection query string.
  212.    * \param aUpdatePreparedQueryStr
  213.    *                            Property update prepared query string.
  214.    */
  215.  
  216.   _convertURLPropertyValues: function
  217.     sbLibraryMigration__convertURLPropertyValues(aLibrary,
  218.                                                  aSelectQueryStr,
  219.                                                  aUpdatePreparedQueryStr) {
  220.     // Select the list of URL property values to update.
  221.     var query = Cc["@songbirdnest.com/Songbird/DatabaseQuery;1"]
  222.                   .createInstance(Ci.sbIDatabaseQuery);
  223.     query.databaseLocation = aLibrary.databaseLocation;
  224.     query.setDatabaseGUID(aLibrary.databaseGuid);
  225.     query.addQuery(aSelectQueryStr);
  226.     query.setAsyncQuery(false);
  227.     if (query.execute() != 0)
  228.       throw "Media item fetch failed";
  229.     var result = query.getResultObject();
  230.  
  231.     // Convert property URLs to nsIFiles and back again.
  232.     var preparedStatement;
  233.     var queryCount = 0;
  234.     query = null;
  235.     this._total = result.getRowCount();
  236.     for (this._progress = 0; this._progress < this._total; ++this._progress) {
  237.       // Get the property info.
  238.       var id = result.getRowCell(this._progress, 0);
  239.       var url = result.getRowCell(this._progress, 1);
  240.  
  241.       // Convert the URL to an nsIFile and back.  Skip property if no converted
  242.       // URL or converted URL is the same as the original.
  243.       var convertedURL = this._convertURL(url);
  244.       if (!convertedURL || (convertedURL == url))
  245.         continue;
  246.  
  247.       // Set up query to write converted URL back.
  248.       if (!query) {
  249.         query = Cc["@songbirdnest.com/Songbird/DatabaseQuery;1"]
  250.                   .createInstance(Ci.sbIDatabaseQuery);
  251.         query.databaseLocation = aLibrary.databaseLocation;
  252.         query.setDatabaseGUID(aLibrary.databaseGuid);
  253.         preparedStatement = query.prepareQuery(aUpdatePreparedQueryStr);
  254.       }
  255.       query.addPreparedStatement(preparedStatement);
  256.       query.bindStringParameter(0, convertedURL);
  257.       query.bindStringParameter(1, id);
  258.       queryCount++;
  259.  
  260.       // Execute query if batch is full.
  261.       if (queryCount >= this.batchSize) {
  262.         query.setAsyncQuery(false);
  263.         if (query.execute() != 0)
  264.           throw "Media item write failed";
  265.         query = null;
  266.         queryCount = 0;
  267.       }
  268.     }
  269.  
  270.     // Execute any remaining queries.
  271.     if (query && (queryCount > 0)) {
  272.       query.setAsyncQuery(false);
  273.       if (query.execute() != 0)
  274.         throw "Media item write failed";
  275.     }
  276.   },
  277.  
  278.  
  279.   /**
  280.    * Convert the local file URL specified by aURL to an nsIFile and back to a
  281.    * URL and return the result.
  282.    *
  283.    * \param aURL                URL to convert.
  284.    *
  285.    * \return                    Converted URL.
  286.    */
  287.  
  288.   _convertURL: function sbLibraryMigration__convertURL(aURL) {
  289.     // Get the IO service.
  290.     var ioService = Cc["@mozilla.org/network/io-service;1"]
  291.                       .getService(Ci.nsIIOService);
  292.  
  293.     // Convert the URL to an nsIFile and back.
  294.     try {
  295.       var uri = ioService.newURI(aURL, null, null);
  296.       var fileURL = uri.QueryInterface(Ci.nsIFileURL);
  297.       var convertedURL = ioService.newFileURI(fileURL.file).spec;
  298.     }
  299.     catch (e) {
  300.       LOG("URL should have been a file URL: " + aURL + ": " + e);
  301.       return null;
  302.     }
  303.  
  304.     return convertedURL;
  305.   },
  306.  
  307.  
  308.   /**
  309.    * Return the property ID for the property with the name specified by
  310.    * aPropertyName within the library specified by aLibrary.
  311.    *
  312.    * \param aLibrary            Library containing property.
  313.    * \param aPropertyName       Name of property.
  314.    *
  315.    * \return                    Property ID.
  316.    */
  317.  
  318.   _getPropertyID: function sbLibraryMigration__getPropertyID(aLibrary,
  319.                                                              aPropertyName) {
  320.     // Query for the property ID.
  321.     var query = Cc["@songbirdnest.com/Songbird/DatabaseQuery;1"]
  322.                   .createInstance(Ci.sbIDatabaseQuery);
  323.     query.databaseLocation = aLibrary.databaseLocation;
  324.     query.setDatabaseGUID(aLibrary.databaseGuid);
  325.     query.addQuery(<>SELECT property_id FROM properties
  326.                        WHERE property_name = "{aPropertyName}"</>);
  327.     query.setAsyncQuery(false);
  328.     if (query.execute() != 0)
  329.       throw "Property ID query failed";
  330.  
  331.     return query.getResultObject().getRowCell(0, 0);
  332.   },
  333.  
  334.  
  335. ///// sbIJobProgress
  336.   get status() Ci.sbIJobProgress.STATUS_RUNNING,
  337.   get blocked() false,
  338.   get progress() this._progress,
  339.   get total() this._total,
  340.   get errorCount() this._errors.length,
  341.   getErrorMessages: function sbLibraryMigration_getErrorMessages()
  342.     ArrayConverter.StringEnumerator(this._errors),
  343.   /// addJobProgressListener / removeJobProgressListener not implemented
  344. ///// sbIJobProgressCancellable
  345.   get canCancel() false,
  346.   cancel: function sbLibraryMigration_cancel()
  347.     { throw Cr.NS_ERROR_NOT_IMPLEMENTED }
  348. };
  349.  
  350. //-----------------------------------------------------------------------------
  351. // Module
  352. //-----------------------------------------------------------------------------
  353. function NSGetModule(compMgr, fileSpec) {
  354.   return XPCOMUtils.generateModule([
  355.     sbLibraryMigration
  356.   ]);
  357. }
  358.  
  359.