LCOV - app.info - dom/indexedDB/OpenDatabaseHelper.cpp

LCOV - code coverage report
| Current view: | directory - dom/indexedDB - OpenDatabaseHelper.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 964 | 364 | 37.8 %
| Date: | 2012-06-02 | Functions: | 70 | 36 | 51.4 %

           1                 : /* ***** BEGIN LICENSE BLOCK *****
           2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           3                 :  *
           4                 :  * The contents of this file are subject to the Mozilla Public License Version
           5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           6                 :  * the License. You may obtain a copy of the License at
           7                 :  * http://www.mozilla.org/MPL/
           8                 :  *
           9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          11                 :  * for the specific language governing rights and limitations under the
          12                 :  * License.
          13                 :  *
          14                 :  * The Original Code is Indexed Database.
          15                 :  *
          16                 :  * The Initial Developer of the Original Code is
          17                 :  * The Mozilla Foundation.
          18                 :  * Portions created by the Initial Developer are Copyright (C) 2010
          19                 :  * the Initial Developer. All Rights Reserved.
          20                 :  *
          21                 :  * Contributor(s):
          22                 :  *   Ben Turner <bent.mozilla@gmail.com>
          23                 :  *   Kyle Huey <me@kylehuey.com>
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : #include "OpenDatabaseHelper.h"
          40                 :
          41                 : #include "nsIFile.h"
          42                 :
          43                 : #include "mozilla/storage.h"
          44                 : #include "nsContentUtils.h"
          45                 : #include "nsEscape.h"
          46                 : #include "nsThreadUtils.h"
          47                 : #include "snappy/snappy.h"
          48                 : #include "test_quota.h"
          49                 :
          50                 : #include "IDBEvents.h"
          51                 : #include "IDBFactory.h"
          52                 : #include "IndexedDatabaseManager.h"
          53                 :
          54                 : using namespace mozilla;
          55                 : USING_INDEXEDDB_NAMESPACE
          56                 :
          57                 : namespace {
          58                 :
          59                 : // If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major
          60                 : // schema version.
          61                 : PR_STATIC_ASSERT(JS_STRUCTURED_CLONE_VERSION == 1);
          62                 :
          63                 : // Major schema version. Bump for almost everything.
          64                 : const PRUint32 kMajorSchemaVersion = 12;
          65                 :
          66                 : // Minor schema version. Should almost always be 0 (maybe bump on release
          67                 : // branches if we have to).
          68                 : const PRUint32 kMinorSchemaVersion = 0;
          69                 :
          70                 : // The schema version we store in the SQLite database is a (signed) 32-bit
          71                 : // integer. The major version is left-shifted 4 bits so the max value is
          72                 : // 0xFFFFFFF. The minor version occupies the lower 4 bits and its max is 0xF.
          73                 : PR_STATIC_ASSERT(kMajorSchemaVersion <= 0xFFFFFFF);
          74                 : PR_STATIC_ASSERT(kMajorSchemaVersion <= 0xF);
          75                 :
          76                 : inline
          77                 : PRInt32
          78               0 : MakeSchemaVersion(PRUint32 aMajorSchemaVersion,
          79                 :                   PRUint32 aMinorSchemaVersion)
          80                 : {
          81               0 :   return PRInt32((aMajorSchemaVersion << 4) + aMinorSchemaVersion);
          82                 : }
          83                 :
          84                 : const PRInt32 kSQLiteSchemaVersion = PRInt32((kMajorSchemaVersion << 4) +
          85                 :                                              kMinorSchemaVersion);
          86                 :
          87                 : inline
          88                 : PRUint32 GetMajorSchemaVersion(PRInt32 aSchemaVersion)
          89                 : {
          90                 :   return PRUint32(aSchemaVersion) >> 4;
          91                 : }
          92                 :
          93                 : inline
          94                 : PRUint32 GetMinorSchemaVersion(PRInt32 aSchemaVersion)
          95                 : {
          96                 :   return PRUint32(aSchemaVersion) & 0xF;
          97                 : }
          98                 :
          99                 : nsresult
         100              76 : GetDatabaseFilename(const nsAString& aName,
         101                 :                     nsAString& aDatabaseFilename)
         102                 : {
         103              76 :   aDatabaseFilename.AppendInt(HashString(aName));
         104                 :
         105             152 :   nsCString escapedName;
         106              76 :   if (!NS_Escape(NS_ConvertUTF16toUTF8(aName), escapedName, url_XPAlphas)) {
         107               0 :     NS_WARNING("Can't escape database name!");
         108               0 :     return NS_ERROR_UNEXPECTED;
         109                 :   }
         110                 :
         111              76 :   const char* forwardIter = escapedName.BeginReading();
         112              76 :   const char* backwardIter = escapedName.EndReading() - 1;
         113                 :
         114             152 :   nsCString substring;
         115            1127 :   while (forwardIter <= backwardIter && substring.Length() < 21) {
         116             975 :     if (substring.Length() % 2) {
         117             450 :       substring.Append(*backwardIter--);
         118                 :     }
         119                 :     else {
         120             525 :       substring.Append(*forwardIter++);
         121                 :     }
         122                 :   }
         123                 :
         124              76 :   aDatabaseFilename.Append(NS_ConvertASCIItoUTF16(substring));
         125                 :
         126              76 :   return NS_OK;
         127                 : }
         128                 :
         129                 : nsresult
         130              52 : CreateFileTables(mozIStorageConnection* aDBConn)
         131                 : {
         132                 :   // Table `file`
         133              52 :   nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         134                 :     "CREATE TABLE file ("
         135                 :       "id INTEGER PRIMARY KEY, "
         136                 :       "refcount INTEGER NOT NULL"
         137                 :     ");"
         138              52 :   ));
         139              52 :   NS_ENSURE_SUCCESS(rv, rv);
         140                 :
         141              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         142                 :     "CREATE TRIGGER object_data_insert_trigger "
         143                 :     "AFTER INSERT ON object_data "
         144                 :     "FOR EACH ROW "
         145                 :     "WHEN NEW.file_ids IS NOT NULL "
         146                 :     "BEGIN "
         147                 :       "SELECT update_refcount(NULL, NEW.file_ids); "
         148                 :     "END;"
         149              52 :   ));
         150              52 :   NS_ENSURE_SUCCESS(rv, rv);
         151                 :
         152              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         153                 :     "CREATE TRIGGER object_data_update_trigger "
         154                 :     "AFTER UPDATE OF file_ids ON object_data "
         155                 :     "FOR EACH ROW "
         156                 :     "WHEN OLD.file_ids IS NOT NULL OR NEW.file_ids IS NOT NULL "
         157                 :     "BEGIN "
         158                 :       "SELECT update_refcount(OLD.file_ids, NEW.file_ids); "
         159                 :     "END;"
         160              52 :   ));
         161              52 :   NS_ENSURE_SUCCESS(rv, rv);
         162                 :
         163              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         164                 :     "CREATE TRIGGER object_data_delete_trigger "
         165                 :     "AFTER DELETE ON object_data "
         166                 :     "FOR EACH ROW WHEN OLD.file_ids IS NOT NULL "
         167                 :     "BEGIN "
         168                 :       "SELECT update_refcount(OLD.file_ids, NULL); "
         169                 :     "END;"
         170              52 :   ));
         171              52 :   NS_ENSURE_SUCCESS(rv, rv);
         172                 :
         173              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         174                 :     "CREATE TRIGGER file_update_trigger "
         175                 :     "AFTER UPDATE ON file "
         176                 :     "FOR EACH ROW WHEN NEW.refcount = 0 "
         177                 :     "BEGIN "
         178                 :       "DELETE FROM file WHERE id = OLD.id; "
         179                 :     "END;"
         180              52 :   ));
         181              52 :   NS_ENSURE_SUCCESS(rv, rv);
         182                 :
         183              52 :   return NS_OK;
         184                 : }
         185                 :
         186                 : nsresult
         187              52 : CreateTables(mozIStorageConnection* aDBConn)
         188                 : {
         189              52 :   NS_PRECONDITION(!NS_IsMainThread(),
         190                 :                   "Creating tables on the main thread!");
         191              52 :   NS_PRECONDITION(aDBConn, "Passing a null database connection!");
         192                 :
         193                 :   // Table `database`
         194              52 :   nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         195                 :     "CREATE TABLE database ("
         196                 :       "name TEXT NOT NULL, "
         197                 :       "version INTEGER NOT NULL DEFAULT 0"
         198                 :     ");"
         199              52 :   ));
         200              52 :   NS_ENSURE_SUCCESS(rv, rv);
         201                 :
         202                 :   // Table `object_store`
         203              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         204                 :     "CREATE TABLE object_store ("
         205                 :       "id INTEGER PRIMARY KEY, "
         206                 :       "auto_increment INTEGER NOT NULL DEFAULT 0, "
         207                 :       "name TEXT NOT NULL, "
         208                 :       "key_path TEXT, "
         209                 :       "UNIQUE (name)"
         210                 :     ");"
         211              52 :   ));
         212              52 :   NS_ENSURE_SUCCESS(rv, rv);
         213                 :
         214                 :   // Table `object_data`
         215              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         216                 :     "CREATE TABLE object_data ("
         217                 :       "id INTEGER PRIMARY KEY, "
         218                 :       "object_store_id INTEGER NOT NULL, "
         219                 :       "key_value BLOB DEFAULT NULL, "
         220                 :       "file_ids TEXT, "
         221                 :       "data BLOB NOT NULL, "
         222                 :       "UNIQUE (object_store_id, key_value), "
         223                 :       "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
         224                 :         "CASCADE"
         225                 :     ");"
         226              52 :   ));
         227              52 :   NS_ENSURE_SUCCESS(rv, rv);
         228                 :
         229                 :   // Table `index`
         230              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         231                 :     "CREATE TABLE object_store_index ("
         232                 :       "id INTEGER PRIMARY KEY, "
         233                 :       "object_store_id INTEGER NOT NULL, "
         234                 :       "name TEXT NOT NULL, "
         235                 :       "key_path TEXT NOT NULL, "
         236                 :       "unique_index INTEGER NOT NULL, "
         237                 :       "multientry INTEGER NOT NULL, "
         238                 :       "UNIQUE (object_store_id, name), "
         239                 :       "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
         240                 :         "CASCADE"
         241                 :     ");"
         242              52 :   ));
         243              52 :   NS_ENSURE_SUCCESS(rv, rv);
         244                 :
         245                 :   // Table `index_data`
         246              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         247                 :     "CREATE TABLE index_data ("
         248                 :       "index_id INTEGER NOT NULL, "
         249                 :       "value BLOB NOT NULL, "
         250                 :       "object_data_key BLOB NOT NULL, "
         251                 :       "object_data_id INTEGER NOT NULL, "
         252                 :       "PRIMARY KEY (index_id, value, object_data_key), "
         253                 :       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         254                 :         "CASCADE, "
         255                 :       "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
         256                 :         "CASCADE"
         257                 :     ");"
         258              52 :   ));
         259              52 :   NS_ENSURE_SUCCESS(rv, rv);
         260                 :
         261                 :   // Need this to make cascading deletes from object_data and object_store fast.
         262              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         263                 :     "CREATE INDEX index_data_object_data_id_index "
         264                 :     "ON index_data (object_data_id);"
         265              52 :   ));
         266              52 :   NS_ENSURE_SUCCESS(rv, rv);
         267                 :
         268                 :   // Table `unique_index_data`
         269              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         270                 :     "CREATE TABLE unique_index_data ("
         271                 :       "index_id INTEGER NOT NULL, "
         272                 :       "value BLOB NOT NULL, "
         273                 :       "object_data_key BLOB NOT NULL, "
         274                 :       "object_data_id INTEGER NOT NULL, "
         275                 :       "PRIMARY KEY (index_id, value, object_data_key), "
         276                 :       "UNIQUE (index_id, value), "
         277                 :       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         278                 :         "CASCADE "
         279                 :       "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
         280                 :         "CASCADE"
         281                 :     ");"
         282              52 :   ));
         283              52 :   NS_ENSURE_SUCCESS(rv, rv);
         284                 :
         285                 :   // Need this to make cascading deletes from object_data and object_store fast.
         286              52 :   rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         287                 :     "CREATE INDEX unique_index_data_object_data_id_index "
         288                 :     "ON unique_index_data (object_data_id);"
         289              52 :   ));
         290              52 :   NS_ENSURE_SUCCESS(rv, rv);
         291                 :
         292              52 :   rv = CreateFileTables(aDBConn);
         293              52 :   NS_ENSURE_SUCCESS(rv, rv);
         294                 :
         295              52 :   rv = aDBConn->SetSchemaVersion(kSQLiteSchemaVersion);
         296              52 :   NS_ENSURE_SUCCESS(rv, rv);
         297                 :
         298              52 :   return NS_OK;
         299                 : }
         300                 :
         301                 : nsresult
         302               0 : UpgradeSchemaFrom4To5(mozIStorageConnection* aConnection)
         303                 : {
         304                 :   nsresult rv;
         305                 :
         306                 :   // All we changed is the type of the version column, so lets try to
         307                 :   // convert that to an integer, and if we fail, set it to 0.
         308               0 :   nsCOMPtr<mozIStorageStatement> stmt;
         309               0 :   rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
         310                 :     "SELECT name, version, dataVersion "
         311                 :     "FROM database"
         312               0 :   ), getter_AddRefs(stmt));
         313               0 :   NS_ENSURE_SUCCESS(rv, rv);
         314                 :
         315               0 :   nsString name;
         316                 :   PRInt32 intVersion;
         317                 :   PRInt64 dataVersion;
         318                 :
         319                 :   {
         320               0 :     mozStorageStatementScoper scoper(stmt);
         321                 :
         322                 :     bool hasResults;
         323               0 :     rv = stmt->ExecuteStep(&hasResults);
         324               0 :     NS_ENSURE_SUCCESS(rv, rv);
         325               0 :     NS_ENSURE_TRUE(hasResults, NS_ERROR_FAILURE);
         326                 :
         327               0 :     nsString version;
         328               0 :     rv = stmt->GetString(1, version);
         329               0 :     NS_ENSURE_SUCCESS(rv, rv);
         330                 :
         331               0 :     intVersion = version.ToInteger(&rv, 10);
         332               0 :     if (NS_FAILED(rv)) {
         333               0 :       intVersion = 0;
         334                 :     }
         335                 :
         336               0 :     rv = stmt->GetString(0, name);
         337               0 :     NS_ENSURE_SUCCESS(rv, rv);
         338                 :
         339               0 :     rv = stmt->GetInt64(2, &dataVersion);
         340               0 :     NS_ENSURE_SUCCESS(rv, rv);
         341                 :   }
         342                 :
         343               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         344                 :     "DROP TABLE database"
         345               0 :   ));
         346               0 :   NS_ENSURE_SUCCESS(rv, rv);
         347                 :
         348               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         349                 :     "CREATE TABLE database ("
         350                 :       "name TEXT NOT NULL, "
         351                 :       "version INTEGER NOT NULL DEFAULT 0, "
         352                 :       "dataVersion INTEGER NOT NULL"
         353                 :     ");"
         354               0 :   ));
         355               0 :   NS_ENSURE_SUCCESS(rv, rv);
         356                 :
         357               0 :   rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
         358                 :     "INSERT INTO database (name, version, dataVersion) "
         359                 :     "VALUES (:name, :version, :dataVersion)"
         360               0 :   ), getter_AddRefs(stmt));
         361               0 :   NS_ENSURE_SUCCESS(rv, rv);
         362                 :
         363                 :   {
         364               0 :     mozStorageStatementScoper scoper(stmt);
         365                 :
         366               0 :     rv = stmt->BindStringParameter(0, name);
         367               0 :     NS_ENSURE_SUCCESS(rv, rv);
         368                 :
         369               0 :     rv = stmt->BindInt32Parameter(1, intVersion);
         370               0 :     NS_ENSURE_SUCCESS(rv, rv);
         371                 :
         372               0 :     rv = stmt->BindInt64Parameter(2, dataVersion);
         373               0 :     NS_ENSURE_SUCCESS(rv, rv);
         374                 :
         375               0 :     rv = stmt->Execute();
         376               0 :     NS_ENSURE_SUCCESS(rv, rv);
         377                 :   }
         378                 :
         379               0 :   rv = aConnection->SetSchemaVersion(5);
         380               0 :   NS_ENSURE_SUCCESS(rv, rv);
         381                 :
         382               0 :   return NS_OK;
         383                 : }
         384                 :
         385                 : nsresult
         386               0 : UpgradeSchemaFrom5To6(mozIStorageConnection* aConnection)
         387                 : {
         388                 :   // First, drop all the indexes we're no longer going to use.
         389               0 :   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         390                 :     "DROP INDEX key_index;"
         391               0 :   ));
         392               0 :   NS_ENSURE_SUCCESS(rv, rv);
         393                 :
         394               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         395                 :     "DROP INDEX ai_key_index;"
         396               0 :   ));
         397               0 :   NS_ENSURE_SUCCESS(rv, rv);
         398                 :
         399               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         400                 :     "DROP INDEX value_index;"
         401               0 :   ));
         402               0 :   NS_ENSURE_SUCCESS(rv, rv);
         403                 :
         404               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         405                 :     "DROP INDEX ai_value_index;"
         406               0 :   ));
         407               0 :   NS_ENSURE_SUCCESS(rv, rv);
         408                 :
         409                 :   // Now, reorder the columns of object_data to put the blob data last. We do
         410                 :   // this by copying into a temporary table, dropping the original, then copying
         411                 :   // back into a newly created table.
         412               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         413                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
         414                 :       "id INTEGER PRIMARY KEY, "
         415                 :       "object_store_id, "
         416                 :       "key_value, "
         417                 :       "data "
         418                 :     ");"
         419               0 :   ));
         420               0 :   NS_ENSURE_SUCCESS(rv, rv);
         421                 :
         422               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         423                 :     "INSERT INTO temp_upgrade "
         424                 :       "SELECT id, object_store_id, key_value, data "
         425                 :       "FROM object_data;"
         426               0 :   ));
         427               0 :   NS_ENSURE_SUCCESS(rv, rv);
         428                 :
         429               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         430                 :     "DROP TABLE object_data;"
         431               0 :   ));
         432               0 :   NS_ENSURE_SUCCESS(rv, rv);
         433                 :
         434               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         435                 :     "CREATE TABLE object_data ("
         436                 :       "id INTEGER PRIMARY KEY, "
         437                 :       "object_store_id INTEGER NOT NULL, "
         438                 :       "key_value DEFAULT NULL, "
         439                 :       "data BLOB NOT NULL, "
         440                 :       "UNIQUE (object_store_id, key_value), "
         441                 :       "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
         442                 :         "CASCADE"
         443                 :     ");"
         444               0 :   ));
         445               0 :   NS_ENSURE_SUCCESS(rv, rv);
         446                 :
         447               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         448                 :     "INSERT INTO object_data "
         449                 :       "SELECT id, object_store_id, key_value, data "
         450                 :       "FROM temp_upgrade;"
         451               0 :   ));
         452               0 :   NS_ENSURE_SUCCESS(rv, rv);
         453                 :
         454               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         455                 :     "DROP TABLE temp_upgrade;"
         456               0 :   ));
         457               0 :   NS_ENSURE_SUCCESS(rv, rv);
         458                 :
         459                 :   // We need to add a unique constraint to our ai_object_data table. Copy all
         460                 :   // the data out of it using a temporary table as before.
         461               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         462                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
         463                 :       "id INTEGER PRIMARY KEY, "
         464                 :       "object_store_id, "
         465                 :       "data "
         466                 :     ");"
         467               0 :   ));
         468               0 :   NS_ENSURE_SUCCESS(rv, rv);
         469                 :
         470               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         471                 :     "INSERT INTO temp_upgrade "
         472                 :       "SELECT id, object_store_id, data "
         473                 :       "FROM ai_object_data;"
         474               0 :   ));
         475               0 :   NS_ENSURE_SUCCESS(rv, rv);
         476                 :
         477               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         478                 :     "DROP TABLE ai_object_data;"
         479               0 :   ));
         480               0 :   NS_ENSURE_SUCCESS(rv, rv);
         481                 :
         482               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         483                 :     "CREATE TABLE ai_object_data ("
         484                 :       "id INTEGER PRIMARY KEY AUTOINCREMENT, "
         485                 :       "object_store_id INTEGER NOT NULL, "
         486                 :       "data BLOB NOT NULL, "
         487                 :       "UNIQUE (object_store_id, id), "
         488                 :       "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
         489                 :         "CASCADE"
         490                 :     ");"
         491               0 :   ));
         492               0 :   NS_ENSURE_SUCCESS(rv, rv);
         493                 :
         494               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         495                 :     "INSERT INTO ai_object_data "
         496                 :       "SELECT id, object_store_id, data "
         497                 :       "FROM temp_upgrade;"
         498               0 :   ));
         499               0 :   NS_ENSURE_SUCCESS(rv, rv);
         500                 :
         501               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         502                 :     "DROP TABLE temp_upgrade;"
         503               0 :   ));
         504               0 :   NS_ENSURE_SUCCESS(rv, rv);
         505                 :
         506                 :   // Fix up the index_data table. We're reordering the columns as well as
         507                 :   // changing the primary key from being a simple id to being a composite.
         508               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         509                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
         510                 :       "index_id, "
         511                 :       "value, "
         512                 :       "object_data_key, "
         513                 :       "object_data_id "
         514                 :     ");"
         515               0 :   ));
         516               0 :   NS_ENSURE_SUCCESS(rv, rv);
         517                 :
         518               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         519                 :     "INSERT INTO temp_upgrade "
         520                 :       "SELECT index_id, value, object_data_key, object_data_id "
         521                 :       "FROM index_data;"
         522               0 :   ));
         523               0 :   NS_ENSURE_SUCCESS(rv, rv);
         524                 :
         525               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         526                 :     "DROP TABLE index_data;"
         527               0 :   ));
         528               0 :   NS_ENSURE_SUCCESS(rv, rv);
         529                 :
         530               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         531                 :     "CREATE TABLE index_data ("
         532                 :       "index_id INTEGER NOT NULL, "
         533                 :       "value NOT NULL, "
         534                 :       "object_data_key NOT NULL, "
         535                 :       "object_data_id INTEGER NOT NULL, "
         536                 :       "PRIMARY KEY (index_id, value, object_data_key), "
         537                 :       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         538                 :         "CASCADE, "
         539                 :       "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
         540                 :         "CASCADE"
         541                 :     ");"
         542               0 :   ));
         543               0 :   NS_ENSURE_SUCCESS(rv, rv);
         544                 :
         545               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         546                 :     "INSERT OR IGNORE INTO index_data "
         547                 :       "SELECT index_id, value, object_data_key, object_data_id "
         548                 :       "FROM temp_upgrade;"
         549               0 :   ));
         550               0 :   NS_ENSURE_SUCCESS(rv, rv);
         551                 :
         552               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         553                 :     "DROP TABLE temp_upgrade;"
         554               0 :   ));
         555               0 :   NS_ENSURE_SUCCESS(rv, rv);
         556                 :
         557               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         558                 :     "CREATE INDEX index_data_object_data_id_index "
         559                 :     "ON index_data (object_data_id);"
         560               0 :   ));
         561               0 :   NS_ENSURE_SUCCESS(rv, rv);
         562                 :
         563                 :   // Fix up the unique_index_data table. We're reordering the columns as well as
         564                 :   // changing the primary key from being a simple id to being a composite.
         565               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         566                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
         567                 :       "index_id, "
         568                 :       "value, "
         569                 :       "object_data_key, "
         570                 :       "object_data_id "
         571                 :     ");"
         572               0 :   ));
         573               0 :   NS_ENSURE_SUCCESS(rv, rv);
         574                 :
         575               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         576                 :     "INSERT INTO temp_upgrade "
         577                 :       "SELECT index_id, value, object_data_key, object_data_id "
         578                 :       "FROM unique_index_data;"
         579               0 :   ));
         580               0 :   NS_ENSURE_SUCCESS(rv, rv);
         581                 :
         582               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         583                 :     "DROP TABLE unique_index_data;"
         584               0 :   ));
         585               0 :   NS_ENSURE_SUCCESS(rv, rv);
         586                 :
         587               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         588                 :     "CREATE TABLE unique_index_data ("
         589                 :       "index_id INTEGER NOT NULL, "
         590                 :       "value NOT NULL, "
         591                 :       "object_data_key NOT NULL, "
         592                 :       "object_data_id INTEGER NOT NULL, "
         593                 :       "PRIMARY KEY (index_id, value, object_data_key), "
         594                 :       "UNIQUE (index_id, value), "
         595                 :       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         596                 :         "CASCADE "
         597                 :       "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
         598                 :         "CASCADE"
         599                 :     ");"
         600               0 :   ));
         601               0 :   NS_ENSURE_SUCCESS(rv, rv);
         602                 :
         603               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         604                 :     "INSERT INTO unique_index_data "
         605                 :       "SELECT index_id, value, object_data_key, object_data_id "
         606                 :       "FROM temp_upgrade;"
         607               0 :   ));
         608               0 :   NS_ENSURE_SUCCESS(rv, rv);
         609                 :
         610               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         611                 :     "DROP TABLE temp_upgrade;"
         612               0 :   ));
         613               0 :   NS_ENSURE_SUCCESS(rv, rv);
         614                 :
         615               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         616                 :     "CREATE INDEX unique_index_data_object_data_id_index "
         617                 :     "ON unique_index_data (object_data_id);"
         618               0 :   ));
         619               0 :   NS_ENSURE_SUCCESS(rv, rv);
         620                 :
         621                 :   // Fix up the ai_index_data table. We're reordering the columns as well as
         622                 :   // changing the primary key from being a simple id to being a composite.
         623               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         624                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
         625                 :       "index_id, "
         626                 :       "value, "
         627                 :       "ai_object_data_id "
         628                 :     ");"
         629               0 :   ));
         630               0 :   NS_ENSURE_SUCCESS(rv, rv);
         631                 :
         632               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         633                 :     "INSERT INTO temp_upgrade "
         634                 :       "SELECT index_id, value, ai_object_data_id "
         635                 :       "FROM ai_index_data;"
         636               0 :   ));
         637               0 :   NS_ENSURE_SUCCESS(rv, rv);
         638                 :
         639               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         640                 :     "DROP TABLE ai_index_data;"
         641               0 :   ));
         642               0 :   NS_ENSURE_SUCCESS(rv, rv);
         643                 :
         644               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         645                 :     "CREATE TABLE ai_index_data ("
         646                 :       "index_id INTEGER NOT NULL, "
         647                 :       "value NOT NULL, "
         648                 :       "ai_object_data_id INTEGER NOT NULL, "
         649                 :       "PRIMARY KEY (index_id, value, ai_object_data_id), "
         650                 :       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         651                 :         "CASCADE, "
         652                 :       "FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
         653                 :         "CASCADE"
         654                 :     ");"
         655               0 :   ));
         656               0 :   NS_ENSURE_SUCCESS(rv, rv);
         657                 :
         658               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         659                 :     "INSERT OR IGNORE INTO ai_index_data "
         660                 :       "SELECT index_id, value, ai_object_data_id "
         661                 :       "FROM temp_upgrade;"
         662               0 :   ));
         663               0 :   NS_ENSURE_SUCCESS(rv, rv);
         664                 :
         665               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         666                 :     "DROP TABLE temp_upgrade;"
         667               0 :   ));
         668               0 :   NS_ENSURE_SUCCESS(rv, rv);
         669                 :
         670               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         671                 :     "CREATE INDEX ai_index_data_ai_object_data_id_index "
         672                 :     "ON ai_index_data (ai_object_data_id);"
         673               0 :   ));
         674               0 :   NS_ENSURE_SUCCESS(rv, rv);
         675                 :
         676                 :   // Fix up the ai_unique_index_data table. We're reordering the columns as well
         677                 :   // as changing the primary key from being a simple id to being a composite.
         678               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         679                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
         680                 :       "index_id, "
         681                 :       "value, "
         682                 :       "ai_object_data_id "
         683                 :     ");"
         684               0 :   ));
         685               0 :   NS_ENSURE_SUCCESS(rv, rv);
         686                 :
         687               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         688                 :     "INSERT INTO temp_upgrade "
         689                 :       "SELECT index_id, value, ai_object_data_id "
         690                 :       "FROM ai_unique_index_data;"
         691               0 :   ));
         692               0 :   NS_ENSURE_SUCCESS(rv, rv);
         693                 :
         694               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         695                 :     "DROP TABLE ai_unique_index_data;"
         696               0 :   ));
         697               0 :   NS_ENSURE_SUCCESS(rv, rv);
         698                 :
         699               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         700                 :     "CREATE TABLE ai_unique_index_data ("
         701                 :       "index_id INTEGER NOT NULL, "
         702                 :       "value NOT NULL, "
         703                 :       "ai_object_data_id INTEGER NOT NULL, "
         704                 :       "UNIQUE (index_id, value), "
         705                 :       "PRIMARY KEY (index_id, value, ai_object_data_id), "
         706                 :       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
         707                 :         "CASCADE, "
         708                 :       "FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
         709                 :         "CASCADE"
         710                 :     ");"
         711               0 :   ));
         712               0 :   NS_ENSURE_SUCCESS(rv, rv);
         713                 :
         714               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         715                 :     "INSERT INTO ai_unique_index_data "
         716                 :       "SELECT index_id, value, ai_object_data_id "
         717                 :       "FROM temp_upgrade;"
         718               0 :   ));
         719               0 :   NS_ENSURE_SUCCESS(rv, rv);
         720                 :
         721               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         722                 :     "DROP TABLE temp_upgrade;"
         723               0 :   ));
         724               0 :   NS_ENSURE_SUCCESS(rv, rv);
         725                 :
         726               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         727                 :     "CREATE INDEX ai_unique_index_data_ai_object_data_id_index "
         728                 :     "ON ai_unique_index_data (ai_object_data_id);"
         729               0 :   ));
         730               0 :   NS_ENSURE_SUCCESS(rv, rv);
         731                 :
         732               0 :   rv = aConnection->SetSchemaVersion(6);
         733               0 :   NS_ENSURE_SUCCESS(rv, rv);
         734                 :
         735               0 :   return NS_OK;
         736                 : }
         737                 :
         738                 : nsresult
         739               0 : UpgradeSchemaFrom6To7(mozIStorageConnection* aConnection)
         740                 : {
         741               0 :   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         742                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
         743                 :       "id, "
         744                 :       "name, "
         745                 :       "key_path, "
         746                 :       "auto_increment"
         747                 :     ");"
         748               0 :   ));
         749               0 :   NS_ENSURE_SUCCESS(rv, rv);
         750                 :
         751               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         752                 :     "INSERT INTO temp_upgrade "
         753                 :       "SELECT id, name, key_path, auto_increment "
         754                 :       "FROM object_store;"
         755               0 :   ));
         756               0 :   NS_ENSURE_SUCCESS(rv, rv);
         757                 :
         758               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         759                 :     "DROP TABLE object_store;"
         760               0 :   ));
         761               0 :   NS_ENSURE_SUCCESS(rv, rv);
         762                 :
         763               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         764                 :     "CREATE TABLE object_store ("
         765                 :       "id INTEGER PRIMARY KEY, "
         766                 :       "auto_increment INTEGER NOT NULL DEFAULT 0, "
         767                 :       "name TEXT NOT NULL, "
         768                 :       "key_path TEXT, "
         769                 :       "UNIQUE (name)"
         770                 :     ");"
         771               0 :   ));
         772               0 :   NS_ENSURE_SUCCESS(rv, rv);
         773                 :
         774               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         775                 :     "INSERT INTO object_store "
         776                 :       "SELECT id, auto_increment, name, nullif(key_path, '') "
         777                 :       "FROM temp_upgrade;"
         778               0 :   ));
         779               0 :   NS_ENSURE_SUCCESS(rv, rv);
         780                 :
         781               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         782                 :     "DROP TABLE temp_upgrade;"
         783               0 :   ));
         784               0 :   NS_ENSURE_SUCCESS(rv, rv);
         785                 :
         786               0 :   rv = aConnection->SetSchemaVersion(7);
         787               0 :   NS_ENSURE_SUCCESS(rv, rv);
         788                 :
         789               0 :   return NS_OK;
         790                 : }
         791                 :
         792                 : nsresult
         793               0 : UpgradeSchemaFrom7To8(mozIStorageConnection* aConnection)
         794                 : {
         795               0 :   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         796                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
         797                 :       "id, "
         798                 :       "object_store_id, "
         799                 :       "name, "
         800                 :       "key_path, "
         801                 :       "unique_index, "
         802                 :       "object_store_autoincrement"
         803                 :     ");"
         804               0 :   ));
         805               0 :   NS_ENSURE_SUCCESS(rv, rv);
         806                 :
         807               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         808                 :     "INSERT INTO temp_upgrade "
         809                 :       "SELECT id, object_store_id, name, key_path, "
         810                 :       "unique_index, object_store_autoincrement "
         811                 :       "FROM object_store_index;"
         812               0 :   ));
         813               0 :   NS_ENSURE_SUCCESS(rv, rv);
         814                 :
         815               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         816                 :     "DROP TABLE object_store_index;"
         817               0 :   ));
         818               0 :   NS_ENSURE_SUCCESS(rv, rv);
         819                 :
         820               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         821                 :     "CREATE TABLE object_store_index ("
         822                 :       "id INTEGER, "
         823                 :       "object_store_id INTEGER NOT NULL, "
         824                 :       "name TEXT NOT NULL, "
         825                 :       "key_path TEXT NOT NULL, "
         826                 :       "unique_index INTEGER NOT NULL, "
         827                 :       "multientry INTEGER NOT NULL, "
         828                 :       "object_store_autoincrement INTERGER NOT NULL, "
         829                 :       "PRIMARY KEY (id), "
         830                 :       "UNIQUE (object_store_id, name), "
         831                 :       "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
         832                 :         "CASCADE"
         833                 :     ");"
         834               0 :   ));
         835               0 :   NS_ENSURE_SUCCESS(rv, rv);
         836                 :
         837               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         838                 :     "INSERT INTO object_store_index "
         839                 :       "SELECT id, object_store_id, name, key_path, "
         840                 :       "unique_index, 0, object_store_autoincrement "
         841                 :       "FROM temp_upgrade;"
         842               0 :   ));
         843               0 :   NS_ENSURE_SUCCESS(rv, rv);
         844                 :
         845               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         846                 :     "DROP TABLE temp_upgrade;"
         847               0 :   ));
         848               0 :   NS_ENSURE_SUCCESS(rv, rv);
         849                 :
         850               0 :   rv = aConnection->SetSchemaVersion(8);
         851               0 :   NS_ENSURE_SUCCESS(rv, rv);
         852                 :
         853               0 :   return NS_OK;
         854                 : }
         855                 :
         856                 : class CompressDataBlobsFunction : public mozIStorageFunction
         857               0 : {
         858                 : public:
         859                 :   NS_DECL_ISUPPORTS
         860                 :
         861                 :   NS_IMETHOD
         862               0 :   OnFunctionCall(mozIStorageValueArray* aArguments,
         863                 :                  nsIVariant** aResult)
         864                 :   {
         865                 :     PRUint32 argc;
         866               0 :     nsresult rv = aArguments->GetNumEntries(&argc);
         867               0 :     NS_ENSURE_SUCCESS(rv, rv);
         868                 :
         869               0 :     if (argc != 1) {
         870               0 :       NS_WARNING("Don't call me with the wrong number of arguments!");
         871               0 :       return NS_ERROR_UNEXPECTED;
         872                 :     }
         873                 :
         874                 :     PRInt32 type;
         875               0 :     rv = aArguments->GetTypeOfIndex(0, &type);
         876               0 :     NS_ENSURE_SUCCESS(rv, rv);
         877                 :
         878               0 :     if (type != mozIStorageStatement::VALUE_TYPE_BLOB) {
         879               0 :       NS_WARNING("Don't call me with the wrong type of arguments!");
         880               0 :       return NS_ERROR_UNEXPECTED;
         881                 :     }
         882                 :
         883                 :     const PRUint8* uncompressed;
         884                 :     PRUint32 uncompressedLength;
         885               0 :     rv = aArguments->GetSharedBlob(0, &uncompressedLength, &uncompressed);
         886               0 :     NS_ENSURE_SUCCESS(rv, rv);
         887                 :
         888               0 :     size_t compressedLength = snappy::MaxCompressedLength(uncompressedLength);
         889               0 :     nsAutoArrayPtr<char> compressed(new char[compressedLength]);
         890                 :
         891                 :     snappy::RawCompress(reinterpret_cast<const char*>(uncompressed),
         892                 :                         uncompressedLength, compressed.get(),
         893               0 :                         &compressedLength);
         894                 :
         895               0 :     std::pair<const void *, int> data(static_cast<void*>(compressed.get()),
         896               0 :                                       int(compressedLength));
         897                 :
         898                 :     // XXX This copies the buffer again... There doesn't appear to be any way to
         899                 :     //     preallocate space and write directly to a BlobVariant at the moment.
         900               0 :     nsCOMPtr<nsIVariant> result = new mozilla::storage::BlobVariant(data);
         901                 :
         902               0 :     result.forget(aResult);
         903               0 :     return NS_OK;
         904                 :   }
         905                 : };
         906                 :
         907               0 : NS_IMPL_ISUPPORTS1(CompressDataBlobsFunction, mozIStorageFunction)
         908                 :
         909                 : nsresult
         910               0 : UpgradeSchemaFrom8To9_0(mozIStorageConnection* aConnection)
         911                 : {
         912                 :   // We no longer use the dataVersion column.
         913               0 :   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         914                 :     "UPDATE database SET dataVersion = 0;"
         915               0 :   ));
         916               0 :   NS_ENSURE_SUCCESS(rv, rv);
         917                 :
         918               0 :   nsCOMPtr<mozIStorageFunction> compressor = new CompressDataBlobsFunction();
         919                 :
         920               0 :   NS_NAMED_LITERAL_CSTRING(compressorName, "compress");
         921                 :
         922               0 :   rv = aConnection->CreateFunction(compressorName, 1, compressor);
         923               0 :   NS_ENSURE_SUCCESS(rv, rv);
         924                 :
         925                 :   // Turn off foreign key constraints before we do anything here.
         926               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         927                 :     "UPDATE object_data SET data = compress(data);"
         928               0 :   ));
         929               0 :   NS_ENSURE_SUCCESS(rv, rv);
         930                 :
         931               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         932                 :     "UPDATE ai_object_data SET data = compress(data);"
         933               0 :   ));
         934               0 :   NS_ENSURE_SUCCESS(rv, rv);
         935                 :
         936               0 :   rv = aConnection->RemoveFunction(compressorName);
         937               0 :   NS_ENSURE_SUCCESS(rv, rv);
         938                 :
         939               0 :   rv = aConnection->SetSchemaVersion(MakeSchemaVersion(9, 0));
         940               0 :   NS_ENSURE_SUCCESS(rv, rv);
         941                 :
         942               0 :   return NS_OK;
         943                 : }
         944                 :
         945                 : nsresult
         946               0 : UpgradeSchemaFrom9_0To10_0(mozIStorageConnection* aConnection)
         947                 : {
         948               0 :   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         949                 :     "ALTER TABLE object_data ADD COLUMN file_ids TEXT;"
         950               0 :   ));
         951               0 :   NS_ENSURE_SUCCESS(rv, rv);
         952                 :
         953               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         954                 :     "ALTER TABLE ai_object_data ADD COLUMN file_ids TEXT;"
         955               0 :   ));
         956               0 :   NS_ENSURE_SUCCESS(rv, rv);
         957                 :
         958               0 :   rv = CreateFileTables(aConnection);
         959               0 :   NS_ENSURE_SUCCESS(rv, rv);
         960                 :
         961               0 :   rv = aConnection->SetSchemaVersion(MakeSchemaVersion(10, 0));
         962               0 :   NS_ENSURE_SUCCESS(rv, rv);
         963                 :
         964               0 :   return NS_OK;
         965                 : }
         966                 :
         967                 : nsresult
         968               0 : UpgradeSchemaFrom10_0To11_0(mozIStorageConnection* aConnection)
         969                 : {
         970               0 :   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         971                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
         972                 :       "id, "
         973                 :       "object_store_id, "
         974                 :       "name, "
         975                 :       "key_path, "
         976                 :       "unique_index, "
         977                 :       "multientry"
         978                 :     ");"
         979               0 :   ));
         980               0 :   NS_ENSURE_SUCCESS(rv, rv);
         981                 :
         982               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         983                 :     "INSERT INTO temp_upgrade "
         984                 :       "SELECT id, object_store_id, name, key_path, "
         985                 :       "unique_index, multientry "
         986                 :       "FROM object_store_index;"
         987               0 :   ));
         988               0 :   NS_ENSURE_SUCCESS(rv, rv);
         989                 :
         990               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         991                 :     "DROP TABLE object_store_index;"
         992               0 :   ));
         993               0 :   NS_ENSURE_SUCCESS(rv, rv);
         994                 :
         995               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
         996                 :     "CREATE TABLE object_store_index ("
         997                 :       "id INTEGER PRIMARY KEY, "
         998                 :       "object_store_id INTEGER NOT NULL, "
         999                 :       "name TEXT NOT NULL, "
        1000                 :       "key_path TEXT NOT NULL, "
        1001                 :       "unique_index INTEGER NOT NULL, "
        1002                 :       "multientry INTEGER NOT NULL, "
        1003                 :       "UNIQUE (object_store_id, name), "
        1004                 :       "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
        1005                 :         "CASCADE"
        1006                 :     ");"
        1007               0 :   ));
        1008               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1009                 :
        1010               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1011                 :     "INSERT INTO object_store_index "
        1012                 :       "SELECT id, object_store_id, name, key_path, "
        1013                 :       "unique_index, multientry "
        1014                 :       "FROM temp_upgrade;"
        1015               0 :   ));
        1016               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1017                 :
        1018               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1019                 :     "DROP TABLE temp_upgrade;"
        1020               0 :   ));
        1021               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1022                 :
        1023               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1024                 :     "DROP TRIGGER object_data_insert_trigger;"
        1025               0 :   ));
        1026               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1027                 :
        1028               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1029                 :     "INSERT INTO object_data (object_store_id, key_value, data, file_ids) "
        1030                 :       "SELECT object_store_id, id, data, file_ids "
        1031                 :       "FROM ai_object_data;"
        1032               0 :   ));
        1033               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1034                 :
        1035               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1036                 :     "CREATE TRIGGER object_data_insert_trigger "
        1037                 :     "AFTER INSERT ON object_data "
        1038                 :     "FOR EACH ROW "
        1039                 :     "WHEN NEW.file_ids IS NOT NULL "
        1040                 :     "BEGIN "
        1041                 :       "SELECT update_refcount(NULL, NEW.file_ids); "
        1042                 :     "END;"
        1043               0 :   ));
        1044               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1045                 :
        1046               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1047                 :     "INSERT INTO index_data (index_id, value, object_data_key, object_data_id) "
        1048                 :       "SELECT ai_index_data.index_id, ai_index_data.value, ai_index_data.ai_object_data_id, object_data.id "
        1049                 :       "FROM ai_index_data "
        1050                 :       "INNER JOIN object_store_index ON "
        1051                 :         "object_store_index.id = ai_index_data.index_id "
        1052                 :       "INNER JOIN object_data ON "
        1053                 :         "object_data.object_store_id = object_store_index.object_store_id AND "
        1054                 :         "object_data.key_value = ai_index_data.ai_object_data_id;"
        1055               0 :   ));
        1056               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1057                 :
        1058               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1059                 :     "INSERT INTO unique_index_data (index_id, value, object_data_key, object_data_id) "
        1060                 :       "SELECT ai_unique_index_data.index_id, ai_unique_index_data.value, ai_unique_index_data.ai_object_data_id, object_data.id "
        1061                 :       "FROM ai_unique_index_data "
        1062                 :       "INNER JOIN object_store_index ON "
        1063                 :         "object_store_index.id = ai_unique_index_data.index_id "
        1064                 :       "INNER JOIN object_data ON "
        1065                 :         "object_data.object_store_id = object_store_index.object_store_id AND "
        1066                 :         "object_data.key_value = ai_unique_index_data.ai_object_data_id;"
        1067               0 :   ));
        1068               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1069                 :
        1070               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1071                 :     "UPDATE object_store "
        1072                 :       "SET auto_increment = (SELECT max(id) FROM ai_object_data) + 1 "
        1073                 :       "WHERE auto_increment;"
        1074               0 :   ));
        1075               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1076                 :
        1077               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1078                 :     "DROP TABLE ai_unique_index_data;"
        1079               0 :   ));
        1080               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1081                 :
        1082               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1083                 :     "DROP TABLE ai_index_data;"
        1084               0 :   ));
        1085               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1086                 :
        1087               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1088                 :     "DROP TABLE ai_object_data;"
        1089               0 :   ));
        1090               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1091                 :
        1092               0 :   rv = aConnection->SetSchemaVersion(MakeSchemaVersion(11, 0));
        1093               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1094                 :
        1095               0 :   return NS_OK;
        1096                 : }
        1097                 :
        1098                 : class EncodeKeysFunction : public mozIStorageFunction
        1099               0 : {
        1100                 : public:
        1101                 :   NS_DECL_ISUPPORTS
        1102                 :
        1103                 :   NS_IMETHOD
        1104               0 :   OnFunctionCall(mozIStorageValueArray* aArguments,
        1105                 :                  nsIVariant** aResult)
        1106                 :   {
        1107                 :     PRUint32 argc;
        1108               0 :     nsresult rv = aArguments->GetNumEntries(&argc);
        1109               0 :     NS_ENSURE_SUCCESS(rv, rv);
        1110                 :
        1111               0 :     if (argc != 1) {
        1112               0 :       NS_WARNING("Don't call me with the wrong number of arguments!");
        1113               0 :       return NS_ERROR_UNEXPECTED;
        1114                 :     }
        1115                 :
        1116                 :     PRInt32 type;
        1117               0 :     rv = aArguments->GetTypeOfIndex(0, &type);
        1118               0 :     NS_ENSURE_SUCCESS(rv, rv);
        1119                 :
        1120               0 :     Key key;
        1121               0 :     if (type == mozIStorageStatement::VALUE_TYPE_INTEGER) {
        1122                 :       PRInt64 intKey;
        1123               0 :       aArguments->GetInt64(0, &intKey);
        1124               0 :       key.SetFromInteger(intKey);
        1125                 :     }
        1126               0 :     else if (type == mozIStorageStatement::VALUE_TYPE_TEXT) {
        1127               0 :       nsString stringKey;
        1128               0 :       aArguments->GetString(0, stringKey);
        1129               0 :       key.SetFromString(stringKey);
        1130                 :     }
        1131                 :     else {
        1132               0 :       NS_WARNING("Don't call me with the wrong type of arguments!");
        1133               0 :       return NS_ERROR_UNEXPECTED;
        1134                 :     }
        1135                 :
        1136               0 :     const nsCString& buffer = key.GetBuffer();
        1137                 :
        1138               0 :     std::pair<const void *, int> data(static_cast<const void*>(buffer.get()),
        1139               0 :                                       int(buffer.Length()));
        1140                 :
        1141               0 :     nsCOMPtr<nsIVariant> result = new mozilla::storage::BlobVariant(data);
        1142                 :
        1143               0 :     result.forget(aResult);
        1144               0 :     return NS_OK;
        1145                 :   }
        1146                 : };
        1147                 :
        1148               0 : NS_IMPL_ISUPPORTS1(EncodeKeysFunction, mozIStorageFunction)
        1149                 :
        1150                 : nsresult
        1151               0 : UpgradeSchemaFrom11_0To12_0(mozIStorageConnection* aConnection)
        1152                 : {
        1153               0 :   NS_NAMED_LITERAL_CSTRING(encoderName, "encode");
        1154                 :
        1155               0 :   nsCOMPtr<mozIStorageFunction> encoder = new EncodeKeysFunction();
        1156                 :
        1157               0 :   nsresult rv = aConnection->CreateFunction(encoderName, 1, encoder);
        1158               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1159                 :
        1160               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1161                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
        1162                 :       "id INTEGER PRIMARY KEY, "
        1163                 :       "object_store_id, "
        1164                 :       "key_value, "
        1165                 :       "data, "
        1166                 :       "file_ids "
        1167                 :     ");"
        1168               0 :   ));
        1169               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1170                 :
        1171               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1172                 :     "INSERT INTO temp_upgrade "
        1173                 :       "SELECT id, object_store_id, encode(key_value), data, file_ids "
        1174                 :       "FROM object_data;"
        1175               0 :   ));
        1176               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1177                 :
        1178               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1179                 :     "DROP TABLE object_data;"
        1180               0 :   ));
        1181               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1182                 :
        1183               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1184                 :     "CREATE TABLE object_data ("
        1185                 :       "id INTEGER PRIMARY KEY, "
        1186                 :       "object_store_id INTEGER NOT NULL, "
        1187                 :       "key_value BLOB DEFAULT NULL, "
        1188                 :       "file_ids TEXT, "
        1189                 :       "data BLOB NOT NULL, "
        1190                 :       "UNIQUE (object_store_id, key_value), "
        1191                 :       "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
        1192                 :         "CASCADE"
        1193                 :     ");"
        1194               0 :   ));
        1195               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1196                 :
        1197               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1198                 :     "INSERT INTO object_data "
        1199                 :       "SELECT id, object_store_id, key_value, file_ids, data "
        1200                 :       "FROM temp_upgrade;"
        1201               0 :   ));
        1202               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1203                 :
        1204               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1205                 :     "DROP TABLE temp_upgrade;"
        1206               0 :   ));
        1207               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1208                 :
        1209               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1210                 :     "CREATE TRIGGER object_data_insert_trigger "
        1211                 :     "AFTER INSERT ON object_data "
        1212                 :     "FOR EACH ROW "
        1213                 :     "WHEN NEW.file_ids IS NOT NULL "
        1214                 :     "BEGIN "
        1215                 :       "SELECT update_refcount(NULL, NEW.file_ids); "
        1216                 :     "END;"
        1217               0 :   ));
        1218               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1219                 :
        1220               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1221                 :     "CREATE TRIGGER object_data_update_trigger "
        1222                 :     "AFTER UPDATE OF file_ids ON object_data "
        1223                 :     "FOR EACH ROW "
        1224                 :     "WHEN OLD.file_ids IS NOT NULL OR NEW.file_ids IS NOT NULL "
        1225                 :     "BEGIN "
        1226                 :       "SELECT update_refcount(OLD.file_ids, NEW.file_ids); "
        1227                 :     "END;"
        1228               0 :   ));
        1229               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1230                 :
        1231               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1232                 :     "CREATE TRIGGER object_data_delete_trigger "
        1233                 :     "AFTER DELETE ON object_data "
        1234                 :     "FOR EACH ROW WHEN OLD.file_ids IS NOT NULL "
        1235                 :     "BEGIN "
        1236                 :       "SELECT update_refcount(OLD.file_ids, NULL); "
        1237                 :     "END;"
        1238               0 :   ));
        1239               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1240                 :
        1241               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1242                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
        1243                 :       "index_id, "
        1244                 :       "value, "
        1245                 :       "object_data_key, "
        1246                 :       "object_data_id "
        1247                 :     ");"
        1248               0 :   ));
        1249               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1250                 :
        1251               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1252                 :     "INSERT INTO temp_upgrade "
        1253                 :       "SELECT index_id, encode(value), encode(object_data_key), object_data_id "
        1254                 :       "FROM index_data;"
        1255               0 :   ));
        1256               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1257                 :
        1258               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1259                 :     "DROP TABLE index_data;"
        1260               0 :   ));
        1261               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1262                 :
        1263               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1264                 :     "CREATE TABLE index_data ("
        1265                 :       "index_id INTEGER NOT NULL, "
        1266                 :       "value BLOB NOT NULL, "
        1267                 :       "object_data_key BLOB NOT NULL, "
        1268                 :       "object_data_id INTEGER NOT NULL, "
        1269                 :       "PRIMARY KEY (index_id, value, object_data_key), "
        1270                 :       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
        1271                 :         "CASCADE, "
        1272                 :       "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
        1273                 :         "CASCADE"
        1274                 :     ");"
        1275               0 :   ));
        1276               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1277                 :
        1278               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1279                 :     "INSERT INTO index_data "
        1280                 :       "SELECT index_id, value, object_data_key, object_data_id "
        1281                 :       "FROM temp_upgrade;"
        1282               0 :   ));
        1283               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1284                 :
        1285               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1286                 :     "DROP TABLE temp_upgrade;"
        1287               0 :   ));
        1288               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1289                 :
        1290               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1291                 :     "CREATE INDEX index_data_object_data_id_index "
        1292                 :     "ON index_data (object_data_id);"
        1293               0 :   ));
        1294               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1295                 :
        1296               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1297                 :     "CREATE TEMPORARY TABLE temp_upgrade ("
        1298                 :       "index_id, "
        1299                 :       "value, "
        1300                 :       "object_data_key, "
        1301                 :       "object_data_id "
        1302                 :     ");"
        1303               0 :   ));
        1304               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1305                 :
        1306               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1307                 :     "INSERT INTO temp_upgrade "
        1308                 :       "SELECT index_id, encode(value), encode(object_data_key), object_data_id "
        1309                 :       "FROM unique_index_data;"
        1310               0 :   ));
        1311               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1312                 :
        1313               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1314                 :     "DROP TABLE unique_index_data;"
        1315               0 :   ));
        1316               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1317                 :
        1318               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1319                 :     "CREATE TABLE unique_index_data ("
        1320                 :       "index_id INTEGER NOT NULL, "
        1321                 :       "value BLOB NOT NULL, "
        1322                 :       "object_data_key BLOB NOT NULL, "
        1323                 :       "object_data_id INTEGER NOT NULL, "
        1324                 :       "PRIMARY KEY (index_id, value, object_data_key), "
        1325                 :       "UNIQUE (index_id, value), "
        1326                 :       "FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
        1327                 :         "CASCADE "
        1328                 :       "FOREIGN KEY (object_data_id) REFERENCES object_data(id) ON DELETE "
        1329                 :         "CASCADE"
        1330                 :     ");"
        1331               0 :   ));
        1332               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1333                 :
        1334               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1335                 :     "INSERT INTO unique_index_data "
        1336                 :       "SELECT index_id, value, object_data_key, object_data_id "
        1337                 :       "FROM temp_upgrade;"
        1338               0 :   ));
        1339               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1340                 :
        1341               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1342                 :     "DROP TABLE temp_upgrade;"
        1343               0 :   ));
        1344               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1345                 :
        1346               0 :   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1347                 :     "CREATE INDEX unique_index_data_object_data_id_index "
        1348                 :     "ON unique_index_data (object_data_id);"
        1349               0 :   ));
        1350               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1351                 :
        1352               0 :   rv = aConnection->RemoveFunction(encoderName);
        1353               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1354                 :
        1355               0 :   rv = aConnection->SetSchemaVersion(MakeSchemaVersion(12, 0));
        1356               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1357                 :
        1358               0 :   return NS_OK;
        1359                 : }
        1360                 :
        1361                 : class VersionChangeEventsRunnable;
        1362                 :
        1363                 : class SetVersionHelper : public AsyncConnectionHelper,
        1364                 :                          public IDBTransactionListener
        1365             284 : {
        1366                 :   friend class VersionChangeEventsRunnable;
        1367                 : public:
        1368              71 :   SetVersionHelper(IDBTransaction* aTransaction,
        1369                 :                    IDBOpenDBRequest* aRequest,
        1370                 :                    OpenDatabaseHelper* aHelper,
        1371                 :                    PRUint64 aRequestedVersion,
        1372                 :                    PRUint64 aCurrentVersion)
        1373                 :   : AsyncConnectionHelper(aTransaction, aRequest),
        1374                 :     mOpenRequest(aRequest), mOpenHelper(aHelper),
        1375                 :     mRequestedVersion(aRequestedVersion),
        1376              71 :     mCurrentVersion(aCurrentVersion)
        1377                 :   {
        1378              71 :     mTransaction->SetTransactionListener(this);
        1379              71 :   }
        1380                 :
        1381                 :   NS_DECL_ISUPPORTS_INHERITED
        1382                 :
        1383                 :   nsresult GetSuccessResult(JSContext* aCx,
        1384                 :                             jsval* aVal);
        1385                 :
        1386                 : protected:
        1387                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
        1388                 :   nsresult Init();
        1389                 :
        1390                 :   // SetVersionHelper never fires an error event at the request.  It hands that
        1391                 :   // responsibility back to the OpenDatabaseHelper
        1392               0 :   void OnError() { }
        1393                 :
        1394                 :   // Need an upgradeneeded event here.
        1395                 :   already_AddRefed<nsDOMEvent> CreateSuccessEvent();
        1396                 :
        1397                 :   nsresult NotifyTransactionComplete(IDBTransaction* aTransaction);
        1398                 :
        1399               3 :   PRUint64 RequestedVersion() const
        1400                 :   {
        1401               3 :     return mRequestedVersion;
        1402                 :   }
        1403                 :
        1404                 : private:
        1405                 :   // In-params
        1406                 :   nsRefPtr<IDBOpenDBRequest> mOpenRequest;
        1407                 :   nsRefPtr<OpenDatabaseHelper> mOpenHelper;
        1408                 :   PRUint64 mRequestedVersion;
        1409                 :   PRUint64 mCurrentVersion;
        1410                 : };
        1411                 :
        1412                 : class DeleteDatabaseHelper : public AsyncConnectionHelper
        1413               0 : {
        1414                 :   friend class VersionChangeEventsRunnable;
        1415                 : public:
        1416               0 :   DeleteDatabaseHelper(IDBOpenDBRequest* aRequest,
        1417                 :                        OpenDatabaseHelper* aHelper,
        1418                 :                        PRUint64 aCurrentVersion,
        1419                 :                        const nsAString& aName,
        1420                 :                        const nsACString& aASCIIOrigin)
        1421                 :   : AsyncConnectionHelper(static_cast<IDBDatabase*>(nsnull), aRequest),
        1422                 :     mOpenHelper(aHelper), mOpenRequest(aRequest),
        1423                 :     mCurrentVersion(aCurrentVersion), mName(aName),
        1424               0 :     mASCIIOrigin(aASCIIOrigin)
        1425               0 :   { }
        1426                 :
        1427                 :   nsresult GetSuccessResult(JSContext* aCx,
        1428                 :                             jsval* aVal);
        1429                 :
        1430               0 :   void ReleaseMainThreadObjects()
        1431                 :   {
        1432               0 :     mOpenHelper = nsnull;
        1433               0 :     mOpenRequest = nsnull;
        1434                 :
        1435               0 :     AsyncConnectionHelper::ReleaseMainThreadObjects();
        1436               0 :   }
        1437                 :
        1438                 : protected:
        1439                 :   nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
        1440                 :   nsresult Init();
        1441                 :
        1442                 :   // DeleteDatabaseHelper never fires events at the request.  It hands that
        1443                 :   // responsibility back to the OpenDatabaseHelper
        1444               0 :   void OnError()
        1445                 :   {
        1446               0 :     mOpenHelper->NotifyDeleteFinished();
        1447               0 :   }
        1448               0 :   nsresult OnSuccess()
        1449                 :   {
        1450               0 :     return mOpenHelper->NotifyDeleteFinished();
        1451                 :   }
        1452                 :
        1453               0 :   PRUint64 RequestedVersion() const
        1454                 :   {
        1455               0 :     return 0;
        1456                 :   }
        1457                 : private:
        1458                 :   // In-params
        1459                 :   nsRefPtr<OpenDatabaseHelper> mOpenHelper;
        1460                 :   nsRefPtr<IDBOpenDBRequest> mOpenRequest;
        1461                 :   PRUint64 mCurrentVersion;
        1462                 :   nsString mName;
        1463                 :   nsCString mASCIIOrigin;
        1464                 : };
        1465                 :
        1466                 : // Responsible for firing "versionchange" events at all live and non-closed
        1467                 : // databases, and for firing a "blocked" event at the requesting database if any
        1468                 : // databases fail to close.
        1469                 : class VersionChangeEventsRunnable : public nsRunnable
        1470              12 : {
        1471                 : public:
        1472               3 :   VersionChangeEventsRunnable(
        1473                 :                             IDBDatabase* aRequestingDatabase,
        1474                 :                             IDBOpenDBRequest* aRequest,
        1475                 :                             nsTArray<nsRefPtr<IDBDatabase> >& aWaitingDatabases,
        1476                 :                             PRInt64 aOldVersion,
        1477                 :                             PRInt64 aNewVersion)
        1478                 :   : mRequestingDatabase(aRequestingDatabase),
        1479                 :     mRequest(aRequest),
        1480                 :     mOldVersion(aOldVersion),
        1481               3 :     mNewVersion(aNewVersion)
        1482                 :   {
        1483               3 :     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
        1484               3 :     NS_ASSERTION(aRequestingDatabase, "Null pointer!");
        1485               3 :     NS_ASSERTION(aRequest, "Null pointer!");
        1486                 :
        1487               3 :     if (!mWaitingDatabases.SwapElements(aWaitingDatabases)) {
        1488               0 :       NS_ERROR("This should never fail!");
        1489                 :     }
        1490               3 :   }
        1491                 :
        1492               3 :   NS_IMETHOD Run()
        1493                 :   {
        1494               3 :     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
        1495                 :
        1496                 :     // Fire version change events at all of the databases that are not already
        1497                 :     // closed. Also kick bfcached documents out of bfcache.
        1498               3 :     PRUint32 count = mWaitingDatabases.Length();
        1499               7 :     for (PRUint32 index = 0; index < count; index++) {
        1500               4 :       nsRefPtr<IDBDatabase>& database = mWaitingDatabases[index];
        1501                 :
        1502               4 :       if (database->IsClosed()) {
        1503               0 :         continue;
        1504                 :       }
        1505                 :
        1506                 :       // First check if the document the IDBDatabase is part of is bfcached.
        1507               8 :       nsCOMPtr<nsIDocument> ownerDoc = database->GetOwnerDocument();
        1508                 :       nsIBFCacheEntry* bfCacheEntry;
        1509               4 :       if (ownerDoc && (bfCacheEntry = ownerDoc->GetBFCacheEntry())) {
        1510               0 :         bfCacheEntry->RemoveFromBFCacheSync();
        1511               0 :         NS_ASSERTION(database->IsClosed(),
        1512                 :                      "Kicking doc out of bfcache should have closed database");
        1513               0 :         continue;
        1514                 :       }
        1515                 :
        1516                 :       // Otherwise fire a versionchange event.
        1517                 :       nsRefPtr<nsDOMEvent> event =
        1518               8 :         IDBVersionChangeEvent::Create(mOldVersion, mNewVersion);
        1519               4 :       NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
        1520                 :
        1521                 :       bool dummy;
        1522               8 :       database->DispatchEvent(event, &dummy);
        1523                 :     }
        1524                 :
        1525                 :     // Now check to see if any didn't close. If there are some running still
        1526                 :     // then fire the blocked event.
        1527               5 :     for (PRUint32 index = 0; index < count; index++) {
        1528               3 :       if (!mWaitingDatabases[index]->IsClosed()) {
        1529                 :         nsRefPtr<nsDOMEvent> event =
        1530               2 :           IDBVersionChangeEvent::CreateBlocked(mOldVersion, mNewVersion);
        1531               1 :         NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
        1532                 :
        1533                 :         bool dummy;
        1534               1 :         mRequest->DispatchEvent(event, &dummy);
        1535                 :
        1536               1 :         break;
        1537                 :       }
        1538                 :     }
        1539                 :
        1540               3 :     return NS_OK;
        1541                 :   }
        1542                 :
        1543                 :   template <class T>
        1544                 :   static
        1545               3 :   void QueueVersionChange(nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
        1546                 :                           void* aClosure);
        1547                 : private:
        1548                 :   nsRefPtr<IDBDatabase> mRequestingDatabase;
        1549                 :   nsRefPtr<IDBOpenDBRequest> mRequest;
        1550                 :   nsTArray<nsRefPtr<IDBDatabase> > mWaitingDatabases;
        1551                 :   PRInt64 mOldVersion;
        1552                 :   PRInt64 mNewVersion;
        1553                 : };
        1554                 :
        1555                 : } // anonymous namespace
        1556                 :
        1557            1561 : NS_IMPL_THREADSAFE_ISUPPORTS1(OpenDatabaseHelper, nsIRunnable);
        1558                 :
        1559                 : nsresult
        1560              76 : OpenDatabaseHelper::Init()
        1561                 : {
        1562             152 :   nsCString str(mASCIIOrigin);
        1563              76 :   str.Append("*");
        1564              76 :   str.Append(NS_ConvertUTF16toUTF8(mName));
        1565                 :
        1566             152 :   nsCOMPtr<nsIAtom> atom = do_GetAtom(str);
        1567              76 :   NS_ENSURE_TRUE(atom, NS_ERROR_FAILURE);
        1568                 :
        1569              76 :   atom.swap(mDatabaseId);
        1570              76 :   return NS_OK;
        1571                 : }
        1572                 :
        1573                 : nsresult
        1574              76 : OpenDatabaseHelper::Dispatch(nsIEventTarget* aTarget)
        1575                 : {
        1576              76 :   NS_ASSERTION(mState == eCreated, "We've already been dispatched?");
        1577              76 :   mState = eDBWork;
        1578                 :
        1579              76 :   return aTarget->Dispatch(this, NS_DISPATCH_NORMAL);
        1580                 : }
        1581                 :
        1582                 : nsresult
        1583               0 : OpenDatabaseHelper::RunImmediately()
        1584                 : {
        1585               0 :   NS_ASSERTION(mState == eCreated, "We've already been dispatched?");
        1586               0 :   NS_ASSERTION(NS_FAILED(mResultCode),
        1587                 :                "Should only be short-circuiting if we failed!");
        1588               0 :   NS_ASSERTION(NS_IsMainThread(), "All hell is about to break lose!");
        1589                 :
        1590               0 :   mState = eFiringEvents;
        1591               0 :   return this->Run();
        1592                 : }
        1593                 :
        1594                 : nsresult
        1595              76 : OpenDatabaseHelper::DoDatabaseWork()
        1596                 : {
        1597                 : #ifdef DEBUG
        1598                 :   {
        1599                 :     bool correctThread;
        1600              76 :     NS_ASSERTION(NS_SUCCEEDED(IndexedDatabaseManager::Get()->IOThread()->
        1601                 :                               IsOnCurrentThread(&correctThread)) &&
        1602                 :                  correctThread,
        1603                 :                  "Running on the wrong thread!");
        1604                 :   }
        1605                 : #endif
        1606                 :
        1607              76 :   mState = eFiringEvents; // In case we fail somewhere along the line.
        1608                 :
        1609              76 :   if (IndexedDatabaseManager::IsShuttingDown()) {
        1610               0 :     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
        1611                 :   }
        1612                 :
        1613              76 :   NS_ASSERTION(mOpenDBRequest, "This should never be null!");
        1614                 :
        1615                 :   // This will be null for non-window contexts.
        1616              76 :   nsPIDOMWindow* window = mOpenDBRequest->GetOwner();
        1617                 :
        1618             152 :   AutoEnterWindow autoWindow(window);
        1619                 :
        1620             152 :   nsCOMPtr<nsIFile> dbDirectory;
        1621                 :
        1622              76 :   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
        1623              76 :   NS_ASSERTION(mgr, "This should never be null!");
        1624                 :
        1625                 :   nsresult rv = mgr->EnsureOriginIsInitialized(mASCIIOrigin,
        1626              76 :                                                getter_AddRefs(dbDirectory));
        1627              76 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1628                 :
        1629             152 :   nsAutoString filename;
        1630              76 :   rv = GetDatabaseFilename(mName, filename);
        1631              76 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1632                 :
        1633             152 :   nsCOMPtr<nsIFile> dbFile;
        1634              76 :   rv = dbDirectory->Clone(getter_AddRefs(dbFile));
        1635              76 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1636                 :
        1637              76 :   rv = dbFile->Append(filename + NS_LITERAL_STRING(".sqlite"));
        1638              76 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1639                 :
        1640              76 :   rv = dbFile->GetPath(mDatabaseFilePath);
        1641              76 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1642                 :
        1643             152 :   nsCOMPtr<nsIFile> fileManagerDirectory;
        1644              76 :   rv = dbDirectory->Clone(getter_AddRefs(fileManagerDirectory));
        1645              76 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1646                 :
        1647              76 :   rv = fileManagerDirectory->Append(filename);
        1648              76 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1649                 :
        1650             152 :   nsCOMPtr<mozIStorageConnection> connection;
        1651                 :   rv = CreateDatabaseConnection(mName, dbFile, fileManagerDirectory,
        1652              76 :                                 getter_AddRefs(connection));
        1653              76 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1654                 :
        1655                 :   rv = IDBFactory::LoadDatabaseInformation(connection, mDatabaseId,
        1656              76 :                                            &mCurrentVersion, mObjectStores);
        1657              76 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1658                 :
        1659              76 :   if (mForDeletion) {
        1660               0 :     mState = eDeletePending;
        1661               0 :     return NS_OK;
        1662                 :   }
        1663                 :
        1664              99 :   for (PRUint32 i = 0; i < mObjectStores.Length(); i++) {
        1665              23 :     nsRefPtr<ObjectStoreInfo>& objectStoreInfo = mObjectStores[i];
        1666              41 :     for (PRUint32 j = 0; j < objectStoreInfo->indexes.Length(); j++) {
        1667              18 :       IndexInfo& indexInfo = objectStoreInfo->indexes[j];
        1668              18 :       mLastIndexId = NS_MAX(indexInfo.id, mLastIndexId);
        1669                 :     }
        1670              23 :     mLastObjectStoreId = NS_MAX(objectStoreInfo->id, mLastObjectStoreId);
        1671                 :   }
        1672                 :
        1673                 :   // See if we need to do a VERSION_CHANGE transaction
        1674                 :
        1675                 :   // Optional version semantics.
        1676              76 :   if (!mRequestedVersion) {
        1677                 :     // If the requested version was not specified and the database was created,
        1678                 :     // treat it as if version 1 were requested.
        1679               0 :     if (mCurrentVersion == 0) {
        1680               0 :       mRequestedVersion = 1;
        1681                 :     }
        1682                 :     else {
        1683                 :       // Otherwise, treat it as if the current version were requested.
        1684               0 :       mRequestedVersion = mCurrentVersion;
        1685                 :     }
        1686                 :   }
        1687                 :
        1688              76 :   if (mCurrentVersion > mRequestedVersion) {
        1689               1 :     return NS_ERROR_DOM_INDEXEDDB_VERSION_ERR;
        1690                 :   }
        1691                 :
        1692              75 :   if (mCurrentVersion != mRequestedVersion) {
        1693              71 :     mState = eSetVersionPending;
        1694                 :   }
        1695                 :
        1696              75 :   mFileManager = mgr->GetOrCreateFileManager(mASCIIOrigin, mName);
        1697              75 :   NS_ENSURE_TRUE(mFileManager, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1698                 :
        1699              75 :   if (!mFileManager->Inited()) {
        1700              52 :     rv = mFileManager->Init(fileManagerDirectory, connection);
        1701              52 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1702                 :   }
        1703                 :
        1704              75 :   if (!mFileManager->Loaded()) {
        1705              52 :     rv = mFileManager->Load(connection);
        1706              52 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1707                 :   }
        1708                 :
        1709              75 :   return NS_OK;
        1710                 : }
        1711                 :
        1712                 : // static
        1713                 : nsresult
        1714              76 : OpenDatabaseHelper::CreateDatabaseConnection(
        1715                 :                                         const nsAString& aName,
        1716                 :                                         nsIFile* aDBFile,
        1717                 :                                         nsIFile* aFileManagerDirectory,
        1718                 :                                         mozIStorageConnection** aConnection)
        1719                 : {
        1720              76 :   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
        1721                 :
        1722             152 :   NS_NAMED_LITERAL_CSTRING(quotaVFSName, "quota");
        1723                 :
        1724                 :   nsCOMPtr<mozIStorageServiceQuotaManagement> ss =
        1725             152 :     do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
        1726              76 :   NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE);
        1727                 :
        1728             152 :   nsCOMPtr<mozIStorageConnection> connection;
        1729              76 :   nsresult rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
        1730              76 :                                         getter_AddRefs(connection));
        1731              76 :   if (rv == NS_ERROR_FILE_CORRUPTED) {
        1732                 :     // If we're just opening the database during origin initialization, then
        1733                 :     // we don't want to erase any files. The failure here will fail origin
        1734                 :     // initialization too.
        1735               0 :     if (aName.IsVoid()) {
        1736               0 :       return rv;
        1737                 :     }
        1738                 :
        1739                 :     // Nuke the database file.  The web services can recreate their data.
        1740               0 :     rv = aDBFile->Remove(false);
        1741               0 :     NS_ENSURE_SUCCESS(rv, rv);
        1742                 :
        1743                 :     bool exists;
        1744               0 :     rv = aFileManagerDirectory->Exists(&exists);
        1745               0 :     NS_ENSURE_SUCCESS(rv, rv);
        1746                 :
        1747               0 :     if (exists) {
        1748                 :       bool isDirectory;
        1749               0 :       rv = aFileManagerDirectory->IsDirectory(&isDirectory);
        1750               0 :       NS_ENSURE_SUCCESS(rv, rv);
        1751               0 :       NS_ENSURE_TRUE(isDirectory, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1752                 :
        1753               0 :       rv = aFileManagerDirectory->Remove(true);
        1754               0 :       NS_ENSURE_SUCCESS(rv, rv);
        1755                 :     }
        1756                 :
        1757               0 :     rv = ss->OpenDatabaseWithVFS(aDBFile, quotaVFSName,
        1758               0 :                                  getter_AddRefs(connection));
        1759                 :   }
        1760              76 :   NS_ENSURE_SUCCESS(rv, rv);
        1761                 :
        1762              76 :   rv = connection->EnableModule(NS_LITERAL_CSTRING("filesystem"));
        1763              76 :   NS_ENSURE_SUCCESS(rv, rv);
        1764                 :
        1765                 :   // Check to make sure that the database schema is correct.
        1766                 :   PRInt32 schemaVersion;
        1767              76 :   rv = connection->GetSchemaVersion(&schemaVersion);
        1768              76 :   NS_ENSURE_SUCCESS(rv, rv);
        1769                 :
        1770                 :   // Unknown schema will fail origin initialization too
        1771              76 :   if (!schemaVersion && aName.IsVoid()) {
        1772               0 :     NS_WARNING("Unable to open IndexedDB database, schema is not set!");
        1773               0 :     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
        1774                 :   }
        1775                 :
        1776              76 :   if (schemaVersion > kSQLiteSchemaVersion) {
        1777               0 :     NS_WARNING("Unable to open IndexedDB database, schema is too high!");
        1778               0 :     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
        1779                 :   }
        1780                 :
        1781              76 :   bool vacuumNeeded = false;
        1782                 :
        1783              76 :   if (schemaVersion != kSQLiteSchemaVersion) {
        1784                 :     mozStorageTransaction transaction(connection, false,
        1785             104 :                                   mozIStorageConnection::TRANSACTION_IMMEDIATE);
        1786                 :
        1787              52 :     if (!schemaVersion) {
        1788                 :       // Brand new file, initialize our tables.
        1789              52 :       rv = CreateTables(connection);
        1790              52 :       NS_ENSURE_SUCCESS(rv, rv);
        1791                 :
        1792              52 :       NS_ASSERTION(NS_SUCCEEDED(connection->GetSchemaVersion(&schemaVersion)) &&
        1793                 :                    schemaVersion == kSQLiteSchemaVersion,
        1794                 :                    "CreateTables set a bad schema version!");
        1795                 :
        1796             104 :       nsCOMPtr<mozIStorageStatement> stmt;
        1797             104 :       nsresult rv = connection->CreateStatement(NS_LITERAL_CSTRING(
        1798                 :         "INSERT INTO database (name) "
        1799                 :         "VALUES (:name)"
        1800             104 :       ), getter_AddRefs(stmt));
        1801              52 :       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1802                 :
        1803              52 :       rv = stmt->BindStringByName(NS_LITERAL_CSTRING("name"), aName);
        1804              52 :       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1805                 :
        1806              52 :       rv = stmt->Execute();
        1807              52 :       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1808                 :     }
        1809                 :     else  {
        1810                 :       // This logic needs to change next time we change the schema!
        1811                 :       PR_STATIC_ASSERT(kSQLiteSchemaVersion == PRInt32((12 << 4) + 0));
        1812                 :
        1813               0 :       while (schemaVersion != kSQLiteSchemaVersion) {
        1814               0 :         if (schemaVersion == 4) {
        1815               0 :           rv = UpgradeSchemaFrom4To5(connection);
        1816                 :         }
        1817               0 :         else if (schemaVersion == 5) {
        1818               0 :           rv = UpgradeSchemaFrom5To6(connection);
        1819                 :         }
        1820               0 :         else if (schemaVersion == 6) {
        1821               0 :           rv = UpgradeSchemaFrom6To7(connection);
        1822                 :         }
        1823               0 :         else if (schemaVersion == 7) {
        1824               0 :           rv = UpgradeSchemaFrom7To8(connection);
        1825                 :         }
        1826               0 :         else if (schemaVersion == 8) {
        1827               0 :           rv = UpgradeSchemaFrom8To9_0(connection);
        1828               0 :           vacuumNeeded = true;
        1829                 :         }
        1830               0 :         else if (schemaVersion == MakeSchemaVersion(9, 0)) {
        1831               0 :           rv = UpgradeSchemaFrom9_0To10_0(connection);
        1832                 :         }
        1833               0 :         else if (schemaVersion == MakeSchemaVersion(10, 0)) {
        1834               0 :           rv = UpgradeSchemaFrom10_0To11_0(connection);
        1835                 :         }
        1836               0 :         else if (schemaVersion == MakeSchemaVersion(11, 0)) {
        1837               0 :           rv = UpgradeSchemaFrom11_0To12_0(connection);
        1838                 :         }
        1839                 :         else {
        1840                 :           NS_WARNING("Unable to open IndexedDB database, no upgrade path is "
        1841               0 :                      "available!");
        1842               0 :           return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
        1843                 :         }
        1844               0 :         NS_ENSURE_SUCCESS(rv, rv);
        1845                 :
        1846               0 :         rv = connection->GetSchemaVersion(&schemaVersion);
        1847               0 :         NS_ENSURE_SUCCESS(rv, rv);
        1848                 :       }
        1849                 :
        1850               0 :       NS_ASSERTION(schemaVersion == kSQLiteSchemaVersion, "Huh?!");
        1851                 :     }
        1852                 :
        1853              52 :     rv = transaction.Commit();
        1854              52 :     NS_ENSURE_SUCCESS(rv, rv);
        1855                 :   }
        1856                 :
        1857              76 :   if (vacuumNeeded) {
        1858               0 :     rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1859                 :       "VACUUM;"
        1860               0 :     ));
        1861               0 :     NS_ENSURE_SUCCESS(rv, rv);
        1862                 :   }
        1863                 :
        1864                 :   // Turn on foreign key constraints.
        1865             152 :   rv = connection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
        1866                 :     "PRAGMA foreign_keys = ON;"
        1867              76 :   ));
        1868              76 :   NS_ENSURE_SUCCESS(rv, rv);
        1869                 :
        1870              76 :   connection.forget(aConnection);
        1871              76 :   return NS_OK;
        1872                 : }
        1873                 :
        1874                 : nsresult
        1875              71 : OpenDatabaseHelper::StartSetVersion()
        1876                 : {
        1877              71 :   NS_ASSERTION(mState == eSetVersionPending, "Why are we here?");
        1878                 :
        1879                 :   // In case we fail, fire error events
        1880              71 :   mState = eFiringEvents;
        1881                 :
        1882              71 :   nsresult rv = EnsureSuccessResult();
        1883              71 :   NS_ENSURE_SUCCESS(rv, rv);
        1884                 :
        1885             142 :   nsTArray<nsString> storesToOpen;
        1886                 :   nsRefPtr<IDBTransaction> transaction =
        1887                 :     IDBTransaction::Create(mDatabase, storesToOpen,
        1888             142 :                            IDBTransaction::VERSION_CHANGE, true);
        1889              71 :   NS_ENSURE_TRUE(transaction, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1890                 :
        1891                 :   nsRefPtr<SetVersionHelper> helper =
        1892                 :     new SetVersionHelper(transaction, mOpenDBRequest, this, mRequestedVersion,
        1893             213 :                          mCurrentVersion);
        1894                 :
        1895              71 :   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
        1896              71 :   NS_ASSERTION(mgr, "This should never be null!");
        1897                 :
        1898                 :   rv = mgr->AcquireExclusiveAccess(mDatabase, helper,
        1899                 :             &VersionChangeEventsRunnable::QueueVersionChange<SetVersionHelper>,
        1900              71 :                                    helper);
        1901              71 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1902                 :
        1903                 :   // The SetVersionHelper is responsible for dispatching us back to the
        1904                 :   // main thread again and changing the state to eSetVersionCompleted.
        1905              71 :   mState = eSetVersionPending;
        1906                 :
        1907              71 :   return NS_OK;
        1908                 : }
        1909                 :
        1910                 : nsresult
        1911               0 : OpenDatabaseHelper::StartDelete()
        1912                 : {
        1913               0 :   NS_ASSERTION(mState == eDeletePending, "Why are we here?");
        1914                 :
        1915                 :   // In case we fail, fire error events
        1916               0 :   mState = eFiringEvents;
        1917                 :
        1918               0 :   nsresult rv = EnsureSuccessResult();
        1919               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1920                 :
        1921                 :   nsRefPtr<DeleteDatabaseHelper> helper =
        1922                 :     new DeleteDatabaseHelper(mOpenDBRequest, this, mCurrentVersion, mName,
        1923               0 :                              mASCIIOrigin);
        1924                 :
        1925               0 :   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
        1926               0 :   NS_ASSERTION(mgr, "This should never be null!");
        1927                 :
        1928                 :   rv = mgr->AcquireExclusiveAccess(mDatabase, helper,
        1929                 :         &VersionChangeEventsRunnable::QueueVersionChange<DeleteDatabaseHelper>,
        1930               0 :                                    helper);
        1931               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        1932                 :
        1933                 :   // The DeleteDatabaseHelper is responsible for dispatching us back to the
        1934                 :   // main thread again and changing the state to eDeleteCompleted.
        1935               0 :   mState = eDeletePending;
        1936               0 :   return NS_OK;
        1937                 : }
        1938                 :
        1939                 : NS_IMETHODIMP
        1940             223 : OpenDatabaseHelper::Run()
        1941                 : {
        1942             223 :   NS_ASSERTION(mState != eCreated, "Dispatch was not called?!?");
        1943                 :
        1944             223 :   if (NS_IsMainThread()) {
        1945                 :     // If we need to queue up a SetVersionHelper, do that here.
        1946             147 :     if (mState == eSetVersionPending) {
        1947              71 :       nsresult rv = StartSetVersion();
        1948                 :
        1949              71 :       if (NS_SUCCEEDED(rv)) {
        1950              71 :         return rv;
        1951                 :       }
        1952                 :
        1953               0 :       SetError(rv);
        1954                 :       // fall through and run the default error processing
        1955                 :     }
        1956              76 :     else if (mState == eDeletePending) {
        1957               0 :       nsresult rv = StartDelete();
        1958                 :
        1959               0 :       if (NS_SUCCEEDED(rv)) {
        1960               0 :         return rv;
        1961                 :       }
        1962                 :
        1963               0 :       SetError(rv);
        1964                 :       // fall through and run the default error processing
        1965                 :     }
        1966                 :
        1967                 :     // We've done whatever work we need to do on the DB thread, and any
        1968                 :     // SetVersion/DeleteDatabase stuff is done by now.
        1969              76 :     NS_ASSERTION(mState == eFiringEvents ||
        1970                 :                  mState == eSetVersionCompleted ||
        1971                 :                  mState == eDeleteCompleted, "Why are we here?");
        1972                 :
        1973              76 :     switch (mState) {
        1974                 :       case eSetVersionCompleted: {
        1975                 :         // Allow transaction creation/other version change transactions to proceed
        1976                 :         // before we fire events.  Other version changes will be postd to the end
        1977                 :         // of the event loop, and will be behind whatever the page does in
        1978                 :         // its error/success event handlers.
        1979              71 :         mDatabase->ExitSetVersionTransaction();
        1980                 :
        1981              71 :         mState = eFiringEvents;
        1982              71 :         break;
        1983                 :       }
        1984                 :
        1985                 :       case eDeleteCompleted: {
        1986                 :         // Destroy the database now (we should have the only ref).
        1987               0 :         mDatabase = nsnull;
        1988                 :
        1989               0 :         DatabaseInfo::Remove(mDatabaseId);
        1990                 :
        1991               0 :         IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
        1992               0 :         NS_ASSERTION(mgr, "This should never fail!");
        1993                 :
        1994               0 :         mgr->InvalidateFileManager(mASCIIOrigin, mName);
        1995                 :
        1996               0 :         mState = eFiringEvents;
        1997               0 :         break;
        1998                 :       }
        1999                 :
        2000                 :       case eFiringEvents: {
        2001                 :         // Notify the request that we're done, but only if we didn't just
        2002                 :         // finish a [SetVersion/DeleteDatabase]Helper.  In that case, the
        2003                 :         // helper tells the request that it is done, and we avoid calling
        2004                 :         // NotifyHelperCompleted twice.
        2005                 :
        2006               5 :         nsresult rv = mOpenDBRequest->NotifyHelperCompleted(this);
        2007               5 :         if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) {
        2008               0 :           mResultCode = rv;
        2009                 :         }
        2010               5 :         break;
        2011                 :       }
        2012                 :
        2013                 :       default:
        2014               0 :         NS_NOTREACHED("Shouldn't get here!");
        2015                 :     }
        2016                 :
        2017              76 :     NS_ASSERTION(mState == eFiringEvents, "Why are we here?");
        2018                 :
        2019              76 :     if (NS_FAILED(mResultCode)) {
        2020               2 :       DispatchErrorEvent();
        2021                 :     } else {
        2022              74 :       DispatchSuccessEvent();
        2023                 :     }
        2024                 :
        2025              76 :     IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
        2026              76 :     NS_ASSERTION(manager, "This should never be null!");
        2027                 :
        2028              76 :     manager->AllowNextSynchronizedOp(mASCIIOrigin, mDatabaseId);
        2029                 :
        2030              76 :     ReleaseMainThreadObjects();
        2031                 :
        2032              76 :     return NS_OK;
        2033                 :   }
        2034                 :
        2035                 :   // If we're on the DB thread, do that
        2036              76 :   NS_ASSERTION(mState == eDBWork, "Why are we here?");
        2037              76 :   mResultCode = DoDatabaseWork();
        2038              76 :   NS_ASSERTION(mState != eDBWork, "We should be doing something else now.");
        2039                 :
        2040              76 :   return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
        2041                 : }
        2042                 :
        2043                 : nsresult
        2044              75 : OpenDatabaseHelper::EnsureSuccessResult()
        2045                 : {
        2046             150 :   nsRefPtr<DatabaseInfo> dbInfo;
        2047              75 :   if (DatabaseInfo::Get(mDatabaseId, getter_AddRefs(dbInfo))) {
        2048                 :
        2049                 : #ifdef DEBUG
        2050                 :     {
        2051              21 :       NS_ASSERTION(dbInfo->name == mName &&
        2052                 :                    dbInfo->version == mCurrentVersion &&
        2053                 :                    dbInfo->id == mDatabaseId &&
        2054                 :                    dbInfo->filePath == mDatabaseFilePath,
        2055                 :                    "Metadata mismatch!");
        2056                 :
        2057              21 :       PRUint32 objectStoreCount = mObjectStores.Length();
        2058              43 :       for (PRUint32 index = 0; index < objectStoreCount; index++) {
        2059              22 :         nsRefPtr<ObjectStoreInfo>& info = mObjectStores[index];
        2060                 :
        2061              22 :         ObjectStoreInfo* otherInfo = dbInfo->GetObjectStore(info->name);
        2062              22 :         NS_ASSERTION(otherInfo, "ObjectStore not known!");
        2063                 :
        2064              22 :         NS_ASSERTION(info->name == otherInfo->name &&
        2065                 :                      info->id == otherInfo->id &&
        2066                 :                      info->keyPath == otherInfo->keyPath,
        2067                 :                      "Metadata mismatch!");
        2068              22 :         NS_ASSERTION(dbInfo->ContainsStoreName(info->name),
        2069                 :                      "Object store names out of date!");
        2070              22 :         NS_ASSERTION(info->indexes.Length() == otherInfo->indexes.Length(),
        2071                 :                      "Bad index length!");
        2072                 :
        2073              22 :         PRUint32 indexCount = info->indexes.Length();
        2074              40 :         for (PRUint32 indexIndex = 0; indexIndex < indexCount; indexIndex++) {
        2075              18 :           const IndexInfo& indexInfo = info->indexes[indexIndex];
        2076              18 :           const IndexInfo& otherIndexInfo = otherInfo->indexes[indexIndex];
        2077              18 :           NS_ASSERTION(indexInfo.id == otherIndexInfo.id,
        2078                 :                        "Bad index id!");
        2079              18 :           NS_ASSERTION(indexInfo.name == otherIndexInfo.name,
        2080                 :                        "Bad index name!");
        2081              18 :           NS_ASSERTION(indexInfo.keyPath == otherIndexInfo.keyPath,
        2082                 :                        "Bad index keyPath!");
        2083              18 :           NS_ASSERTION(indexInfo.unique == otherIndexInfo.unique,
        2084                 :                        "Bad index unique value!");
        2085                 :         }
        2086                 :       }
        2087                 :     }
        2088                 : #endif
        2089                 :
        2090                 :   }
        2091                 :   else {
        2092             108 :     nsRefPtr<DatabaseInfo> newInfo(new DatabaseInfo());
        2093                 :
        2094              54 :     newInfo->name = mName;
        2095              54 :     newInfo->origin = mASCIIOrigin;
        2096              54 :     newInfo->id = mDatabaseId;
        2097              54 :     newInfo->filePath = mDatabaseFilePath;
        2098                 :
        2099              54 :     if (!DatabaseInfo::Put(newInfo)) {
        2100               0 :       NS_ERROR("Failed to add to hash!");
        2101               0 :       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
        2102                 :     }
        2103                 :
        2104              54 :     newInfo.swap(dbInfo);
        2105                 :
        2106                 :     nsresult rv = IDBFactory::SetDatabaseMetadata(dbInfo, mCurrentVersion,
        2107              54 :                                                   mObjectStores);
        2108              54 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2109                 :
        2110              54 :     NS_ASSERTION(mObjectStores.IsEmpty(), "Should have swapped!");
        2111                 :   }
        2112                 :
        2113              75 :   dbInfo->nextObjectStoreId = mLastObjectStoreId + 1;
        2114              75 :   dbInfo->nextIndexId = mLastIndexId + 1;
        2115                 :
        2116                 :   nsRefPtr<IDBDatabase> database =
        2117                 :     IDBDatabase::Create(mOpenDBRequest,
        2118                 :                         dbInfo.forget(),
        2119                 :                         mASCIIOrigin,
        2120             150 :                         mFileManager);
        2121              75 :   if (!database) {
        2122               0 :     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
        2123                 :   }
        2124                 :
        2125              75 :   NS_ASSERTION(!mDatabase, "Shouldn't have a database yet!");
        2126              75 :   mDatabase.swap(database);
        2127                 :
        2128              75 :   return NS_OK;
        2129                 : }
        2130                 :
        2131                 : nsresult
        2132               4 : OpenDatabaseHelper::GetSuccessResult(JSContext* aCx,
        2133                 :                                      jsval* aVal)
        2134                 : {
        2135                 :   // Be careful not to load the database twice.
        2136               4 :   if (!mDatabase) {
        2137               4 :     nsresult rv = EnsureSuccessResult();
        2138               4 :     NS_ENSURE_SUCCESS(rv, rv);
        2139                 :   }
        2140                 :
        2141               4 :   return WrapNative(aCx, NS_ISUPPORTS_CAST(nsIDOMEventTarget*, mDatabase),
        2142               4 :                     aVal);
        2143                 : }
        2144                 :
        2145                 : nsresult
        2146              71 : OpenDatabaseHelper::NotifySetVersionFinished()
        2147                 : {
        2148              71 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread");
        2149              71 :   NS_ASSERTION(mState = eSetVersionPending, "How did we get here?");
        2150                 :
        2151              71 :   mState = eSetVersionCompleted;
        2152                 :
        2153                 :   // Dispatch ourself back to the main thread
        2154              71 :   return NS_DispatchToCurrentThread(this);
        2155                 : }
        2156                 :
        2157                 : nsresult
        2158               0 : OpenDatabaseHelper::NotifyDeleteFinished()
        2159                 : {
        2160               0 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread");
        2161               0 :   NS_ASSERTION(mState == eDeletePending, "How did we get here?");
        2162                 :
        2163               0 :   mState = eDeleteCompleted;
        2164                 :
        2165                 :   // Dispatch ourself back to the main thread
        2166               0 :   return NS_DispatchToCurrentThread(this);
        2167                 : }
        2168                 :
        2169                 : void
        2170              71 : OpenDatabaseHelper::BlockDatabase()
        2171                 : {
        2172              71 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
        2173              71 :   NS_ASSERTION(mDatabase, "This is going bad fast.");
        2174                 :
        2175              71 :   mDatabase->EnterSetVersionTransaction();
        2176              71 : }
        2177                 :
        2178                 : void
        2179              74 : OpenDatabaseHelper::DispatchSuccessEvent()
        2180                 : {
        2181                 :   nsRefPtr<nsDOMEvent> event =
        2182              74 :     CreateGenericEvent(NS_LITERAL_STRING(SUCCESS_EVT_STR),
        2183             148 :                        eDoesNotBubble, eNotCancelable);
        2184              74 :   if (!event) {
        2185               0 :     NS_ERROR("Failed to create event!");
        2186                 :     return;
        2187                 :   }
        2188                 :
        2189                 :   bool dummy;
        2190              74 :   mOpenDBRequest->DispatchEvent(event, &dummy);
        2191                 : }
        2192                 :
        2193                 : void
        2194               2 : OpenDatabaseHelper::DispatchErrorEvent()
        2195                 : {
        2196                 :   nsRefPtr<nsDOMEvent> event =
        2197               2 :     CreateGenericEvent(NS_LITERAL_STRING(ERROR_EVT_STR),
        2198               4 :                        eDoesBubble, eCancelable);
        2199               2 :   if (!event) {
        2200               0 :     NS_ERROR("Failed to create event!");
        2201                 :     return;
        2202                 :   }
        2203                 :
        2204               2 :   PRUint16 errorCode = 0;
        2205                 :   DebugOnly<nsresult> rv =
        2206               4 :     mOpenDBRequest->GetErrorCode(&errorCode);
        2207               2 :   NS_ASSERTION(NS_SUCCEEDED(rv), "This shouldn't be failing at this point!");
        2208               2 :   if (!errorCode) {
        2209               1 :     mOpenDBRequest->SetError(mResultCode);
        2210                 :   }
        2211                 :
        2212                 :   bool dummy;
        2213               2 :   mOpenDBRequest->DispatchEvent(event, &dummy);
        2214                 : }
        2215                 :
        2216                 : void
        2217              76 : OpenDatabaseHelper::ReleaseMainThreadObjects()
        2218                 : {
        2219              76 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
        2220                 :
        2221              76 :   mOpenDBRequest = nsnull;
        2222              76 :   mDatabase = nsnull;
        2223              76 :   mDatabaseId = nsnull;
        2224                 :
        2225              76 :   HelperBase::ReleaseMainThreadObjects();
        2226              76 : }
        2227                 :
        2228            2278 : NS_IMPL_ISUPPORTS_INHERITED0(SetVersionHelper, AsyncConnectionHelper);
        2229                 :
        2230                 : nsresult
        2231              71 : SetVersionHelper::Init()
        2232                 : {
        2233                 :   // Block transaction creation until we are done.
        2234              71 :   mOpenHelper->BlockDatabase();
        2235                 :
        2236              71 :   return NS_OK;
        2237                 : }
        2238                 :
        2239                 : nsresult
        2240              71 : SetVersionHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
        2241                 : {
        2242              71 :   NS_ASSERTION(aConnection, "Passing a null connection!");
        2243                 :
        2244             142 :   nsCOMPtr<mozIStorageStatement> stmt;
        2245              71 :   nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
        2246                 :     "UPDATE database "
        2247                 :     "SET version = :version"
        2248             142 :   ), getter_AddRefs(stmt));
        2249              71 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2250                 :
        2251             142 :   rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("version"),
        2252              71 :                              mRequestedVersion);
        2253              71 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2254                 :
        2255              71 :   if (NS_FAILED(stmt->Execute())) {
        2256               0 :     return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
        2257                 :   }
        2258                 :
        2259              71 :   return NS_OK;
        2260                 : }
        2261                 :
        2262                 : nsresult
        2263              71 : SetVersionHelper::GetSuccessResult(JSContext* aCx,
        2264                 :                                    jsval* aVal)
        2265                 : {
        2266              71 :   DatabaseInfo* info = mDatabase->Info();
        2267              71 :   info->version = mRequestedVersion;
        2268                 :
        2269              71 :   NS_ASSERTION(mTransaction, "Better have a transaction!");
        2270                 :
        2271              71 :   mOpenRequest->SetTransaction(mTransaction);
        2272                 :
        2273              71 :   return WrapNative(aCx, NS_ISUPPORTS_CAST(nsIDOMEventTarget*, mDatabase),
        2274              71 :                     aVal);
        2275                 : }
        2276                 :
        2277                 : // static
        2278                 : template <class T>
        2279                 : void
        2280                 : VersionChangeEventsRunnable::QueueVersionChange(
        2281                 :                                   nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
        2282                 :                                   void* aClosure)
        2283                 : {
        2284               3 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
        2285               3 :   NS_ASSERTION(!aDatabases.IsEmpty(), "Why are we here?");
        2286                 :
        2287               3 :   T* closure = static_cast<T*>(aClosure);
        2288                 :
        2289                 :   nsRefPtr<VersionChangeEventsRunnable> eventsRunnable =
        2290                 :     new VersionChangeEventsRunnable(closure->mOpenHelper->Database(),
        2291                 :                                     closure->mOpenRequest,
        2292                 :                                     aDatabases,
        2293                 :                                     closure->mCurrentVersion,
        2294               9 :                                     closure->RequestedVersion());
        2295                 :
        2296               3 :   NS_DispatchToCurrentThread(eventsRunnable);
        2297               3 : }
        2298                 :
        2299                 : already_AddRefed<nsDOMEvent>
        2300              71 : SetVersionHelper::CreateSuccessEvent()
        2301                 : {
        2302              71 :   NS_ASSERTION(mCurrentVersion < mRequestedVersion, "Huh?");
        2303                 :
        2304                 :   return IDBVersionChangeEvent::CreateUpgradeNeeded(mCurrentVersion,
        2305              71 :                                                     mRequestedVersion);
        2306                 : }
        2307                 :
        2308                 : nsresult
        2309              71 : SetVersionHelper::NotifyTransactionComplete(IDBTransaction* aTransaction)
        2310                 : {
        2311              71 :   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
        2312              71 :   NS_ASSERTION(aTransaction, "This is unexpected.");
        2313              71 :   NS_ASSERTION(mOpenRequest, "Why don't we have a request?");
        2314                 :
        2315                 :   // If we hit an error, the OpenDatabaseHelper needs to get that error too.
        2316              71 :   nsresult rv = GetResultCode();
        2317              71 :   if (NS_FAILED(rv)) {
        2318               0 :     mOpenHelper->SetError(rv);
        2319                 :   }
        2320                 :
        2321                 :   // If the transaction was aborted, we should throw an error message.
        2322              71 :   if (aTransaction->IsAborted()) {
        2323               1 :     mOpenHelper->SetError(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
        2324                 :   }
        2325                 :
        2326              71 :   mOpenRequest->SetTransaction(nsnull);
        2327              71 :   mOpenRequest = nsnull;
        2328                 :
        2329              71 :   rv = mOpenHelper->NotifySetVersionFinished();
        2330              71 :   mOpenHelper = nsnull;
        2331                 :
        2332              71 :   return rv;
        2333                 : }
        2334                 :
        2335                 : nsresult
        2336               0 : DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
        2337                 : {
        2338               0 :   NS_ASSERTION(!aConnection, "How did we get a connection here?");
        2339                 :
        2340               0 :   nsCOMPtr<nsIFile> directory;
        2341                 :   nsresult rv = IDBFactory::GetDirectoryForOrigin(mASCIIOrigin,
        2342               0 :                                                   getter_AddRefs(directory));
        2343               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2344                 :
        2345               0 :   NS_ASSERTION(directory, "What?");
        2346                 :
        2347               0 :   nsAutoString filename;
        2348               0 :   rv = GetDatabaseFilename(mName, filename);
        2349               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2350                 :
        2351               0 :   nsCOMPtr<nsIFile> dbFile;
        2352               0 :   rv = directory->Clone(getter_AddRefs(dbFile));
        2353               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2354                 :
        2355               0 :   rv = dbFile->Append(filename + NS_LITERAL_STRING(".sqlite"));
        2356               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2357                 :
        2358               0 :   bool exists = false;
        2359               0 :   rv = dbFile->Exists(&exists);
        2360               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2361                 :
        2362                 :   int rc;
        2363                 :
        2364               0 :   if (exists) {
        2365               0 :     nsString dbFilePath;
        2366               0 :     rv = dbFile->GetPath(dbFilePath);
        2367               0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2368                 :
        2369               0 :     rc = sqlite3_quota_remove(NS_ConvertUTF16toUTF8(dbFilePath).get());
        2370               0 :     if (rc != SQLITE_OK) {
        2371               0 :       NS_WARNING("Failed to delete db file!");
        2372               0 :       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
        2373                 :     }
        2374                 :   }
        2375                 :
        2376               0 :   nsCOMPtr<nsIFile> fileManagerDirectory;
        2377               0 :   rv = directory->Clone(getter_AddRefs(fileManagerDirectory));
        2378               0 :   NS_ENSURE_SUCCESS(rv, rv);
        2379                 :
        2380               0 :   rv = fileManagerDirectory->Append(filename);
        2381               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2382                 :
        2383               0 :   rv = fileManagerDirectory->Exists(&exists);
        2384               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2385                 :
        2386               0 :   if (exists) {
        2387                 :     bool isDirectory;
        2388               0 :     rv = fileManagerDirectory->IsDirectory(&isDirectory);
        2389               0 :     NS_ENSURE_SUCCESS(rv, rv);
        2390               0 :     NS_ENSURE_TRUE(isDirectory, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2391                 :
        2392               0 :     nsString fileManagerDirectoryPath;
        2393               0 :     rv = fileManagerDirectory->GetPath(fileManagerDirectoryPath);
        2394               0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
        2395                 :
        2396                 :     rc = sqlite3_quota_remove(
        2397               0 :       NS_ConvertUTF16toUTF8(fileManagerDirectoryPath).get());
        2398               0 :     if (rc != SQLITE_OK) {
        2399               0 :       NS_WARNING("Failed to delete file directory!");
        2400               0 :       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
        2401                 :     }
        2402                 :
        2403               0 :     rv = fileManagerDirectory->Remove(true);
        2404               0 :     NS_ENSURE_SUCCESS(rv, rv);
        2405                 :   }
        2406                 :
        2407               0 :   return NS_OK;
        2408                 : }
        2409                 :
        2410                 : nsresult
        2411               0 : DeleteDatabaseHelper::GetSuccessResult(JSContext* aCx, jsval* aVal)
        2412                 : {
        2413               0 :   return NS_OK;
        2414                 : }
        2415                 :
        2416                 : nsresult
        2417               0 : DeleteDatabaseHelper::Init()
        2418                 : {
        2419                 :   // Note that there's no need to block the database here, since the page
        2420                 :   // never gets to touch it, and all other databases must be closed.
        2421                 :
        2422               0 :   return NS_OK;
        2423                 : }

Generated by: LCOV version 1.7