--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -57,17 +57,16 @@
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#endif
#include "Layers.h"
#include "nsIIOService.h"
#include "mozilla/dom/Element.h"
-#include "mozilla/dom/indexedDB/FileInfo.h"
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "GeckoProfiler.h"
#include "nsDOMBlobBuilder.h"
#include "nsIDOMFileHandle.h"
#include "nsPrintfCString.h"
#include "nsViewportInfo.h"
#include "nsIFormControl.h"
@@ -2793,38 +2792,25 @@ nsDOMWindowUtils::GetFileReferences(cons
nsCString origin;
nsresult rv = quota::QuotaManager::GetASCIIOriginFromWindow(window, origin);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
indexedDB::IndexedDatabaseManager::Get();
if (mgr) {
- nsRefPtr<indexedDB::FileManager> fileManager =
- mgr->GetFileManager(origin, aDatabaseName);
-
- if (fileManager) {
- nsRefPtr<indexedDB::FileInfo> fileInfo = fileManager->GetFileInfo(aId);
-
- if (fileInfo) {
- fileInfo->GetReferences(aRefCnt, aDBRefCnt, aSliceRefCnt);
-
- if (*aRefCnt != -1) {
- // We added an extra temp ref, so account for that accordingly.
- (*aRefCnt)--;
- }
-
- *aResult = true;
- return NS_OK;
- }
- }
+ rv = mgr->BlockAndGetFileReferences(origin, aDatabaseName, aId, aRefCnt,
+ aDBRefCnt, aSliceRefCnt, aResult);
+ NS_ENSURE_SUCCESS(rv, rv);
}
-
- *aRefCnt = *aDBRefCnt = *aSliceRefCnt = -1;
- *aResult = false;
+ else {
+ *aRefCnt = *aDBRefCnt = *aSliceRefCnt = -1;
+ *aResult = false;
+ }
+
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::IsIncrementalGCEnabled(JSContext* cx, bool* aResult)
{
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
--- a/dom/indexedDB/Client.cpp
+++ b/dom/indexedDB/Client.cpp
@@ -10,16 +10,17 @@
#include "mozilla/dom/quota/UsageRunnable.h"
#include "mozilla/dom/quota/Utilities.h"
#include "IDBDatabase.h"
#include "IndexedDatabaseManager.h"
#include "TransactionThreadPool.h"
USING_INDEXEDDB_NAMESPACE
+using mozilla::dom::quota::AssertIsOnIOThread;
using mozilla::dom::quota::QuotaManager;
namespace {
bool
GetDatabaseBaseFilename(const nsAString& aFilename,
nsAString& aDatabaseBaseFilename)
{
@@ -41,16 +42,18 @@ GetDatabaseBaseFilename(const nsAString&
// This needs to be fully qualified to not confuse trace refcnt assertions.
NS_IMPL_ADDREF(mozilla::dom::indexedDB::Client)
NS_IMPL_RELEASE(mozilla::dom::indexedDB::Client)
nsresult
Client::InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable)
{
+ AssertIsOnIOThread();
+
nsCOMPtr<nsIFile> directory;
nsresult rv = GetDirectory(aOrigin, getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, rv);
// We need to see if there are any files in the directory already. If they
// are database files then we need to cleanup stored files (if it's needed)
// and also get the usage.
@@ -157,38 +160,64 @@ Client::InitOrigin(const nsACString& aOr
return NS_OK;
}
nsresult
Client::GetUsageForOrigin(const nsACString& aOrigin,
UsageRunnable* aUsageRunnable)
{
+ AssertIsOnIOThread();
NS_ASSERTION(aUsageRunnable, "Null pointer!");
nsCOMPtr<nsIFile> directory;
nsresult rv = GetDirectory(aOrigin, getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, rv);
rv = GetUsageForDirectoryInternal(directory, aUsageRunnable, true);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
+void
+Client::OnOriginClearCompleted(const nsACString& aPattern)
+{
+ AssertIsOnIOThread();
+
+ IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
+ if (mgr) {
+ mgr->InvalidateFileManagersForPattern(aPattern);
+ }
+}
+
+void
+Client::ReleaseIOThreadObjects()
+{
+ AssertIsOnIOThread();
+
+ IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
+ if (mgr) {
+ mgr->InvalidateAllFileManagers();
+ }
+}
+
bool
Client::IsTransactionServiceActivated()
{
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
return !!TransactionThreadPool::Get();
}
void
Client::WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
nsIRunnable* aCallback)
{
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!aStorages.IsEmpty(), "No storages to wait on!");
NS_ASSERTION(aCallback, "Passed null callback!");
TransactionThreadPool* pool = TransactionThreadPool::Get();
NS_ASSERTION(pool, "Should have checked if transaction service is active!");
nsTArray<nsRefPtr<IDBDatabase> > databases(aStorages.Length());
for (uint32_t index = 0; index < aStorages.Length(); index++) {
@@ -201,61 +230,48 @@ Client::WaitForStoragesToComplete(nsTArr
}
pool->WaitForDatabasesToComplete(databases, aCallback);
}
void
Client::AbortTransactionsForStorage(nsIOfflineStorage* aStorage)
{
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aStorage, "Passed null storage!");
TransactionThreadPool* pool = TransactionThreadPool::Get();
NS_ASSERTION(pool, "Should have checked if transaction service is active!");
IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
NS_ASSERTION(database, "This shouldn't be null!");
pool->AbortTransactionsForDatabase(database);
}
bool
Client::HasTransactionsForStorage(nsIOfflineStorage* aStorage)
{
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
TransactionThreadPool* pool = TransactionThreadPool::Get();
NS_ASSERTION(pool, "Should have checked if transaction service is active!");
IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
NS_ASSERTION(database, "This shouldn't be null!");
return pool->HasTransactionsForDatabase(database);
}
void
-Client::OnOriginClearCompleted(const nsACString& aPattern)
-{
- IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
- if (mgr) {
- mgr->InvalidateFileManagersForPattern(aPattern);
- }
-}
-
-void
Client::ShutdownTransactionService()
{
- TransactionThreadPool::Shutdown();
-}
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-void
-Client::OnShutdownCompleted()
-{
- IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
- if (mgr) {
- mgr->InvalidateAllFileManagers();
- }
+ TransactionThreadPool::Shutdown();
}
nsresult
Client::GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory)
{
QuotaManager* quotaManager = QuotaManager::Get();
NS_ASSERTION(quotaManager, "This should never fail!");
--- a/dom/indexedDB/Client.h
+++ b/dom/indexedDB/Client.h
@@ -36,16 +36,22 @@ public:
virtual nsresult
InitOrigin(const nsACString& aOrigin,
UsageRunnable* aUsageRunnable) MOZ_OVERRIDE;
virtual nsresult
GetUsageForOrigin(const nsACString& aOrigin,
UsageRunnable* aUsageRunnable) MOZ_OVERRIDE;
+ virtual void
+ OnOriginClearCompleted(const nsACString& aPattern) MOZ_OVERRIDE;
+
+ virtual void
+ ReleaseIOThreadObjects() MOZ_OVERRIDE;
+
virtual bool
IsFileServiceUtilized() MOZ_OVERRIDE
{
return true;
}
virtual bool
IsTransactionServiceActivated() MOZ_OVERRIDE;
@@ -56,24 +62,18 @@ public:
virtual void
AbortTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE;
virtual bool
HasTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE;
virtual void
- OnOriginClearCompleted(const nsACString& aPattern) MOZ_OVERRIDE;
-
- virtual void
ShutdownTransactionService() MOZ_OVERRIDE;
- virtual void
- OnShutdownCompleted() MOZ_OVERRIDE;
-
private:
nsresult
GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory);
nsresult
GetUsageForDirectoryInternal(nsIFile* aDirectory,
UsageRunnable* aUsageRunnable,
bool aDatabaseFiles);
--- a/dom/indexedDB/FileInfo.cpp
+++ b/dom/indexedDB/FileInfo.cpp
@@ -68,38 +68,44 @@ void
FileInfo::UpdateReferences(nsAutoRefCnt& aRefCount, int32_t aDelta,
bool aClear)
{
if (IndexedDatabaseManager::IsClosed()) {
NS_ERROR("Shouldn't be called after shutdown!");
return;
}
+ bool needsCleanup;
{
MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
aRefCount = aClear ? 0 : aRefCount + aDelta;
if (mRefCnt + mDBRefCnt + mSliceRefCnt > 0) {
return;
}
mFileManager->mFileInfos.Remove(Id());
+
+ needsCleanup = !mFileManager->Invalidated();
}
- Cleanup();
+ if (needsCleanup) {
+ Cleanup();
+ }
delete this;
}
void
FileInfo::Cleanup()
{
- if (quota::QuotaManager::IsShuttingDown() ||
- mFileManager->Invalidated()) {
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+ if (quota::QuotaManager::IsShuttingDown()) {
return;
}
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
NS_ASSERTION(mgr, "Shouldn't be null!");
if (NS_FAILED(mgr->AsyncDeleteFile(mFileManager, Id()))) {
NS_WARNING("Failed to delete file asynchronously!");
--- a/dom/indexedDB/FileInfo.h
+++ b/dom/indexedDB/FileInfo.h
@@ -22,21 +22,17 @@ class FileInfo
friend class FileManager;
public:
FileInfo(FileManager* aFileManager)
: mFileManager(aFileManager)
{ }
virtual ~FileInfo()
- {
-#ifdef DEBUG
- NS_ASSERTION(NS_IsMainThread(), "File info destroyed on wrong thread!");
-#endif
- }
+ { }
static
FileInfo* Create(FileManager* aFileManager, int64_t aId);
void AddRef()
{
if (IndexedDatabaseManager::IsClosed()) {
NS_AtomicIncrementRefcnt(mRefCnt);
--- a/dom/indexedDB/FileManager.cpp
+++ b/dom/indexedDB/FileManager.cpp
@@ -19,16 +19,17 @@
#include "FileInfo.h"
#include "IndexedDatabaseManager.h"
#include "OpenDatabaseHelper.h"
#include "IndexedDatabaseInlines.h"
#include <algorithm>
USING_INDEXEDDB_NAMESPACE
+using mozilla::dom::quota::AssertIsOnIOThread;
namespace {
PLDHashOperator
EnumerateToTArray(const uint64_t& aKey,
FileInfo* aValue,
void* aUserArg)
{
@@ -57,17 +58,17 @@ GetDirectoryFor(const nsAString& aDirect
}
} // anonymous namespace
nsresult
FileManager::Init(nsIFile* aDirectory,
mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(aDirectory, "Null directory!");
NS_ASSERTION(aConnection, "Null connection!");
mFileInfos.Init();
bool exists;
nsresult rv = aDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
@@ -264,17 +265,17 @@ FileManager::GetFileForId(nsIFile* aDire
}
// static
nsresult
FileManager::InitDirectory(nsIFile* aDirectory,
nsIFile* aDatabaseFile,
const nsACString& aOrigin)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(aDirectory, "Null directory!");
NS_ASSERTION(aDatabaseFile, "Null database file!");
bool exists;
nsresult rv = aDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
if (!exists) {
@@ -380,16 +381,18 @@ FileManager::InitDirectory(nsIFile* aDir
return NS_OK;
}
// static
nsresult
FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage)
{
+ AssertIsOnIOThread();
+
uint64_t usage = 0;
nsCOMPtr<nsISimpleEnumerator> entries;
nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
NS_ENSURE_SUCCESS(rv, rv);
bool hasMore;
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -33,16 +33,17 @@
#include "ProfilerHelpers.h"
#include "TransactionThreadPool.h"
#include "ipc/IndexedDBChild.h"
#include "ipc/IndexedDBParent.h"
USING_INDEXEDDB_NAMESPACE
using mozilla::dom::ContentParent;
+using mozilla::dom::quota::AssertIsOnIOThread;
using mozilla::dom::quota::Client;
using mozilla::dom::quota::QuotaManager;
namespace {
class NoRequestDatabaseHelper : public AsyncConnectionHelper
{
public:
@@ -981,17 +982,17 @@ DeleteObjectStoreHelper::DoDatabaseWork(
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
return NS_OK;
}
nsresult
CreateFileHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "CreateFileHelper::DoDatabaseWork");
if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
NS_WARNING("Refusing to create file because disk space is low!");
return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
}
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -330,17 +330,17 @@ IgnoreWhitespace(PRUnichar c)
// static
nsresult
IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
nsIAtom* aDatabaseId,
uint64_t* aVersion,
ObjectStoreInfoArray& aObjectStores)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(aConnection, "Null pointer!");
aObjectStores.Clear();
// Load object store names and ids.
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT name, id, key_path, auto_increment "
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -10,16 +10,17 @@
#include "nsIDiskSpaceWatcher.h"
#include "nsIDOMScriptObjectFactory.h"
#include "nsIFile.h"
#include "nsIFileStorage.h"
#include "nsIObserverService.h"
#include "nsIScriptError.h"
#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/CondVar.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/Utilities.h"
#include "mozilla/dom/TabContext.h"
#include "mozilla/Services.h"
#include "mozilla/storage.h"
#include "nsContentUtils.h"
#include "nsEventDispatcher.h"
#include "nsThreadUtils.h"
@@ -55,23 +56,62 @@ public:
AsyncDeleteFileRunnable(FileManager* aFileManager, int64_t aFileId);
private:
nsRefPtr<FileManager> mFileManager;
int64_t mFileId;
};
+class GetFileReferencesHelper MOZ_FINAL : public nsIRunnable
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIRUNNABLE
+
+ GetFileReferencesHelper(const nsACString& aOrigin,
+ const nsAString& aDatabaseName,
+ int64_t aFileId)
+ : mOrigin(aOrigin), mDatabaseName(aDatabaseName), mFileId(aFileId),
+ mMutex(IndexedDatabaseManager::FileMutex()),
+ mCondVar(mMutex, "GetFileReferencesHelper::mCondVar"),
+ mMemRefCnt(-1),
+ mDBRefCnt(-1),
+ mSliceRefCnt(-1),
+ mResult(false),
+ mWaiting(true)
+ { }
+
+ nsresult
+ DispatchAndReturnFileReferences(int32_t* aMemRefCnt,
+ int32_t* aDBRefCnt,
+ int32_t* aSliceRefCnt,
+ bool* aResult);
+
+private:
+ nsCString mOrigin;
+ nsString mDatabaseName;
+ int64_t mFileId;
+
+ mozilla::Mutex& mMutex;
+ mozilla::CondVar mCondVar;
+ int32_t mMemRefCnt;
+ int32_t mDBRefCnt;
+ int32_t mSliceRefCnt;
+ bool mResult;
+ bool mWaiting;
+};
+
PLDHashOperator
InvalidateAndRemoveFileManagers(
const nsACString& aKey,
nsAutoPtr<nsTArray<nsRefPtr<FileManager> > >& aValue,
void* aUserArg)
{
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
NS_ASSERTION(aValue, "Null pointer!");
const nsACString* pattern =
static_cast<const nsACString*>(aUserArg);
if (!pattern || PatternMatchesOrigin(*pattern, aKey)) {
for (uint32_t i = 0; i < aValue->Length(); i++) {
@@ -341,16 +381,18 @@ IndexedDatabaseManager::InLowDiskSpaceMo
return !!sLowDiskSpaceMode;
}
#endif
already_AddRefed<FileManager>
IndexedDatabaseManager::GetFileManager(const nsACString& aOrigin,
const nsAString& aDatabaseName)
{
+ AssertIsOnIOThread();
+
nsTArray<nsRefPtr<FileManager> >* array;
if (!mFileManagers.Get(aOrigin, &array)) {
return nullptr;
}
for (uint32_t i = 0; i < array->Length(); i++) {
nsRefPtr<FileManager>& fileManager = array->ElementAt(i);
@@ -361,46 +403,53 @@ IndexedDatabaseManager::GetFileManager(c
}
return nullptr;
}
void
IndexedDatabaseManager::AddFileManager(FileManager* aFileManager)
{
+ AssertIsOnIOThread();
NS_ASSERTION(aFileManager, "Null file manager!");
nsTArray<nsRefPtr<FileManager> >* array;
if (!mFileManagers.Get(aFileManager->Origin(), &array)) {
array = new nsTArray<nsRefPtr<FileManager> >();
mFileManagers.Put(aFileManager->Origin(), array);
}
array->AppendElement(aFileManager);
}
void
IndexedDatabaseManager::InvalidateAllFileManagers()
{
+ AssertIsOnIOThread();
+
mFileManagers.Enumerate(InvalidateAndRemoveFileManagers, nullptr);
}
void
IndexedDatabaseManager::InvalidateFileManagersForPattern(
const nsACString& aPattern)
{
+ AssertIsOnIOThread();
NS_ASSERTION(!aPattern.IsEmpty(), "Empty pattern!");
+
mFileManagers.Enumerate(InvalidateAndRemoveFileManagers,
const_cast<nsACString*>(&aPattern));
}
void
IndexedDatabaseManager::InvalidateFileManager(const nsACString& aOrigin,
const nsAString& aDatabaseName)
{
+ AssertIsOnIOThread();
+
nsTArray<nsRefPtr<FileManager> >* array;
if (!mFileManagers.Get(aOrigin, &array)) {
return;
}
for (uint32_t i = 0; i < array->Length(); i++) {
nsRefPtr<FileManager> fileManager = array->ElementAt(i);
if (fileManager->DatabaseName().Equals(aDatabaseName)) {
@@ -438,16 +487,36 @@ IndexedDatabaseManager::AsyncDeleteFile(
nsresult rv =
quotaManager->IOThread()->Dispatch(runnable, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
+nsresult
+IndexedDatabaseManager::BlockAndGetFileReferences(
+ const nsACString& aOrigin,
+ const nsAString& aDatabaseName,
+ int64_t aFileId,
+ int32_t* aRefCnt,
+ int32_t* aDBRefCnt,
+ int32_t* aSliceRefCnt,
+ bool* aResult)
+{
+ nsRefPtr<GetFileReferencesHelper> helper =
+ new GetFileReferencesHelper(aOrigin, aDatabaseName, aFileId);
+
+ nsresult rv = helper->DispatchAndReturnFileReferences(aRefCnt, aDBRefCnt,
+ aSliceRefCnt, aResult);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
NS_IMPL_ADDREF(IndexedDatabaseManager)
NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager, Destroy())
NS_IMPL_QUERY_INTERFACE2(IndexedDatabaseManager, nsIIndexedDatabaseManager,
nsIObserver)
NS_IMETHODIMP
IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx)
{
@@ -542,17 +611,17 @@ AsyncDeleteFileRunnable::AsyncDeleteFile
}
NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteFileRunnable,
nsIRunnable)
NS_IMETHODIMP
AsyncDeleteFileRunnable::Run()
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
nsCOMPtr<nsIFile> directory = mFileManager->GetDirectory();
NS_ENSURE_TRUE(directory, NS_ERROR_FAILURE);
nsCOMPtr<nsIFile> file = mFileManager->GetFileForId(directory, mFileId);
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
nsresult rv;
@@ -579,8 +648,74 @@ AsyncDeleteFileRunnable::Run()
file = mFileManager->GetFileForId(directory, mFileId);
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
rv = file->Remove(false);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
+
+nsresult
+GetFileReferencesHelper::DispatchAndReturnFileReferences(int32_t* aMemRefCnt,
+ int32_t* aDBRefCnt,
+ int32_t* aSliceRefCnt,
+ bool* aResult)
+{
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+ QuotaManager* quotaManager = QuotaManager::Get();
+ NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+ nsresult rv =
+ quotaManager->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mozilla::MutexAutoLock autolock(mMutex);
+ while (mWaiting) {
+ mCondVar.Wait();
+ }
+
+ *aMemRefCnt = mMemRefCnt;
+ *aDBRefCnt = mDBRefCnt;
+ *aSliceRefCnt = mSliceRefCnt;
+ *aResult = mResult;
+
+ return NS_OK;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(GetFileReferencesHelper,
+ nsIRunnable)
+
+NS_IMETHODIMP
+GetFileReferencesHelper::Run()
+{
+ AssertIsOnIOThread();
+
+ IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
+ NS_ASSERTION(mgr, "This should never fail!");
+
+ nsRefPtr<FileManager> fileManager =
+ mgr->GetFileManager(mOrigin, mDatabaseName);
+
+ if (fileManager) {
+ nsRefPtr<FileInfo> fileInfo = fileManager->GetFileInfo(mFileId);
+
+ if (fileInfo) {
+ fileInfo->GetReferences(&mMemRefCnt, &mDBRefCnt, &mSliceRefCnt);
+
+ if (mMemRefCnt != -1) {
+ // We added an extra temp ref, so account for that accordingly.
+ mMemRefCnt--;
+ }
+
+ mResult = true;
+ }
+ }
+
+ mozilla::MutexAutoLock lock(mMutex);
+ NS_ASSERTION(mWaiting, "Huh?!");
+
+ mWaiting = false;
+ mCondVar.Notify();
+
+ return NS_OK;
+}
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -91,16 +91,28 @@ public:
void
InvalidateFileManager(const nsACString& aOrigin,
const nsAString& aDatabaseName);
nsresult
AsyncDeleteFile(FileManager* aFileManager,
int64_t aFileId);
+ // Don't call this method in real code, it blocks the main thread!
+ // It is intended to be used by mochitests to test correctness of the special
+ // reference counting of stored blobs/files.
+ nsresult
+ BlockAndGetFileReferences(const nsACString& aOrigin,
+ const nsAString& aDatabaseName,
+ int64_t aFileId,
+ int32_t* aRefCnt,
+ int32_t* aDBRefCnt,
+ int32_t* aSliceRefCnt,
+ bool* aResult);
+
static mozilla::Mutex&
FileMutex()
{
IndexedDatabaseManager* mgr = Get();
NS_ASSERTION(mgr, "Must have a manager here!");
return mgr->mFileMutex;
}
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -91,17 +91,17 @@ GetDatabaseFilename(const nsAString& aNa
aDatabaseFilename.Append(NS_ConvertASCIItoUTF16(substring));
return NS_OK;
}
nsresult
CreateFileTables(mozIStorageConnection* aDBConn)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "CreateFileTables");
// Table `file`
nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE file ("
"id INTEGER PRIMARY KEY, "
@@ -153,17 +153,17 @@ CreateFileTables(mozIStorageConnection*
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
CreateTables(mozIStorageConnection* aDBConn)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
NS_ASSERTION(aDBConn, "Passing a null database connection!");
PROFILER_LABEL("IndexedDB", "CreateTables");
// Table `database`
nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE database ("
@@ -270,17 +270,17 @@ CreateTables(mozIStorageConnection* aDBC
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
UpgradeSchemaFrom4To5(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom4To5");
nsresult rv;
// All we changed is the type of the version column, so lets try to
// convert that to an integer, and if we fail, set it to 0.
@@ -359,17 +359,17 @@ UpgradeSchemaFrom4To5(mozIStorageConnect
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
UpgradeSchemaFrom5To6(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom5To6");
// First, drop all the indexes we're no longer going to use.
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP INDEX key_index;"
));
@@ -717,17 +717,17 @@ UpgradeSchemaFrom5To6(mozIStorageConnect
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
UpgradeSchemaFrom6To7(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom6To7");
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TEMPORARY TABLE temp_upgrade ("
"id, "
"name, "
@@ -776,17 +776,17 @@ UpgradeSchemaFrom6To7(mozIStorageConnect
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
UpgradeSchemaFrom7To8(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom7To8");
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TEMPORARY TABLE temp_upgrade ("
"id, "
"object_store_id, "
@@ -900,17 +900,17 @@ public:
}
};
NS_IMPL_ISUPPORTS1(CompressDataBlobsFunction, mozIStorageFunction)
nsresult
UpgradeSchemaFrom8To9_0(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom8To9_0");
// We no longer use the dataVersion column.
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"UPDATE database SET dataVersion = 0;"
));
@@ -941,17 +941,17 @@ UpgradeSchemaFrom8To9_0(mozIStorageConne
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
UpgradeSchemaFrom9_0To10_0(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom9_0To10_0");
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"ALTER TABLE object_data ADD COLUMN file_ids TEXT;"
));
NS_ENSURE_SUCCESS(rv, rv);
@@ -968,17 +968,17 @@ UpgradeSchemaFrom9_0To10_0(mozIStorageCo
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
UpgradeSchemaFrom10_0To11_0(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom10_0To11_0");
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TEMPORARY TABLE temp_upgrade ("
"id, "
"object_store_id, "
@@ -1158,17 +1158,17 @@ public:
}
};
NS_IMPL_ISUPPORTS1(EncodeKeysFunction, mozIStorageFunction)
nsresult
UpgradeSchemaFrom11_0To12_0(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom11_0To12_0");
NS_NAMED_LITERAL_CSTRING(encoderName, "encode");
nsCOMPtr<mozIStorageFunction> encoder = new EncodeKeysFunction();
@@ -1375,17 +1375,17 @@ UpgradeSchemaFrom11_0To12_0(mozIStorageC
return NS_OK;
}
nsresult
UpgradeSchemaFrom12_0To13_0(mozIStorageConnection* aConnection,
bool* aVacuumNeeded)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom12_0To13_0");
nsresult rv;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
int32_t defaultPageSize;
@@ -1712,25 +1712,17 @@ OpenDatabaseHelper::RunImmediately()
mState = eFiringEvents;
return this->Run();
}
nsresult
OpenDatabaseHelper::DoDatabaseWork()
{
-#ifdef DEBUG
- {
- bool correctThread;
- NS_ASSERTION(NS_SUCCEEDED(QuotaManager::Get()->IOThread()->
- IsOnCurrentThread(&correctThread)) &&
- correctThread,
- "Running on the wrong thread!");
- }
-#endif
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "OpenDatabaseHelper::DoDatabaseWork");
mState = eFiringEvents; // In case we fail somewhere along the line.
if (QuotaManager::IsShuttingDown()) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@@ -1866,17 +1858,17 @@ OpenDatabaseHelper::DoDatabaseWork()
nsresult
OpenDatabaseHelper::CreateDatabaseConnection(
nsIFile* aDBFile,
nsIFile* aFMDirectory,
const nsAString& aName,
const nsACString& aOrigin,
mozIStorageConnection** aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
PROFILER_LABEL("IndexedDB", "OpenDatabaseHelper::CreateDatabaseConnection");
nsresult rv;
bool exists;
if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
@@ -2167,21 +2159,16 @@ OpenDatabaseHelper::Run()
}
case eDeleteCompleted: {
// Destroy the database now (we should have the only ref).
mDatabase = nullptr;
DatabaseInfo::Remove(mDatabaseId);
- IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
- NS_ASSERTION(mgr, "This should never fail!");
-
- mgr->InvalidateFileManager(mASCIIOrigin, mName);
-
mState = eFiringEvents;
break;
}
case eFiringEvents: {
// Notify the request that we're done, but only if we didn't just
// finish a [SetVersion/DeleteDatabase]Helper. In that case, the
// helper tells the request that it is done, and we avoid calling
@@ -2574,17 +2561,17 @@ SetVersionHelper::NotifyTransactionPostC
return rv;
}
NS_IMPL_ISUPPORTS_INHERITED0(DeleteDatabaseHelper, AsyncConnectionHelper);
nsresult
DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
NS_ASSERTION(!aConnection, "How did we get a connection here?");
PROFILER_LABEL("IndexedDB", "DeleteDatabaseHelper::DoDatabaseWork");
const StoragePrivilege& privilege = mOpenHelper->Privilege();
QuotaManager* quotaManager = QuotaManager::Get();
@@ -2678,16 +2665,21 @@ DeleteDatabaseHelper::DoDatabaseWork(moz
if (privilege != Chrome) {
QuotaManager* quotaManager = QuotaManager::Get();
NS_ASSERTION(quotaManager, "Shouldn't be null!");
quotaManager->DecreaseUsageForOrigin(mASCIIOrigin, usage);
}
}
+ IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
+ NS_ASSERTION(mgr, "This should never fail!");
+
+ mgr->InvalidateFileManager(mASCIIOrigin, mName);
+
return NS_OK;
}
nsresult
DeleteDatabaseHelper::GetSuccessResult(JSContext* aCx, jsval* aVal)
{
return NS_OK;
}
--- a/dom/quota/Client.h
+++ b/dom/quota/Client.h
@@ -63,23 +63,31 @@ public:
}
else {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
+ // Methods which are called on the IO thred.
virtual nsresult
InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable) = 0;
virtual nsresult
GetUsageForOrigin(const nsACString& aOrigin,
UsageRunnable* aUsageRunnable) = 0;
+ virtual void
+ OnOriginClearCompleted(const nsACString& aPattern) = 0;
+
+ virtual void
+ ReleaseIOThreadObjects() = 0;
+
+ // Methods which are called on the main thred.
virtual bool
IsFileServiceUtilized() = 0;
virtual bool
IsTransactionServiceActivated() = 0;
virtual void
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
@@ -87,24 +95,18 @@ public:
virtual void
AbortTransactionsForStorage(nsIOfflineStorage* aStorage) = 0;
virtual bool
HasTransactionsForStorage(nsIOfflineStorage* aStorage) = 0;
virtual void
- OnOriginClearCompleted(const nsACString& aPattern) = 0;
-
- virtual void
ShutdownTransactionService() = 0;
- virtual void
- OnShutdownCompleted() = 0;
-
protected:
virtual ~Client()
{ }
};
END_QUOTA_NAMESPACE
#endif // mozilla_dom_quota_client_h__
--- a/dom/quota/QuotaCommon.h
+++ b/dom/quota/QuotaCommon.h
@@ -15,9 +15,22 @@
#define BEGIN_QUOTA_NAMESPACE \
namespace mozilla { namespace dom { namespace quota {
#define END_QUOTA_NAMESPACE \
} /* namespace quota */ } /* namespace dom */ } /* namespace mozilla */
#define USING_QUOTA_NAMESPACE \
using namespace mozilla::dom::quota;
+BEGIN_QUOTA_NAMESPACE
+
+#ifdef DEBUG
+void
+AssertIsOnIOThread();
+#else
+inline void
+AssertIsOnIOThread()
+{ }
+#endif
+
+END_QUOTA_NAMESPACE
+
#endif // mozilla_dom_quota_quotacommon_h__
--- a/dom/quota/QuotaManager.cpp
+++ b/dom/quota/QuotaManager.cpp
@@ -235,16 +235,30 @@ public:
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIUsageCallback> mCallback;
uint32_t mAppId;
OriginOrPatternString mOrigin;
CallbackState mCallbackState;
bool mInMozBrowserOnly;
};
+#ifdef DEBUG
+void
+AssertIsOnIOThread()
+{
+ QuotaManager* quotaManager = QuotaManager::Get();
+ NS_ASSERTION(quotaManager, "Must have a manager here!");
+
+ bool correctThread;
+ NS_ASSERTION(NS_SUCCEEDED(quotaManager->IOThread()->
+ IsOnCurrentThread(&correctThread)) && correctThread,
+ "Running on the wrong thread!");
+}
+#endif
+
END_QUOTA_NAMESPACE
namespace {
QuotaManager* gInstance = nullptr;
int32_t gShutdown = 0;
int32_t gStorageQuotaMB = DEFAULT_QUOTA_MB;
@@ -821,24 +835,17 @@ QuotaManager::GetDirectoryForOrigin(cons
return NS_OK;
}
nsresult
QuotaManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
bool aTrackQuota,
nsIFile** aDirectory)
{
-#ifdef DEBUG
- {
- bool correctThread;
- NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) &&
- correctThread,
- "Running on the wrong thread!");
- }
-#endif
+ AssertIsOnIOThread();
nsCOMPtr<nsIFile> directory;
nsresult rv = GetDirectoryForOrigin(aOrigin, getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, rv);
bool exists;
rv = directory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
@@ -943,32 +950,30 @@ QuotaManager::EnsureOriginIsInitialized(
mInitializedOrigins.AppendElement(aOrigin);
NS_ADDREF(*aDirectory = directory);
return NS_OK;
}
void
-QuotaManager::UninitializeOriginsByPattern(const nsACString& aPattern)
+QuotaManager::OriginClearCompleted(const nsACString& aPattern)
{
-#ifdef DEBUG
- {
- bool correctThread;
- NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) &&
- correctThread,
- "Running on the wrong thread!");
- }
-#endif
-
- for (int32_t i = mInitializedOrigins.Length() - 1; i >= 0; i--) {
+ AssertIsOnIOThread();
+
+ int32_t i;
+ for (i = mInitializedOrigins.Length() - 1; i >= 0; i--) {
if (PatternMatchesOrigin(aPattern, mInitializedOrigins[i])) {
mInitializedOrigins.RemoveElementAt(i);
}
}
+
+ for (i = 0; i < Client::TYPE_MAX; i++) {
+ mClients[i]->OnOriginClearCompleted(aPattern);
+ }
}
already_AddRefed<mozilla::dom::quota::Client>
QuotaManager::GetClient(Client::Type aClientType)
{
nsRefPtr<Client> client = mClients.SafeElementAt(aClientType);
return client.forget();
}
@@ -1223,16 +1228,27 @@ QuotaManager::Observe(nsISupports* aSubj
if (!NS_ProcessNextEvent(thread)) {
NS_ERROR("Failed to process next event!");
break;
}
}
}
}
+ // Give clients a chance to cleanup IO thread only objects.
+ nsCOMPtr<nsIRunnable> runnable =
+ NS_NewRunnableMethod(this, &QuotaManager::ReleaseIOThreadObjects);
+ if (!runnable) {
+ NS_WARNING("Failed to create runnable!");
+ }
+
+ if (NS_FAILED(mIOThread->Dispatch(runnable, NS_DISPATCH_NORMAL))) {
+ NS_WARNING("Failed to dispatch runnable!");
+ }
+
// Make sure to join with our IO thread.
if (NS_FAILED(mIOThread->Shutdown())) {
NS_WARNING("Failed to shutdown IO thread!");
}
// Kick off the shutdown timer.
if (NS_FAILED(mShutdownTimer->Init(this, DEFAULT_SHUTDOWN_TIMER_MS,
nsITimer::TYPE_ONE_SHOT))) {
@@ -1246,20 +1262,16 @@ QuotaManager::Observe(nsISupports* aSubj
}
// Cancel the timer regardless of whether it actually fired.
if (NS_FAILED(mShutdownTimer->Cancel())) {
NS_WARNING("Failed to cancel shutdown timer!");
}
}
- for (uint32_t index = 0; index < Client::TYPE_MAX; index++) {
- mClients[index]->OnShutdownCompleted();
- }
-
return NS_OK;
}
if (!strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC)) {
NS_ASSERTION(IsMainProcess(), "Should only happen in the main process!");
NS_WARNING("Some storage operations are taking longer than expected "
"during shutdown and will be aborted!");
@@ -1815,17 +1827,17 @@ OriginClearRunnable::InvalidateOpenedSto
for (uint32_t index = 0; index < storages.Length(); index++) {
storages[index]->Invalidate();
}
}
void
OriginClearRunnable::DeleteFiles(QuotaManager* aQuotaManager)
{
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ 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);
@@ -1873,17 +1885,17 @@ OriginClearRunnable::DeleteFiles(QuotaMa
// This should never fail if we've closed all storage connections
// correctly...
NS_ERROR("Failed to remove directory!");
}
}
aQuotaManager->RemoveQuotaForPattern(mOriginOrPattern);
- aQuotaManager->UninitializeOriginsByPattern(mOriginOrPattern);
+ aQuotaManager->OriginClearCompleted(mOriginOrPattern);
}
NS_IMPL_THREADSAFE_ISUPPORTS1(OriginClearRunnable, nsIRunnable)
NS_IMETHODIMP
OriginClearRunnable::Run()
{
PROFILER_LABEL("Quota", "OriginClearRunnable::Run");
@@ -1908,17 +1920,17 @@ OriginClearRunnable::Run()
quotaManager->AcquireExclusiveAccess(mOriginOrPattern, this,
InvalidateOpenedStorages, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
case IO: {
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
AdvanceState();
DeleteFiles(quotaManager);
// Now dispatch back to the main thread.
if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
NS_WARNING("Failed to dispatch to main thread!");
@@ -1926,20 +1938,16 @@ OriginClearRunnable::Run()
}
return NS_OK;
}
case Complete: {
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
- for (uint32_t index = 0; index < Client::TYPE_MAX; index++) {
- quotaManager->mClients[index]->OnOriginClearCompleted(mOriginOrPattern);
- }
-
// Tell the QuotaManager that we're done.
quotaManager->AllowNextSynchronizedOp(mOriginOrPattern, nullptr);
return NS_OK;
}
default:
NS_ERROR("Unknown state value!");
@@ -2004,17 +2012,17 @@ AsyncUsageRunnable::RunInternal()
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch to the IO thread!");
}
return NS_OK;
}
case IO: {
- NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+ AssertIsOnIOThread();
AdvanceState();
// Get the directory that contains all the storage files we care about.
nsCOMPtr<nsIFile> directory;
rv = quotaManager->GetDirectoryForOrigin(mOrigin,
getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -191,17 +191,17 @@ public:
nsIFile** aDirectory) const;
nsresult
EnsureOriginIsInitialized(const nsACString& aOrigin,
bool aTrackQuota,
nsIFile** aDirectory);
void
- UninitializeOriginsByPattern(const nsACString& aPattern);
+ OriginClearCompleted(const nsACString& aPattern);
nsIThread*
IOThread()
{
NS_ASSERTION(mIOThread, "This should never be null!");
return mIOThread;
}
@@ -288,16 +288,26 @@ private:
nsISupports* aId);
nsresult
ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly);
nsresult
MaybeUpgradeOriginDirectory(nsIFile* aDirectory);
+ void
+ ReleaseIOThreadObjects()
+ {
+ AssertIsOnIOThread();
+
+ for (uint32_t index = 0; index < Client::TYPE_MAX; index++) {
+ mClients[index]->ReleaseIOThreadObjects();
+ }
+ }
+
static void
GetOriginPatternString(uint32_t aAppId,
MozBrowserPatternFlag aBrowserFlag,
const nsACString& aOrigin,
nsAutoCString& _retval);
// TLS storage index for the current thread's window.
unsigned int mCurrentWindowIndex;