summaryrefslogtreecommitdiffstats
path: root/dom/indexedDB/FileInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/indexedDB/FileInfo.cpp')
-rw-r--r--dom/indexedDB/FileInfo.cpp260
1 files changed, 260 insertions, 0 deletions
diff --git a/dom/indexedDB/FileInfo.cpp b/dom/indexedDB/FileInfo.cpp
new file mode 100644
index 000000000..471007273
--- /dev/null
+++ b/dom/indexedDB/FileInfo.cpp
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "FileInfo.h"
+
+#include "FileManager.h"
+#include "IndexedDatabaseManager.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/dom/quota/QuotaManager.h"
+#include "nsError.h"
+#include "nsThreadUtils.h"
+
+namespace mozilla {
+namespace dom {
+namespace indexedDB {
+
+using namespace mozilla::dom::quota;
+
+namespace {
+
+template <typename IdType>
+class FileInfoImpl final
+ : public FileInfo
+{
+ IdType mFileId;
+
+public:
+ FileInfoImpl(FileManager* aFileManager, IdType aFileId)
+ : FileInfo(aFileManager)
+ , mFileId(aFileId)
+ {
+ MOZ_ASSERT(aFileManager);
+ MOZ_ASSERT(aFileId > 0);
+ }
+
+private:
+ ~FileInfoImpl()
+ { }
+
+ virtual int64_t
+ Id() const override
+ {
+ return int64_t(mFileId);
+ }
+};
+
+class CleanupFileRunnable final
+ : public Runnable
+{
+ RefPtr<FileManager> mFileManager;
+ int64_t mFileId;
+
+public:
+ static void
+ DoCleanup(FileManager* aFileManager, int64_t aFileId);
+
+ CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId)
+ : mFileManager(aFileManager)
+ , mFileId(aFileId)
+ {
+ MOZ_ASSERT(aFileManager);
+ MOZ_ASSERT(aFileId > 0);
+ }
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+private:
+ ~CleanupFileRunnable()
+ { }
+
+ NS_DECL_NSIRUNNABLE
+};
+
+} // namespace
+
+FileInfo::FileInfo(FileManager* aFileManager)
+ : mFileManager(aFileManager)
+{
+ MOZ_ASSERT(aFileManager);
+}
+
+FileInfo::~FileInfo()
+{
+}
+
+// static
+FileInfo*
+FileInfo::Create(FileManager* aFileManager, int64_t aId)
+{
+ MOZ_ASSERT(aFileManager);
+ MOZ_ASSERT(aId > 0);
+
+ if (aId <= INT16_MAX) {
+ return new FileInfoImpl<int16_t>(aFileManager, aId);
+ }
+
+ if (aId <= INT32_MAX) {
+ return new FileInfoImpl<int32_t>(aFileManager, aId);
+ }
+
+ return new FileInfoImpl<int64_t>(aFileManager, aId);
+}
+
+void
+FileInfo::GetReferences(int32_t* aRefCnt,
+ int32_t* aDBRefCnt,
+ int32_t* aSliceRefCnt)
+{
+ MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
+
+ MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
+
+ if (aRefCnt) {
+ *aRefCnt = mRefCnt;
+ }
+
+ if (aDBRefCnt) {
+ *aDBRefCnt = mDBRefCnt;
+ }
+
+ if (aSliceRefCnt) {
+ *aSliceRefCnt = mSliceRefCnt;
+ }
+}
+
+void
+FileInfo::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount,
+ int32_t aDelta,
+ CustomCleanupCallback* aCustomCleanupCallback)
+{
+ // XXX This can go away once DOM objects no longer hold FileInfo objects...
+ // Looking at you, BlobImplBase...
+ // BlobImplBase is being addressed in bug 1068975.
+ if (IndexedDatabaseManager::IsClosed()) {
+ MOZ_ASSERT(&aRefCount == &mRefCnt);
+ MOZ_ASSERT(aDelta == 1 || aDelta == -1);
+
+ if (aDelta > 0) {
+ ++aRefCount;
+ } else {
+ nsrefcnt count = --aRefCount;
+ if (!count) {
+ mRefCnt = 1;
+ delete this;
+ }
+ }
+ return;
+ }
+
+ MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
+
+ bool needsCleanup;
+ {
+ MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
+
+ aRefCount = aRefCount + aDelta;
+
+ if (mRefCnt + mDBRefCnt + mSliceRefCnt > 0) {
+ return;
+ }
+
+ mFileManager->mFileInfos.Remove(Id());
+
+ needsCleanup = !mFileManager->Invalidated();
+ }
+
+ if (needsCleanup) {
+ if (aCustomCleanupCallback) {
+ nsresult rv = aCustomCleanupCallback->Cleanup(mFileManager, Id());
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Custom cleanup failed!");
+ }
+ } else {
+ Cleanup();
+ }
+ }
+
+ delete this;
+}
+
+bool
+FileInfo::LockedClearDBRefs()
+{
+ MOZ_ASSERT(!IndexedDatabaseManager::IsClosed());
+
+ IndexedDatabaseManager::FileMutex().AssertCurrentThreadOwns();
+
+ mDBRefCnt = 0;
+
+ if (mRefCnt || mSliceRefCnt) {
+ return true;
+ }
+
+ // In this case, we are not responsible for removing the file info from the
+ // hashtable. It's up to FileManager which is the only caller of this method.
+
+ MOZ_ASSERT(mFileManager->Invalidated());
+
+ delete this;
+
+ return false;
+}
+
+void
+FileInfo::Cleanup()
+{
+ int64_t id = Id();
+
+ // IndexedDatabaseManager is main-thread only.
+ if (!NS_IsMainThread()) {
+ RefPtr<CleanupFileRunnable> cleaner =
+ new CleanupFileRunnable(mFileManager, id);
+
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(cleaner));
+ return;
+ }
+
+ CleanupFileRunnable::DoCleanup(mFileManager, id);
+}
+
+// static
+void
+CleanupFileRunnable::DoCleanup(FileManager* aFileManager, int64_t aFileId)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aFileManager);
+ MOZ_ASSERT(aFileId > 0);
+
+ if (NS_WARN_IF(QuotaManager::IsShuttingDown())) {
+ return;
+ }
+
+ RefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
+ MOZ_ASSERT(mgr);
+
+ if (NS_FAILED(mgr->AsyncDeleteFile(aFileManager, aFileId))) {
+ NS_WARNING("Failed to delete file asynchronously!");
+ }
+}
+
+NS_IMPL_ISUPPORTS_INHERITED0(CleanupFileRunnable, Runnable)
+
+NS_IMETHODIMP
+CleanupFileRunnable::Run()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ DoCleanup(mFileManager, mFileId);
+
+ return NS_OK;
+}
+
+} // namespace indexedDB
+} // namespace dom
+} // namespace mozilla