Bug 1056939 - indexedDB.open fails for certain database names - part 2; r=bent
authorJan Varga <jan.varga@gmail.com>
Mon, 13 Oct 2014 21:12:25 +0200
changeset 210206 11b19b78962a9e1a3c3789a65a3e524606cc5f5c
parent 210205 9c6049c49c654ea0c0d0f8db4c90a8cce146f4e4
child 210207 c782a908f89c5d5a8f6c120113ca2d08bdcd2a90
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbent
bugs1056939
milestone35.0a1
Bug 1056939 - indexedDB.open fails for certain database names - part 2; r=bent
dom/indexedDB/ActorsParent.cpp
dom/indexedDB/test/unit/bug1056939.zip
dom/indexedDB/test/unit/test_bug1056939.js
dom/indexedDB/test/unit/xpcshell-head-parent-process.js
dom/indexedDB/test/unit/xpcshell-parent-process.ini
dom/quota/QuotaManager.cpp
dom/quota/QuotaManager.h
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -9151,28 +9151,28 @@ QuotaClient::NoteBackgroundThread(nsIEve
 }
 
 mozilla::dom::quota::Client::Type
 QuotaClient::GetType()
 {
   return QuotaClient::IDB;
 }
 
+struct FileManagerInitInfo
+{
+  nsCOMPtr<nsIFile> mDirectory;
+  nsCOMPtr<nsIFile> mDatabaseFile;
+};
+
 nsresult
 QuotaClient::InitOrigin(PersistenceType aPersistenceType,
                         const nsACString& aGroup,
                         const nsACString& aOrigin,
                         UsageInfo* aUsageInfo)
 {
-  struct FileManagerInitInfo
-  {
-    nsCOMPtr<nsIFile> mDirectory;
-    nsCOMPtr<nsIFile> mDatabaseFile;
-  };
-
   AssertIsOnIOThread();
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv =
     GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -9208,38 +9208,40 @@ QuotaClient::InitOrigin(PersistenceType 
     MOZ_ASSERT(file);
 
     nsString leafName;
     rv = file->GetLeafName(leafName);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    if (StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
-      continue;
-    }
-
-    if (leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
-      continue;
-    }
 
     bool isDirectory;
     rv = file->IsDirectory(&isDirectory);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (isDirectory) {
       if (!StringEndsWith(leafName, filesSuffix) ||
           !validSubdirs.GetEntry(leafName)) {
         subdirsToProcess.AppendElement(leafName);
       }
       continue;
     }
 
+    // Skip SQLite and Desktop Service Store (.DS_Store) files.
+    // Desktop Service Store file is only used on Mac OS X, but the profile
+    // can be shared across different operating systems, so we check it on
+    // all platforms.
+    if (StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal")) ||
+        leafName.EqualsLiteral(DSSTORE_FILE_NAME)) {
+      continue;
+    }
+
     nsDependentSubstring dbBaseFilename;
     if (!GetDatabaseBaseFilename(leafName, dbBaseFilename)) {
       unknownFiles.AppendElement(file);
       continue;
     }
 
     nsString fmDirectoryBaseName = dbBaseFilename + filesSuffix;
 
@@ -9277,26 +9279,24 @@ QuotaClient::InitOrigin(PersistenceType 
 
       continue;
     }
 
     // The directory didn't have the right suffix but we might need to rename
     // it. Check to see if we have a database that references this directory.
     nsString subdirNameWithSuffix = subdirName + filesSuffix;
     if (!validSubdirs.GetEntry(subdirNameWithSuffix)) {
-#ifdef XP_WIN
       // Windows doesn't allow a directory to end with a dot ('.'), so we have
       // to check that possibility here too.
+      // We do this on all platforms, because the origin directory may have
+      // been created on Windows and now accessed on different OS.
       subdirNameWithSuffix = subdirName + NS_LITERAL_STRING(".") + filesSuffix;
       if (NS_WARN_IF(!validSubdirs.GetEntry(subdirNameWithSuffix))) {
         return NS_ERROR_UNEXPECTED;
       }
-#else
-      return NS_ERROR_UNEXPECTED;
-#endif
     }
 
     // We do have a database that uses this directory so we should rename it
     // now. However, first check to make sure that we're not overwriting
     // something else.
     nsCOMPtr<nsIFile> subdir;
     rv = directory->Clone(getter_AddRefs(subdir));
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -9334,39 +9334,16 @@ QuotaClient::InitOrigin(PersistenceType 
     MOZ_ASSERT(isDirectory);
 
     rv = subdir->RenameTo(nullptr, subdirNameWithSuffix);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
-  for (uint32_t count = unknownFiles.Length(), i = 0; i < count; i++) {
-    nsCOMPtr<nsIFile>& unknownFile = unknownFiles[i];
-
-    // Some temporary SQLite files could disappear, so we have to check if the
-    // unknown file still exists.
-    bool exists;
-    rv = unknownFile->Exists(&exists);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    if (exists) {
-      nsString leafName;
-      unknownFile->GetLeafName(leafName);
-
-      // The journal file may exists even after db has been correctly opened.
-      if (NS_WARN_IF(!StringEndsWith(leafName,
-                                     NS_LITERAL_STRING(".sqlite-journal")))) {
-        return NS_ERROR_UNEXPECTED;
-      }
-    }
-  }
-
   for (uint32_t count = initInfos.Length(), i = 0; i < count; i++) {
     FileManagerInitInfo& initInfo = initInfos[i];
     MOZ_ASSERT(initInfo.mDirectory);
     MOZ_ASSERT(initInfo.mDatabaseFile);
 
     rv = FileManager::InitDirectory(initInfo.mDirectory,
                                     initInfo.mDatabaseFile,
                                     aPersistenceType,
@@ -9392,16 +9369,33 @@ QuotaClient::InitOrigin(PersistenceType 
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       aUsageInfo->AppendToFileUsage(usage);
     }
   }
 
+  // We have to do this after file manager initialization.
+  for (uint32_t count = unknownFiles.Length(), i = 0; i < count; i++) {
+    nsCOMPtr<nsIFile>& unknownFile = unknownFiles[i];
+
+    // Some temporary SQLite files could disappear during file manager
+    // initialization, so we have to check if the unknown file still exists.
+    bool exists;
+    rv = unknownFile->Exists(&exists);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    if (exists) {
+      return NS_ERROR_UNEXPECTED;
+    }
+  }
+
   return NS_OK;
 }
 
 nsresult
 QuotaClient::GetUsageForOrigin(PersistenceType aPersistenceType,
                                const nsACString& aGroup,
                                const nsACString& aOrigin,
                                UsageInfo* aUsageInfo)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..db3cfe62464e8f50d11664578c879c8af7c45014
GIT binary patch
literal 8029
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
DhVkiI
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_bug1056939.js
@@ -0,0 +1,131 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var testGenerator = testSteps();
+
+function testSteps()
+{
+  const dbName1 = "upgrade_test";
+  const dbName2 = "testing.foobar";
+  const dbName3 = "xxxxxxx.xxxxxx";
+
+  clearAllDatabases(continueToNextStepSync);
+  yield undefined;
+
+  installPackagedProfile("bug1056939");
+
+  let request = indexedDB.open(dbName1, 1);
+  request.onerror = errorHandler;
+  request.onupgradeneeded = unexpectedSuccessHandler;
+  request.onsuccess = grabEventAndContinueHandler;
+  let event = yield undefined;
+
+  is(event.type, "success", "Correct event type");
+
+  request = indexedDB.open(dbName2, 1);
+  request.onerror = errorHandler;
+  request.onupgradeneeded = unexpectedSuccessHandler;
+  request.onsuccess = grabEventAndContinueHandler;
+  event = yield undefined;
+
+  is(event.type, "success", "Got correct event type");
+
+  request = indexedDB.open(dbName3, 1);
+  request.onerror = errorHandler;
+  request.onupgradeneeded = unexpectedSuccessHandler;
+  request.onsuccess = grabEventAndContinueHandler;
+  event = yield undefined;
+
+  is(event.type, "success", "Got correct event type");
+
+  clearAllDatabases(continueToNextStepSync);
+  yield undefined;
+
+  request = indexedDB.open(dbName3, 1);
+  request.onerror = errorHandler;
+  request.onupgradeneeded = grabEventAndContinueHandler;
+  request.onsuccess = unexpectedSuccessHandler;
+  event = yield undefined;
+
+  is(event.type, "upgradeneeded", "Got correct event type");
+
+  request.onupgradeneeded = unexpectedSuccessHandler;
+  request.onsuccess = grabEventAndContinueHandler;
+  event = yield undefined;
+
+  is(event.type, "success", "Got correct event type");
+
+  resetAllDatabases(continueToNextStepSync);
+  yield undefined;
+
+  request = indexedDB.open(dbName3, 1);
+  request.onerror = errorHandler;
+  request.onupgradeneeded = unexpectedSuccessHandler;
+  request.onsuccess = grabEventAndContinueHandler;
+  event = yield undefined;
+
+  is(event.type, "success", "Got correct event type");
+
+  finishTest();
+  yield undefined;
+}
+
+function installPackagedProfile(packageName)
+{
+  let directoryService = Cc["@mozilla.org/file/directory_service;1"]
+                         .getService(Ci.nsIProperties);
+
+  let profileDir = directoryService.get("ProfD", Ci.nsIFile);
+
+  let currentDir = directoryService.get("CurWorkD", Ci.nsIFile);
+
+  let packageFile = currentDir.clone();
+  packageFile.append(packageName + ".zip");
+
+  let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
+                  .createInstance(Ci.nsIZipReader);
+  zipReader.open(packageFile);
+
+  let entryNames = [];
+  let entries = zipReader.findEntries(null);
+  while (entries.hasMore()) {
+    let entry = entries.getNext();
+    if (entry != "create_db.html") {
+      entryNames.push(entry);
+    }
+  }
+  entryNames.sort();
+
+  for (let entryName of entryNames) {
+    let zipentry = zipReader.getEntry(entryName);
+
+    let file = profileDir.clone();
+    let split = entryName.split("/");
+    for(let i = 0; i < split.length; i++) {
+      file.append(split[i]);
+    }
+
+    if (zipentry.isDirectory) {
+      file.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
+    } else {
+      let istream = zipReader.getInputStream(entryName);
+
+      var ostream = Cc["@mozilla.org/network/file-output-stream;1"]
+                    .createInstance(Ci.nsIFileOutputStream);
+      ostream.init(file, -1, parseInt("0644", 8), 0);
+
+      let bostream = Cc['@mozilla.org/network/buffered-output-stream;1']
+                     .createInstance(Ci.nsIBufferedOutputStream);
+      bostream.init(ostream, 32768);
+
+      bostream.writeFrom(istream, istream.available());
+
+      istream.close();
+      bostream.close();
+    }
+  }
+
+  zipReader.close();
+}
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
+++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
@@ -225,17 +225,17 @@ function setTimeout(fun, timeout) {
       fun();
     }
   };
   timer.initWithCallback(event, timeout,
                          Components.interfaces.nsITimer.TYPE_ONE_SHOT);
   return timer;
 }
 
-function clearAllDatabases(callback) {
+function resetOrClearAllDatabases(callback, clear) {
   if (!SpecialPowers.isMainProcess()) {
     throw new Error("clearAllDatabases not implemented for child processes!");
   }
 
   let quotaManager = Cc["@mozilla.org/dom/quota/manager;1"]
                        .getService(Ci.nsIQuotaManager);
 
   const quotaPref = "dom.quotaManager.testing";
@@ -243,17 +243,21 @@ function clearAllDatabases(callback) {
   let oldPrefValue;
   if (SpecialPowers._getPrefs().prefHasUserValue(quotaPref)) {
     oldPrefValue = SpecialPowers.getBoolPref(quotaPref);
   }
 
   SpecialPowers.setBoolPref(quotaPref, true);
 
   try {
-    quotaManager.clear();
+    if (clear) {
+      quotaManager.clear();
+    } else {
+      quotaManager.reset();
+    }
   } catch(e) {
     if (oldPrefValue !== undefined) {
       SpecialPowers.setBoolPref(quotaPref, oldPrefValue);
     } else {
       SpecialPowers.clearUserPref(quotaPref);
     }
     throw e;
   }
@@ -261,16 +265,24 @@ function clearAllDatabases(callback) {
   let uri = Cc["@mozilla.org/network/io-service;1"]
               .getService(Ci.nsIIOService)
               .newURI("http://foo.com", null, null);
   quotaManager.getUsageForURI(uri, function(usage, fileUsage) {
     callback();
   });
 }
 
+function resetAllDatabases(callback) {
+  resetOrClearAllDatabases(callback, false);
+}
+
+function clearAllDatabases(callback) {
+  resetOrClearAllDatabases(callback, true);
+}
+
 var SpecialPowers = {
   isMainProcess: function() {
     return Components.classes["@mozilla.org/xre/app-info;1"]
                      .getService(Components.interfaces.nsIXULRuntime)
                      .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
   },
   notifyObservers: function(subject, topic, data) {
     var obsvc = Cc['@mozilla.org/observer-service;1']
--- a/dom/indexedDB/test/unit/xpcshell-parent-process.ini
+++ b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
@@ -3,25 +3,27 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 [DEFAULT]
 dupe-manifest =
 head = xpcshell-head-parent-process.js
 tail =
 skip-if = toolkit == 'android' || toolkit == 'gonk'
 support-files =
+  bug1056939.zip
   GlobalObjectsChild.js
   GlobalObjectsComponent.js
   GlobalObjectsComponent.manifest
   GlobalObjectsModule.jsm
   GlobalObjectsSandbox.js
   xpcshell-shared.ini
 
 [include:xpcshell-shared.ini]
 
+[test_bug1056939.js]
 [test_globalObjects_ipc.js]
 [test_invalidate.js]
 # disabled for the moment.
 skip-if = true
 [test_lowDiskSpace.js]
 [test_temporary_storage.js]
 # bug 951017: intermittent failure on Android x86 emulator
 skip-if = os == "android" && processor == "x86"
--- a/dom/quota/QuotaManager.cpp
+++ b/dom/quota/QuotaManager.cpp
@@ -377,18 +377,17 @@ public:
     }
   }
 
   static void
   InvalidateOpenedStorages(nsTArray<nsCOMPtr<nsIOfflineStorage> >& aStorages,
                            void* aClosure);
 
   void
-  DeleteFiles(QuotaManager* aQuotaManager,
-              PersistenceType aPersistenceType);
+  DeleteFiles(QuotaManager* aQuotaManager);
 
 private:
   ~ResetOrClearRunnable() {}
 
   CallbackState mCallbackState;
   bool mClear;
 };
 
@@ -988,16 +987,19 @@ QuotaManager::Init()
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = indexedDBDir->GetPath(mIndexedDBPath);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = baseDir->Append(NS_LITERAL_STRING("storage"));
     NS_ENSURE_SUCCESS(rv, rv);
 
+    rv = baseDir->GetPath(mStoragePath);
+    NS_ENSURE_SUCCESS(rv, rv);
+
     nsCOMPtr<nsIFile> persistentStorageDir;
     rv = baseDir->Clone(getter_AddRefs(persistentStorageDir));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = persistentStorageDir->Append(NS_LITERAL_STRING("persistent"));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = persistentStorageDir->GetPath(mPersistentStoragePath);
@@ -1972,16 +1974,17 @@ QuotaManager::OriginClearCompleted(
 
 void
 QuotaManager::ResetOrClearCompleted()
 {
   AssertIsOnIOThread();
 
   mInitializedOrigins.Clear();
   mTemporaryStorageInitialized = false;
+  mStorageAreaInitialized = false;
 
   ReleaseIOThreadObjects();
 }
 
 already_AddRefed<mozilla::dom::quota::Client>
 QuotaManager::GetClient(Client::Type aClientType)
 {
   nsRefPtr<Client> client = mClients.SafeElementAt(aClientType);
@@ -3923,29 +3926,28 @@ ResetOrClearRunnable::InvalidateOpenedSt
   storages.SwapElements(aStorages);
 
   for (uint32_t index = 0; index < storages.Length(); index++) {
     storages[index]->Invalidate();
   }
 }
 
 void
-ResetOrClearRunnable::DeleteFiles(QuotaManager* aQuotaManager,
-                                  PersistenceType aPersistenceType)
+ResetOrClearRunnable::DeleteFiles(QuotaManager* aQuotaManager)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(aQuotaManager, "Don't pass me null!");
 
   nsresult rv;
 
   nsCOMPtr<nsIFile> directory =
     do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS_VOID(rv);
 
-  rv = directory->InitWithPath(aQuotaManager->GetStoragePath(aPersistenceType));
+  rv = directory->InitWithPath(aQuotaManager->GetStoragePath());
   NS_ENSURE_SUCCESS_VOID(rv);
 
   rv = directory->Remove(true);
   if (rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST &&
       rv != NS_ERROR_FILE_NOT_FOUND && NS_FAILED(rv)) {
     // This should never fail if we've closed all storage connections
     // correctly...
     NS_ERROR("Failed to remove directory!");
@@ -3983,18 +3985,17 @@ ResetOrClearRunnable::Run()
     }
 
     case IO: {
       AssertIsOnIOThread();
 
       AdvanceState();
 
       if (mClear) {
-        DeleteFiles(quotaManager, PERSISTENCE_TYPE_PERSISTENT);
-        DeleteFiles(quotaManager, PERSISTENCE_TYPE_TEMPORARY);
+        DeleteFiles(quotaManager);
       }
 
       quotaManager->RemoveQuota();
       quotaManager->ResetOrClearCompleted();
 
       // Now dispatch back to the main thread.
       if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
         NS_WARNING("Failed to dispatch to main thread!");
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -275,16 +275,22 @@ public:
     NS_ASSERTION(mIOThread, "This should never be null!");
     return mIOThread;
   }
 
   already_AddRefed<Client>
   GetClient(Client::Type aClientType);
 
   const nsString&
+  GetStoragePath() const
+  {
+    return mStoragePath;
+  }
+
+  const nsString&
   GetStoragePath(PersistenceType aPersistenceType) const
   {
     if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
       return mPersistentStoragePath;
     }
 
     NS_ASSERTION(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY, "Huh?");
 
@@ -515,16 +521,17 @@ private:
 
   // A list of all successfully initialized origins. This list isn't protected
   // by any mutex but it is only ever touched on the IO thread.
   nsTArray<nsCString> mInitializedOrigins;
 
   nsAutoTArray<nsRefPtr<Client>, Client::TYPE_MAX> mClients;
 
   nsString mIndexedDBPath;
+  nsString mStoragePath;
   nsString mPersistentStoragePath;
   nsString mTemporaryStoragePath;
 
   uint64_t mTemporaryStorageLimit;
   uint64_t mTemporaryStorageUsage;
   bool mTemporaryStorageInitialized;
 
   bool mStorageAreaInitialized;