mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-04-04 05:32:56 +00:00
Bug 767944 - Implement a manager for centralized quota and storage handling. r=bent
This commit is contained in:
parent
4fe36b6a32
commit
8b28e5b8f1
b2g/installer
browser
content
dom
base
file
indexedDB
CheckPermissionsHelper.cppClient.cppClient.hFileInfo.cppFileManager.cppFileManager.hIDBDatabase.cppIDBDatabase.hIDBFactory.cppIDBFileHandle.cppIDBTransaction.hIndexedDatabase.hIndexedDatabaseInlines.hIndexedDatabaseManager.cppIndexedDatabaseManager.hMakefile.inOpenDatabaseHelper.cppOpenDatabaseHelper.hTransactionThreadPool.cppTransactionThreadPool.h
ipc
nsIIndexedDatabaseManager.idltest
quota
AcquireListener.hArrayCluster.hCheckQuotaHelper.cppCheckQuotaHelper.hClient.hFileStreams.cppFileStreams.hMakefile.inOriginOrPatternString.hQuotaManager.cppQuotaManager.hQuotaObject.cppQuotaObject.hStorageMatcher.hStoragePrivilege.hUsageRunnable.hUtilities.hmoz.buildnsIOfflineStorage.hnsIQuotaManager.idlnsIQuotaRequest.idlnsIUsageCallback.idl
js/xpconnect/src
layout/build
mobile/android/installer
storage/src
toolkit/forgetaboutsite
@ -202,6 +202,7 @@
|
||||
@BINPATH@/components/dom_browserelement.xpt
|
||||
@BINPATH@/components/dom_messages.xpt
|
||||
@BINPATH@/components/dom_power.xpt
|
||||
@BINPATH@/components/dom_quota.xpt
|
||||
@BINPATH@/components/dom_range.xpt
|
||||
@BINPATH@/components/dom_settings.xpt
|
||||
@BINPATH@/components/dom_permissionsettings.xpt
|
||||
|
@ -7,11 +7,11 @@ const ALLOW = nsIPermissionManager.ALLOW_ACTION; // 1
|
||||
const BLOCK = nsIPermissionManager.DENY_ACTION; // 2
|
||||
const SESSION = nsICookiePermission.ACCESS_SESSION; // 8
|
||||
|
||||
const nsIIndexedDatabaseManager =
|
||||
Components.interfaces.nsIIndexedDatabaseManager;
|
||||
const nsIQuotaManager = Components.interfaces.nsIQuotaManager;
|
||||
|
||||
var gPermURI;
|
||||
var gPrefs;
|
||||
var gUsageRequest;
|
||||
|
||||
var gPermObj = {
|
||||
image: function getImageDefaultPermission()
|
||||
@ -116,9 +116,10 @@ function onUnloadPermission()
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
os.removeObserver(permissionObserver, "perm-changed");
|
||||
|
||||
var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"]
|
||||
.getService(nsIIndexedDatabaseManager);
|
||||
dbManager.cancelGetUsageForURI(gPermURI, onIndexedDBUsageCallback);
|
||||
if (gUsageRequest) {
|
||||
gUsageRequest.cancel();
|
||||
gUsageRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
function initRow(aPartId)
|
||||
@ -205,9 +206,10 @@ function setRadioState(aPartId, aValue)
|
||||
|
||||
function initIndexedDBRow()
|
||||
{
|
||||
var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"]
|
||||
.getService(nsIIndexedDatabaseManager);
|
||||
dbManager.getUsageForURI(gPermURI, onIndexedDBUsageCallback);
|
||||
var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"]
|
||||
.getService(nsIQuotaManager);
|
||||
gUsageRequest =
|
||||
quotaManager.getUsageForURI(gPermURI, onIndexedDBUsageCallback);
|
||||
|
||||
var status = document.getElementById("indexedDBStatus");
|
||||
var button = document.getElementById("indexedDBClear");
|
||||
@ -219,9 +221,9 @@ function initIndexedDBRow()
|
||||
|
||||
function onIndexedDBClear()
|
||||
{
|
||||
Components.classes["@mozilla.org/dom/indexeddb/manager;1"]
|
||||
.getService(nsIIndexedDatabaseManager)
|
||||
.clearDatabasesForURI(gPermURI);
|
||||
Components.classes["@mozilla.org/dom/quota/manager;1"]
|
||||
.getService(nsIQuotaManager)
|
||||
.clearStoragesForURI(gPermURI);
|
||||
|
||||
var permissionManager = Components.classes[PERMISSION_CONTRACTID]
|
||||
.getService(nsIPermissionManager);
|
||||
|
@ -203,6 +203,7 @@
|
||||
#endif
|
||||
@BINPATH@/components/dom_browserelement.xpt
|
||||
@BINPATH@/components/dom_power.xpt
|
||||
@BINPATH@/components/dom_quota.xpt
|
||||
@BINPATH@/components/dom_range.xpt
|
||||
@BINPATH@/components/dom_settings.xpt
|
||||
@BINPATH@/components/dom_permissionsettings.xpt
|
||||
|
@ -156,7 +156,7 @@
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "nsEventStateManager.h"
|
||||
|
||||
@ -7638,11 +7638,11 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have running IndexedDB transactions
|
||||
indexedDB::IndexedDatabaseManager* idbManager =
|
||||
win ? indexedDB::IndexedDatabaseManager::Get() : nullptr;
|
||||
if (idbManager && idbManager->HasOpenTransactions(win)) {
|
||||
return false;
|
||||
// Check if we have running offline storage transactions
|
||||
quota::QuotaManager* quotaManager =
|
||||
win ? quota::QuotaManager::Get() : nullptr;
|
||||
if (quotaManager && quotaManager->HasOpenTransactions(win)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "DOMMediaStream.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
#include "VideoUtils.h"
|
||||
#include "MediaEngine.h"
|
||||
|
@ -63,6 +63,7 @@
|
||||
#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"
|
||||
@ -2756,8 +2757,7 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName,
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
||||
nsCString origin;
|
||||
nsresult rv = indexedDB::IndexedDatabaseManager::GetASCIIOriginFromWindow(
|
||||
window, origin);
|
||||
nsresult rv = quota::QuotaManager::GetASCIIOriginFromWindow(window, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
|
||||
|
@ -207,7 +207,7 @@
|
||||
#include "prenv.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/IDBFactory.h"
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
|
||||
#include "mozilla/dom/StructuredCloneTags.h"
|
||||
|
||||
@ -1390,11 +1390,10 @@ nsGlobalWindow::FreeInnerObjects()
|
||||
AutoPushJSContext cx(scx ? scx->GetNativeContext() : nullptr);
|
||||
mozilla::dom::workers::CancelWorkersForWindow(cx, this);
|
||||
|
||||
// Close all IndexedDB databases for this window.
|
||||
indexedDB::IndexedDatabaseManager* idbManager =
|
||||
indexedDB::IndexedDatabaseManager::Get();
|
||||
if (idbManager) {
|
||||
idbManager->AbortCloseDatabasesForWindow(this);
|
||||
// Close all offline storages for this window.
|
||||
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
|
||||
if (quotaManager) {
|
||||
quotaManager->AbortCloseStoragesForWindow(this);
|
||||
}
|
||||
|
||||
ClearAllTimeouts();
|
||||
|
@ -107,7 +107,7 @@ FileHandle::Open(FileMode aMode, ErrorResult& aError)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (FileService::IsShuttingDown() || mFileStorage->IsStorageShuttingDown()) {
|
||||
if (FileService::IsShuttingDown() || mFileStorage->IsShuttingDown()) {
|
||||
aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -152,11 +152,11 @@ FileService::Enqueue(LockedFile* aLockedFile, FileHelper* aFileHelper)
|
||||
|
||||
FileHandle* fileHandle = aLockedFile->mFileHandle;
|
||||
|
||||
if (fileHandle->mFileStorage->IsStorageInvalidated()) {
|
||||
if (fileHandle->mFileStorage->IsInvalidated()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsISupports* storageId = fileHandle->mFileStorage->StorageId();
|
||||
nsIAtom* storageId = fileHandle->mFileStorage->Id();
|
||||
const nsAString& fileName = fileHandle->mFileName;
|
||||
bool modeIsWrite = aLockedFile->mMode == LockedFile::READ_WRITE;
|
||||
|
||||
@ -226,7 +226,7 @@ FileService::NotifyLockedFileCompleted(LockedFile* aLockedFile)
|
||||
NS_ASSERTION(aLockedFile, "Null pointer!");
|
||||
|
||||
FileHandle* fileHandle = aLockedFile->mFileHandle;
|
||||
nsISupports* storageId = fileHandle->mFileStorage->StorageId();
|
||||
nsIAtom* storageId = fileHandle->mFileStorage->Id();
|
||||
|
||||
FileStorageInfo* fileStorageInfo;
|
||||
if (!mFileStorageInfos.Get(storageId, &fileStorageInfo)) {
|
||||
@ -256,10 +256,10 @@ FileService::NotifyLockedFileCompleted(LockedFile* aLockedFile)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
FileService::WaitForAllStoragesToComplete(
|
||||
nsTArray<nsCOMPtr<nsIFileStorage> >& aStorages,
|
||||
nsIRunnable* aCallback)
|
||||
void
|
||||
FileService::WaitForStoragesToComplete(
|
||||
nsTArray<nsCOMPtr<nsIFileStorage> >& aStorages,
|
||||
nsIRunnable* aCallback)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aStorages.IsEmpty(), "No databases to wait on!");
|
||||
@ -272,8 +272,6 @@ FileService::WaitForAllStoragesToComplete(
|
||||
if (MaybeFireCallback(*callback)) {
|
||||
mCompleteCallbacks.RemoveElementAt(mCompleteCallbacks.Length() - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -283,7 +281,7 @@ FileService::AbortLockedFilesForStorage(nsIFileStorage* aFileStorage)
|
||||
NS_ASSERTION(aFileStorage, "Null pointer!");
|
||||
|
||||
FileStorageInfo* fileStorageInfo;
|
||||
if (!mFileStorageInfos.Get(aFileStorage->StorageId(), &fileStorageInfo)) {
|
||||
if (!mFileStorageInfos.Get(aFileStorage->Id(), &fileStorageInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -303,7 +301,7 @@ FileService::HasLockedFilesForStorage(nsIFileStorage* aFileStorage)
|
||||
NS_ASSERTION(aFileStorage, "Null pointer!");
|
||||
|
||||
FileStorageInfo* fileStorageInfo;
|
||||
if (!mFileStorageInfos.Get(aFileStorage->StorageId(), &fileStorageInfo)) {
|
||||
if (!mFileStorageInfos.Get(aFileStorage->Id(), &fileStorageInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -330,8 +328,7 @@ FileService::MaybeFireCallback(StoragesCompleteCallback& aCallback)
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
for (uint32_t index = 0; index < aCallback.mStorages.Length(); index++) {
|
||||
if (mFileStorageInfos.Get(aCallback.mStorages[index]->StorageId(),
|
||||
nullptr)) {
|
||||
if (mFileStorageInfos.Get(aCallback.mStorages[index]->Id(), nullptr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -488,7 +485,7 @@ FileService::FileStorageInfo::RemoveLockedFileQueue(LockedFile* aLockedFile)
|
||||
|
||||
bool
|
||||
FileService::FileStorageInfo::HasRunningLockedFiles(
|
||||
nsIFileStorage* aFileStorage)
|
||||
nsIFileStorage* aFileStorage)
|
||||
{
|
||||
for (uint32_t index = 0; index < mLockedFileQueues.Length(); index++) {
|
||||
LockedFile* lockedFile = mLockedFileQueues[index]->mLockedFile;
|
||||
|
@ -46,9 +46,9 @@ public:
|
||||
void
|
||||
NotifyLockedFileCompleted(LockedFile* aLockedFile);
|
||||
|
||||
bool
|
||||
WaitForAllStoragesToComplete(nsTArray<nsCOMPtr<nsIFileStorage> >& aStorages,
|
||||
nsIRunnable* aCallback);
|
||||
void
|
||||
WaitForStoragesToComplete(nsTArray<nsCOMPtr<nsIFileStorage> >& aStorages,
|
||||
nsIRunnable* aCallback);
|
||||
|
||||
void
|
||||
AbortLockedFilesForStorage(nsIFileStorage* aFileStorage);
|
||||
@ -129,8 +129,8 @@ private:
|
||||
|
||||
inline void
|
||||
CollectRunningAndDelayedLockedFiles(
|
||||
nsIFileStorage* aFileStorage,
|
||||
nsTArray<nsRefPtr<LockedFile> >& aLockedFiles);
|
||||
nsIFileStorage* aFileStorage,
|
||||
nsTArray<nsRefPtr<LockedFile> >& aLockedFiles);
|
||||
|
||||
void
|
||||
LockFileForReading(const nsAString& aFileName)
|
||||
|
@ -384,7 +384,7 @@ LockedFile::CreateParallelStream(nsISupports** aStream)
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsIFileStorage* fileStorage = mFileHandle->mFileStorage;
|
||||
if (fileStorage->IsStorageInvalidated()) {
|
||||
if (fileStorage->IsInvalidated()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
@ -404,7 +404,7 @@ LockedFile::GetOrCreateStream(nsISupports** aStream)
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsIFileStorage* fileStorage = mFileHandle->mFileStorage;
|
||||
if (fileStorage->IsStorageInvalidated()) {
|
||||
if (fileStorage->IsInvalidated()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
@ -957,7 +957,7 @@ FinishHelper::Run()
|
||||
}
|
||||
|
||||
nsIFileStorage* fileStorage = mLockedFile->mFileHandle->mFileStorage;
|
||||
if (fileStorage->IsStorageInvalidated()) {
|
||||
if (fileStorage->IsInvalidated()) {
|
||||
mAborted = true;
|
||||
}
|
||||
|
||||
|
@ -10,52 +10,50 @@
|
||||
#include "nsISupports.h"
|
||||
|
||||
#define NS_FILESTORAGE_IID \
|
||||
{0xa0801944, 0x2f1c, 0x4203, \
|
||||
{ 0x9c, 0xaa, 0xaa, 0x47, 0xe0, 0x0c, 0x67, 0x92 } }
|
||||
{0x6278f453, 0xd557, 0x4a55, \
|
||||
{ 0x99, 0x3e, 0xf4, 0x69, 0xe2, 0xa5, 0xe1, 0xd0 } }
|
||||
|
||||
class nsIAtom;
|
||||
|
||||
class nsIFileStorage : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_FILESTORAGE_IID)
|
||||
|
||||
virtual const nsACString&
|
||||
StorageOrigin() = 0;
|
||||
NS_IMETHOD_(nsIAtom*)
|
||||
Id() = 0;
|
||||
|
||||
virtual nsISupports*
|
||||
StorageId() = 0;
|
||||
// Whether or not the storage has been invalidated. If it has then no further
|
||||
// operations for this storage will be allowed to run.
|
||||
NS_IMETHOD_(bool)
|
||||
IsInvalidated() = 0;
|
||||
|
||||
virtual bool
|
||||
IsStorageInvalidated() = 0;
|
||||
NS_IMETHOD_(bool)
|
||||
IsShuttingDown() = 0;
|
||||
|
||||
virtual bool
|
||||
IsStorageShuttingDown() = 0;
|
||||
|
||||
virtual void
|
||||
NS_IMETHOD_(void)
|
||||
SetThreadLocals() = 0;
|
||||
|
||||
virtual void
|
||||
NS_IMETHOD_(void)
|
||||
UnsetThreadLocals() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFileStorage, NS_FILESTORAGE_IID)
|
||||
|
||||
#define NS_DECL_NSIFILESTORAGE \
|
||||
virtual const nsACString& \
|
||||
StorageOrigin() MOZ_OVERRIDE; \
|
||||
NS_IMETHOD_(nsIAtom*) \
|
||||
Id() MOZ_OVERRIDE; \
|
||||
\
|
||||
virtual nsISupports* \
|
||||
StorageId() MOZ_OVERRIDE; \
|
||||
NS_IMETHOD_(bool) \
|
||||
IsInvalidated() MOZ_OVERRIDE; \
|
||||
\
|
||||
virtual bool \
|
||||
IsStorageInvalidated() MOZ_OVERRIDE; \
|
||||
NS_IMETHOD_(bool) \
|
||||
IsShuttingDown() MOZ_OVERRIDE; \
|
||||
\
|
||||
virtual bool \
|
||||
IsStorageShuttingDown() MOZ_OVERRIDE; \
|
||||
\
|
||||
virtual void \
|
||||
NS_IMETHOD_(void) \
|
||||
SetThreadLocals() MOZ_OVERRIDE; \
|
||||
\
|
||||
virtual void \
|
||||
NS_IMETHOD_(void) \
|
||||
UnsetThreadLocals() MOZ_OVERRIDE;
|
||||
|
||||
#endif // nsIFileStorage_h__
|
||||
|
@ -19,8 +19,9 @@
|
||||
#include "nsDOMStorage.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#include "IndexedDatabaseManager.h"
|
||||
|
||||
@ -140,10 +141,10 @@ CheckPermissionsHelper::Run()
|
||||
window.swap(mWindow);
|
||||
|
||||
if (permission == PERMISSION_ALLOWED) {
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||
|
||||
return helper->Dispatch(mgr->IOThread());
|
||||
return helper->Dispatch(quotaManager->IOThread());
|
||||
}
|
||||
|
||||
NS_ASSERTION(permission == PERMISSION_PROMPT ||
|
||||
|
338
dom/indexedDB/Client.cpp
Normal file
338
dom/indexedDB/Client.cpp
Normal file
@ -0,0 +1,338 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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 "Client.h"
|
||||
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#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::QuotaManager;
|
||||
|
||||
namespace {
|
||||
|
||||
bool
|
||||
GetDatabaseBaseFilename(const nsAString& aFilename,
|
||||
nsAString& aDatabaseBaseFilename)
|
||||
{
|
||||
NS_ASSERTION(!aFilename.IsEmpty(), "Bad argument!");
|
||||
|
||||
NS_NAMED_LITERAL_STRING(sqlite, ".sqlite");
|
||||
|
||||
if (!StringEndsWith(aFilename, sqlite)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aDatabaseBaseFilename =
|
||||
Substring(aFilename, 0, aFilename.Length() - sqlite.Length());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// 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)
|
||||
{
|
||||
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.
|
||||
|
||||
nsAutoTArray<nsString, 20> subdirsToProcess;
|
||||
nsAutoTArray<nsCOMPtr<nsIFile> , 20> unknownFiles;
|
||||
nsTHashtable<nsStringHashKey> validSubdirs;
|
||||
validSubdirs.Init(20);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
||||
hasMore && (!aUsageRunnable || !aUsageRunnable->Canceled())) {
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
rv = entries->GetNext(getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
|
||||
NS_ENSURE_TRUE(file, NS_NOINTERFACE);
|
||||
|
||||
nsString leafName;
|
||||
rv = file->GetLeafName(leafName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isDirectory;
|
||||
rv = file->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isDirectory) {
|
||||
if (!validSubdirs.GetEntry(leafName)) {
|
||||
subdirsToProcess.AppendElement(leafName);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nsString dbBaseFilename;
|
||||
if (!GetDatabaseBaseFilename(leafName, dbBaseFilename)) {
|
||||
unknownFiles.AppendElement(file);
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> fmDirectory;
|
||||
rv = directory->Clone(getter_AddRefs(fmDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = fmDirectory->Append(dbBaseFilename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = FileManager::InitDirectory(fmDirectory, file, aOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aUsageRunnable) {
|
||||
int64_t fileSize;
|
||||
rv = file->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aUsageRunnable->AppendToDatabaseUsage(uint64_t(fileSize));
|
||||
|
||||
uint64_t usage;
|
||||
rv = FileManager::GetUsage(fmDirectory, &usage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aUsageRunnable->AppendToFileUsage(usage);
|
||||
}
|
||||
|
||||
validSubdirs.PutEntry(dbBaseFilename);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (uint32_t i = 0; i < subdirsToProcess.Length(); i++) {
|
||||
const nsString& subdir = subdirsToProcess[i];
|
||||
if (!validSubdirs.GetEntry(subdir)) {
|
||||
NS_WARNING("Unknown subdirectory found!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < unknownFiles.Length(); 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);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (exists) {
|
||||
nsString leafName;
|
||||
unknownFile->GetLeafName(leafName);
|
||||
|
||||
// The journal file may exists even after db has been correctly opened.
|
||||
if (!StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
|
||||
NS_WARNING("Unknown file found!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Client::GetUsageForOrigin(const nsACString& aOrigin,
|
||||
UsageRunnable* aUsageRunnable)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool
|
||||
Client::IsTransactionServiceActivated()
|
||||
{
|
||||
return !!TransactionThreadPool::Get();
|
||||
}
|
||||
|
||||
void
|
||||
Client::WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
||||
nsIRunnable* aCallback)
|
||||
{
|
||||
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<IDBDatabase*> databases(aStorages.Length());
|
||||
for (uint32_t index = 0; index < aStorages.Length(); index++) {
|
||||
IDBDatabase* database = IDBDatabase::FromStorage(aStorages[index]);
|
||||
NS_ASSERTION(database, "This shouldn't be null!");
|
||||
|
||||
databases.AppendElement(database);
|
||||
}
|
||||
|
||||
pool->WaitForDatabasesToComplete(databases, aCallback);
|
||||
}
|
||||
|
||||
void
|
||||
Client::AbortTransactionsForStorage(nsIOfflineStorage* aStorage)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
void
|
||||
Client::OnShutdownCompleted()
|
||||
{
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
if (mgr) {
|
||||
mgr->InvalidateAllFileManagers();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
Client::GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory)
|
||||
{
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never fail!");
|
||||
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv =
|
||||
quotaManager->GetDirectoryForOrigin(aOrigin, getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(directory, "What?");
|
||||
|
||||
rv = directory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
directory.forget(aDirectory);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Client::GetUsageForDirectoryInternal(nsIFile* aDirectory,
|
||||
UsageRunnable* aUsageRunnable,
|
||||
bool aDatabaseFiles)
|
||||
{
|
||||
NS_ASSERTION(aDirectory, "Null pointer!");
|
||||
NS_ASSERTION(aUsageRunnable, "Null pointer!");
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!entries) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
||||
hasMore && !aUsageRunnable->Canceled()) {
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
rv = entries->GetNext(getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file(do_QueryInterface(entry));
|
||||
NS_ASSERTION(file, "Don't know what this is!");
|
||||
|
||||
bool isDirectory;
|
||||
rv = file->IsDirectory(&isDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isDirectory) {
|
||||
if (aDatabaseFiles) {
|
||||
rv = GetUsageForDirectoryInternal(file, aUsageRunnable, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
nsString leafName;
|
||||
rv = file->GetLeafName(leafName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!leafName.EqualsLiteral(JOURNAL_DIRECTORY_NAME)) {
|
||||
NS_WARNING("Unknown directory found!");
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int64_t fileSize;
|
||||
rv = file->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(fileSize >= 0, "Negative size?!");
|
||||
|
||||
if (aDatabaseFiles) {
|
||||
aUsageRunnable->AppendToDatabaseUsage(uint64_t(fileSize));
|
||||
}
|
||||
else {
|
||||
aUsageRunnable->AppendToFileUsage(uint64_t(fileSize));
|
||||
}
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
87
dom/indexedDB/Client.h
Normal file
87
dom/indexedDB/Client.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_indexeddb_client_h__
|
||||
#define mozilla_dom_indexeddb_client_h__
|
||||
|
||||
#include "IndexedDatabase.h"
|
||||
|
||||
#include "mozilla/dom/quota/Client.h"
|
||||
|
||||
#define IDB_DIRECTORY_NAME "idb"
|
||||
#define JOURNAL_DIRECTORY_NAME "journals"
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class Client : public mozilla::dom::quota::Client
|
||||
{
|
||||
typedef mozilla::dom::quota::UsageRunnable UsageRunnable;
|
||||
|
||||
public:
|
||||
NS_IMETHOD_(nsrefcnt)
|
||||
AddRef() MOZ_OVERRIDE;
|
||||
|
||||
NS_IMETHOD_(nsrefcnt)
|
||||
Release() MOZ_OVERRIDE;
|
||||
|
||||
virtual Type
|
||||
GetType() MOZ_OVERRIDE
|
||||
{
|
||||
return IDB;
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
InitOrigin(const nsACString& aOrigin,
|
||||
UsageRunnable* aUsageRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
GetUsageForOrigin(const nsACString& aOrigin,
|
||||
UsageRunnable* aUsageRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
IsFileServiceUtilized() MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
IsTransactionServiceActivated() MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
||||
nsIRunnable* aCallback) MOZ_OVERRIDE;
|
||||
|
||||
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);
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_client_h__
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "FileInfo.h"
|
||||
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
// static
|
||||
@ -91,7 +93,7 @@ FileInfo::UpdateReferences(nsAutoRefCnt& aRefCount, int32_t aDelta,
|
||||
void
|
||||
FileInfo::Cleanup()
|
||||
{
|
||||
if (IndexedDatabaseManager::IsShuttingDown() ||
|
||||
if (quota::QuotaManager::IsShuttingDown() ||
|
||||
mFileManager->Invalidated()) {
|
||||
return;
|
||||
}
|
||||
|
@ -11,9 +11,11 @@
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
#include "mozilla/dom/quota/Utilities.h"
|
||||
#include "mozStorageCID.h"
|
||||
#include "mozStorageHelper.h"
|
||||
|
||||
#include "Client.h"
|
||||
#include "FileInfo.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "OpenDatabaseHelper.h"
|
||||
@ -21,8 +23,6 @@
|
||||
#include "IndexedDatabaseInlines.h"
|
||||
#include <algorithm>
|
||||
|
||||
#define JOURNAL_DIRECTORY_NAME "journals"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
namespace {
|
||||
@ -412,7 +412,7 @@ FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage)
|
||||
rv = file->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
IncrementUsage(&usage, uint64_t(fileSize));
|
||||
quota::IncrementUsage(&usage, uint64_t(fileSize));
|
||||
}
|
||||
|
||||
*aUsage = usage;
|
||||
|
@ -8,12 +8,14 @@
|
||||
#define mozilla_dom_indexeddb_filemanager_h__
|
||||
|
||||
#include "IndexedDatabase.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
#include "mozilla/dom/quota/StoragePrivilege.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
class mozIStorageConnection;
|
||||
class mozIStorageServiceQuotaManagement;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
@ -23,8 +25,10 @@ class FileManager
|
||||
{
|
||||
friend class FileInfo;
|
||||
|
||||
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
||||
|
||||
public:
|
||||
FileManager(const nsACString& aOrigin, FactoryPrivilege aPrivilege,
|
||||
FileManager(const nsACString& aOrigin, StoragePrivilege aPrivilege,
|
||||
const nsAString& aDatabaseName)
|
||||
: mOrigin(aOrigin), mPrivilege(aPrivilege), mDatabaseName(aDatabaseName),
|
||||
mLastFileId(0), mInvalidated(false)
|
||||
@ -40,7 +44,7 @@ public:
|
||||
return mOrigin;
|
||||
}
|
||||
|
||||
const FactoryPrivilege& Privilege() const
|
||||
const StoragePrivilege& Privilege() const
|
||||
{
|
||||
return mPrivilege;
|
||||
}
|
||||
@ -81,7 +85,7 @@ public:
|
||||
|
||||
private:
|
||||
nsCString mOrigin;
|
||||
FactoryPrivilege mPrivilege;
|
||||
StoragePrivilege mPrivilege;
|
||||
nsString mDatabaseName;
|
||||
|
||||
nsString mDirectoryPath;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/quota/Client.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMLists.h"
|
||||
@ -27,7 +28,6 @@
|
||||
#include "IDBObjectStore.h"
|
||||
#include "IDBTransaction.h"
|
||||
#include "IDBFactory.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "TransactionThreadPool.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -37,6 +37,7 @@
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using mozilla::dom::ContentParent;
|
||||
using mozilla::dom::quota::Client;
|
||||
using mozilla::dom::quota::QuotaManager;
|
||||
|
||||
namespace {
|
||||
@ -199,17 +200,30 @@ IDBDatabase::Create(IDBWrapperCache* aOwnerCache,
|
||||
db->mFileManager = aFileManager;
|
||||
db->mContentParent = aContentParent;
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||
|
||||
if (!mgr->RegisterDatabase(db)) {
|
||||
db->mQuotaClient = quotaManager->GetClient(Client::IDB);
|
||||
NS_ASSERTION(db->mQuotaClient, "This shouldn't fail!");
|
||||
|
||||
if (!quotaManager->RegisterStorage(db)) {
|
||||
// Either out of memory or shutting down.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
db->mRegistered = true;
|
||||
|
||||
return db.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
IDBDatabase*
|
||||
IDBDatabase::FromStorage(nsIOfflineStorage* aStorage)
|
||||
{
|
||||
return aStorage->GetClient()->GetType() == Client::IDB ?
|
||||
static_cast<IDBDatabase*>(aStorage) : nullptr;
|
||||
}
|
||||
|
||||
IDBDatabase::IDBDatabase()
|
||||
: mDatabaseId(0),
|
||||
mActorChild(nullptr),
|
||||
@ -237,14 +251,14 @@ IDBDatabase::~IDBDatabase()
|
||||
if (mRegistered) {
|
||||
CloseInternal(true);
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
if (mgr) {
|
||||
mgr->UnregisterDatabase(this);
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
if (quotaManager) {
|
||||
quotaManager->UnregisterStorage(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NS_IMETHODIMP_(void)
|
||||
IDBDatabase::Invalidate()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
@ -311,9 +325,9 @@ IDBDatabase::CloseInternal(bool aIsDead)
|
||||
}
|
||||
}
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
if (mgr) {
|
||||
mgr->OnDatabaseClosed(this);
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
if (quotaManager) {
|
||||
quotaManager->OnStorageClosed(this);
|
||||
}
|
||||
|
||||
// And let the parent process know as well.
|
||||
@ -324,8 +338,8 @@ IDBDatabase::CloseInternal(bool aIsDead)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsClosed() const
|
||||
NS_IMETHODIMP_(bool)
|
||||
IDBDatabase::IsClosed()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mClosed;
|
||||
@ -367,10 +381,10 @@ IDBDatabase::OnUnlink()
|
||||
// transactions from starting and unblock any other SetVersion callers.
|
||||
CloseInternal(true);
|
||||
|
||||
// No reason for the IndexedDatabaseManager to track us any longer.
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
if (mgr) {
|
||||
mgr->UnregisterDatabase(this);
|
||||
// No reason for the QuotaManager to track us any longer.
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
if (quotaManager) {
|
||||
quotaManager->UnregisterStorage(this);
|
||||
|
||||
// Don't try to unregister again in the destructor.
|
||||
mRegistered = false;
|
||||
@ -433,6 +447,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBDatabase)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIIDBDatabase)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIFileStorage)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIOfflineStorage)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBDatabase)
|
||||
NS_INTERFACE_MAP_END_INHERITING(IDBWrapperCache)
|
||||
|
||||
@ -602,7 +617,7 @@ IDBDatabase::Transaction(const jsval& aStoreNames,
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (IndexedDatabaseManager::IsShuttingDown()) {
|
||||
if (QuotaManager::IsShuttingDown()) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
@ -744,7 +759,7 @@ IDBDatabase::MozCreateFileHandle(const nsAString& aName,
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
if (IndexedDatabaseManager::IsShuttingDown()) {
|
||||
if (QuotaManager::IsShuttingDown()) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
@ -757,10 +772,10 @@ IDBDatabase::MozCreateFileHandle(const nsAString& aName,
|
||||
nsRefPtr<CreateFileHelper> helper =
|
||||
new CreateFileHelper(this, request, aName, aType);
|
||||
|
||||
IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(manager, "We should definitely have a manager here");
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "We should definitely have a manager here");
|
||||
|
||||
nsresult rv = helper->Dispatch(manager->IOThread());
|
||||
nsresult rv = helper->Dispatch(quotaManager->IOThread());
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
request.forget(_retval);
|
||||
@ -778,43 +793,55 @@ IDBDatabase::Close()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const nsACString&
|
||||
IDBDatabase::StorageOrigin()
|
||||
NS_IMETHODIMP_(nsIAtom*)
|
||||
IDBDatabase::Id()
|
||||
{
|
||||
return Origin();
|
||||
return mDatabaseId;
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
IDBDatabase::StorageId()
|
||||
NS_IMETHODIMP_(bool)
|
||||
IDBDatabase::IsInvalidated()
|
||||
{
|
||||
return Id();
|
||||
return mInvalidated;
|
||||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsStorageInvalidated()
|
||||
NS_IMETHODIMP_(bool)
|
||||
IDBDatabase::IsShuttingDown()
|
||||
{
|
||||
return IsInvalidated();
|
||||
return QuotaManager::IsShuttingDown();
|
||||
}
|
||||
|
||||
bool
|
||||
IDBDatabase::IsStorageShuttingDown()
|
||||
{
|
||||
return IndexedDatabaseManager::IsShuttingDown();
|
||||
}
|
||||
|
||||
void
|
||||
NS_IMETHODIMP_(void)
|
||||
IDBDatabase::SetThreadLocals()
|
||||
{
|
||||
NS_ASSERTION(GetOwner(), "Should have owner!");
|
||||
QuotaManager::SetCurrentWindow(GetOwner());
|
||||
}
|
||||
|
||||
void
|
||||
NS_IMETHODIMP_(void)
|
||||
IDBDatabase::UnsetThreadLocals()
|
||||
{
|
||||
QuotaManager::SetCurrentWindow(nullptr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(mozilla::dom::quota::Client*)
|
||||
IDBDatabase::GetClient()
|
||||
{
|
||||
return mQuotaClient;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
IDBDatabase::IsOwned(nsPIDOMWindow* aOwner)
|
||||
{
|
||||
return GetOwner() == aOwner;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(const nsACString&)
|
||||
IDBDatabase::Origin()
|
||||
{
|
||||
return mASCIIOrigin;
|
||||
}
|
||||
|
||||
nsresult
|
||||
IDBDatabase::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
{
|
||||
|
@ -12,9 +12,12 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIFileStorage.h"
|
||||
#include "nsIIDBDatabase.h"
|
||||
#include "nsIOfflineStorage.h"
|
||||
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/FileManager.h"
|
||||
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
class nsPIDOMWindow;
|
||||
@ -22,6 +25,9 @@ class nsPIDOMWindow;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
namespace quota {
|
||||
class Client;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +46,7 @@ struct ObjectStoreInfoGuts;
|
||||
|
||||
class IDBDatabase : public IDBWrapperCache,
|
||||
public nsIIDBDatabase,
|
||||
public nsIFileStorage
|
||||
public nsIOfflineStorage
|
||||
{
|
||||
friend class AsyncConnectionHelper;
|
||||
friend class IndexedDatabaseManager;
|
||||
@ -50,6 +56,7 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIIDBDATABASE
|
||||
NS_DECL_NSIFILESTORAGE
|
||||
NS_DECL_NSIOFFLINESTORAGE_NOCLOSE
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase, IDBWrapperCache)
|
||||
|
||||
@ -61,14 +68,19 @@ public:
|
||||
FileManager* aFileManager,
|
||||
mozilla::dom::ContentParent* aContentParent);
|
||||
|
||||
static IDBDatabase*
|
||||
FromStorage(nsIOfflineStorage* aStorage);
|
||||
|
||||
static IDBDatabase*
|
||||
FromStorage(nsIFileStorage* aStorage)
|
||||
{
|
||||
nsCOMPtr<nsIOfflineStorage> storage = do_QueryInterface(aStorage);
|
||||
return storage ? FromStorage(storage) : nullptr;
|
||||
}
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
|
||||
|
||||
nsIAtom* Id() const
|
||||
{
|
||||
return mDatabaseId;
|
||||
}
|
||||
|
||||
DatabaseInfo* Info() const
|
||||
{
|
||||
return mDatabaseInfo;
|
||||
@ -95,28 +107,10 @@ public:
|
||||
return doc.forget();
|
||||
}
|
||||
|
||||
const nsCString& Origin() const
|
||||
{
|
||||
return mASCIIOrigin;
|
||||
}
|
||||
|
||||
void Invalidate();
|
||||
|
||||
// Whether or not the database has been invalidated. If it has then no further
|
||||
// transactions for this database will be allowed to run. This function may be
|
||||
// called on any thread.
|
||||
bool IsInvalidated() const
|
||||
{
|
||||
return mInvalidated;
|
||||
}
|
||||
|
||||
void DisconnectFromActorParent();
|
||||
|
||||
void CloseInternal(bool aIsDead);
|
||||
|
||||
// Whether or not the database has had Close called on it.
|
||||
bool IsClosed() const;
|
||||
|
||||
void EnterSetVersionTransaction();
|
||||
void ExitSetVersionTransaction();
|
||||
|
||||
@ -195,6 +189,8 @@ private:
|
||||
|
||||
mozilla::dom::ContentParent* mContentParent;
|
||||
|
||||
nsRefPtr<mozilla::dom::quota::Client> mQuotaClient;
|
||||
|
||||
bool mInvalidated;
|
||||
bool mRegistered;
|
||||
bool mClosed;
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/PBrowserChild.h"
|
||||
#include "mozilla/dom/quota/OriginOrPatternString.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
@ -45,6 +47,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
USING_QUOTA_NAMESPACE
|
||||
|
||||
using mozilla::dom::ContentChild;
|
||||
using mozilla::dom::ContentParent;
|
||||
@ -103,7 +106,7 @@ IDBFactory::Create(nsPIDOMWindow* aWindow,
|
||||
|
||||
// Make sure that the manager is up before we do anything here since lots of
|
||||
// decisions depend on which process we're running in.
|
||||
nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
|
||||
indexedDB::IndexedDatabaseManager* mgr =
|
||||
indexedDB::IndexedDatabaseManager::GetOrCreate();
|
||||
NS_ENSURE_TRUE(mgr, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
@ -111,7 +114,7 @@ IDBFactory::Create(nsPIDOMWindow* aWindow,
|
||||
|
||||
nsCString origin(aASCIIOrigin);
|
||||
if (origin.IsEmpty()) {
|
||||
rv = IndexedDatabaseManager::GetASCIIOriginFromWindow(aWindow, origin);
|
||||
rv = QuotaManager::GetASCIIOriginFromWindow(aWindow, origin);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Not allowed.
|
||||
*aFactory = nullptr;
|
||||
@ -161,8 +164,7 @@ IDBFactory::Create(JSContext* aCx,
|
||||
NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
|
||||
|
||||
nsCString origin;
|
||||
nsresult rv =
|
||||
IndexedDatabaseManager::GetASCIIOriginFromWindow(nullptr, origin);
|
||||
nsresult rv = QuotaManager::GetASCIIOriginFromWindow(nullptr, origin);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
nsRefPtr<IDBFactory> factory = new IDBFactory();
|
||||
@ -521,7 +523,7 @@ IDBFactory::OpenCommon(const nsAString& aName,
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window;
|
||||
JSObject* scriptOwner = nullptr;
|
||||
FactoryPrivilege privilege;
|
||||
StoragePrivilege privilege;
|
||||
|
||||
if (mWindow) {
|
||||
window = mWindow;
|
||||
@ -551,17 +553,17 @@ IDBFactory::OpenCommon(const nsAString& aName,
|
||||
nsRefPtr<CheckPermissionsHelper> permissionHelper =
|
||||
new CheckPermissionsHelper(openHelper, window, aDeleting);
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||
|
||||
rv =
|
||||
mgr->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(aASCIIOrigin),
|
||||
openHelper->Id(), permissionHelper);
|
||||
rv = quotaManager->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(
|
||||
aASCIIOrigin), openHelper->Id(),
|
||||
permissionHelper);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
}
|
||||
else if (aDeleting) {
|
||||
nsCOMPtr<nsIAtom> databaseId =
|
||||
IndexedDatabaseManager::GetDatabaseId(aASCIIOrigin, aName);
|
||||
QuotaManager::GetStorageId(aASCIIOrigin, aName);
|
||||
NS_ENSURE_TRUE(databaseId, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
IndexedDBDeleteDatabaseRequestChild* actor =
|
||||
|
@ -67,7 +67,10 @@ IDBFileHandle::Create(IDBDatabase* aDatabase,
|
||||
already_AddRefed<nsISupports>
|
||||
IDBFileHandle::CreateStream(nsIFile* aFile, bool aReadOnly)
|
||||
{
|
||||
const nsACString& origin = mFileStorage->StorageOrigin();
|
||||
nsCOMPtr<nsIOfflineStorage> storage = do_QueryInterface(mFileStorage);
|
||||
NS_ASSERTION(storage, "This should always succeed!");
|
||||
|
||||
const nsACString& origin = storage->Origin();
|
||||
|
||||
nsCOMPtr<nsISupports> result;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/IDBDatabase.h"
|
||||
#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
|
||||
|
@ -36,11 +36,6 @@ class FileInfo;
|
||||
class IDBDatabase;
|
||||
class IDBTransaction;
|
||||
|
||||
enum FactoryPrivilege {
|
||||
Content,
|
||||
Chrome
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void SwapData(T& aData1, T& aData2)
|
||||
{
|
||||
@ -175,44 +170,6 @@ struct SerializedStructuredCloneWriteInfo
|
||||
uint64_t offsetToKeyProp;
|
||||
};
|
||||
|
||||
class OriginOrPatternString : public nsCString
|
||||
{
|
||||
public:
|
||||
static OriginOrPatternString
|
||||
FromOrigin(const nsACString& aOrigin)
|
||||
{
|
||||
return OriginOrPatternString(aOrigin, true);
|
||||
}
|
||||
|
||||
static OriginOrPatternString
|
||||
FromPattern(const nsACString& aPattern)
|
||||
{
|
||||
return OriginOrPatternString(aPattern, false);
|
||||
}
|
||||
|
||||
bool
|
||||
IsOrigin() const
|
||||
{
|
||||
return mIsOrigin;
|
||||
}
|
||||
|
||||
bool
|
||||
IsPattern() const
|
||||
{
|
||||
return !mIsOrigin;
|
||||
}
|
||||
|
||||
private:
|
||||
OriginOrPatternString(const nsACString& aOriginOrPattern, bool aIsOrigin)
|
||||
: nsCString(aOriginOrPattern), mIsOrigin(aIsOrigin)
|
||||
{ }
|
||||
|
||||
bool
|
||||
operator==(const OriginOrPatternString& aOther) MOZ_DELETE;
|
||||
|
||||
bool mIsOrigin;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_indexeddatabase_h__
|
||||
|
@ -79,17 +79,4 @@ AppendConditionClause(const nsACString& aColumnName,
|
||||
aResult += NS_LITERAL_CSTRING(" :") + aArgName;
|
||||
}
|
||||
|
||||
inline void
|
||||
IncrementUsage(uint64_t* aUsage, uint64_t aDelta)
|
||||
{
|
||||
// Watch for overflow!
|
||||
if ((UINT64_MAX - *aUsage) < aDelta) {
|
||||
NS_WARNING("Usage exceeds the maximum!");
|
||||
*aUsage = UINT64_MAX;
|
||||
}
|
||||
else {
|
||||
*aUsage += aDelta;
|
||||
}
|
||||
}
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,23 +9,15 @@
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
#include "nsIIndexedDatabaseManager.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#define INDEXEDDB_MANAGER_CONTRACTID "@mozilla.org/dom/indexeddb/manager;1"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIFile;
|
||||
class nsITimer;
|
||||
class nsPIDOMWindow;
|
||||
class nsEventChainPostVisitor;
|
||||
|
||||
@ -35,96 +27,30 @@ class TabContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class AsyncConnectionHelper;
|
||||
class FileManager;
|
||||
class IDBDatabase;
|
||||
|
||||
class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager,
|
||||
public nsIObserver
|
||||
class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager
|
||||
{
|
||||
friend class IDBDatabase;
|
||||
|
||||
public:
|
||||
static already_AddRefed<IndexedDatabaseManager> GetOrCreate();
|
||||
|
||||
// Returns a non-owning reference.
|
||||
static IndexedDatabaseManager* Get();
|
||||
|
||||
// Returns an owning reference! No one should call this but the factory.
|
||||
static IndexedDatabaseManager* FactoryCreate();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINDEXEDDATABASEMANAGER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// Waits for databases to be cleared and for version change transactions to
|
||||
// complete before dispatching the given runnable.
|
||||
nsresult WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId,
|
||||
nsIRunnable* aRunnable);
|
||||
// Returns a non-owning reference.
|
||||
static IndexedDatabaseManager*
|
||||
GetOrCreate();
|
||||
|
||||
void AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId);
|
||||
// Returns a non-owning reference.
|
||||
static IndexedDatabaseManager*
|
||||
Get();
|
||||
|
||||
nsIThread* IOThread()
|
||||
{
|
||||
NS_ASSERTION(mIOThread, "This should never be null!");
|
||||
return mIOThread;
|
||||
}
|
||||
// Returns an owning reference! No one should call this but the factory.
|
||||
static IndexedDatabaseManager*
|
||||
FactoryCreate();
|
||||
|
||||
// Returns true if we've begun the shutdown process.
|
||||
static bool IsShuttingDown();
|
||||
|
||||
static bool IsClosed();
|
||||
|
||||
typedef void
|
||||
(*WaitingOnDatabasesCallback)(nsTArray<nsRefPtr<IDBDatabase> >&, void*);
|
||||
|
||||
// Acquire exclusive access to the database given (waits for all others to
|
||||
// close). If databases need to close first, the callback will be invoked
|
||||
// with an array of said databases.
|
||||
nsresult AcquireExclusiveAccess(IDBDatabase* aDatabase,
|
||||
const nsACString& aOrigin,
|
||||
AsyncConnectionHelper* aHelper,
|
||||
WaitingOnDatabasesCallback aCallback,
|
||||
void* aClosure)
|
||||
{
|
||||
NS_ASSERTION(aDatabase, "Need a DB here!");
|
||||
return AcquireExclusiveAccess(aOrigin, aDatabase, aHelper, nullptr,
|
||||
aCallback, aClosure);
|
||||
}
|
||||
|
||||
nsresult AcquireExclusiveAccess(const nsACString& aOrigin,
|
||||
nsIRunnable* aRunnable,
|
||||
WaitingOnDatabasesCallback aCallback,
|
||||
void* aClosure)
|
||||
{
|
||||
return AcquireExclusiveAccess(aOrigin, nullptr, nullptr, aRunnable, aCallback,
|
||||
aClosure);
|
||||
}
|
||||
|
||||
// Called when a window is being purged from the bfcache or the user leaves
|
||||
// a page which isn't going into the bfcache. Forces any live database
|
||||
// objects to close themselves and aborts any running transactions.
|
||||
void AbortCloseDatabasesForWindow(nsPIDOMWindow* aWindow);
|
||||
|
||||
// Used to check if there are running transactions in a given window.
|
||||
bool HasOpenTransactions(nsPIDOMWindow* aWindow);
|
||||
|
||||
static uint32_t
|
||||
GetIndexedDBQuotaMB();
|
||||
|
||||
nsresult EnsureOriginIsInitialized(const nsACString& aOrigin,
|
||||
FactoryPrivilege aPrivilege,
|
||||
nsIFile** aDirectory);
|
||||
|
||||
void UninitializeOriginsByPattern(const nsACString& aPattern);
|
||||
|
||||
static nsresult
|
||||
GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow, nsCString& aASCIIOrigin);
|
||||
static bool
|
||||
IsClosed();
|
||||
|
||||
static bool
|
||||
IsMainProcess()
|
||||
@ -143,25 +69,22 @@ public:
|
||||
void
|
||||
AddFileManager(FileManager* aFileManager);
|
||||
|
||||
void InvalidateFileManagersForPattern(const nsACString& aPattern);
|
||||
void
|
||||
InvalidateAllFileManagers();
|
||||
|
||||
void InvalidateFileManager(const nsACString& aOrigin,
|
||||
const nsAString& aDatabaseName);
|
||||
void
|
||||
InvalidateFileManagersForPattern(const nsACString& aPattern);
|
||||
|
||||
nsresult AsyncDeleteFile(FileManager* aFileManager,
|
||||
int64_t aFileId);
|
||||
|
||||
const nsString&
|
||||
GetBaseDirectory() const
|
||||
{
|
||||
return mDatabaseBasePath;
|
||||
}
|
||||
void
|
||||
InvalidateFileManager(const nsACString& aOrigin,
|
||||
const nsAString& aDatabaseName);
|
||||
|
||||
nsresult
|
||||
GetDirectoryForOrigin(const nsACString& aASCIIOrigin,
|
||||
nsIFile** aDirectory) const;
|
||||
AsyncDeleteFile(FileManager* aFileManager,
|
||||
int64_t aFileId);
|
||||
|
||||
static mozilla::Mutex& FileMutex()
|
||||
static mozilla::Mutex&
|
||||
FileMutex()
|
||||
{
|
||||
IndexedDatabaseManager* mgr = Get();
|
||||
NS_ASSERTION(mgr, "Must have a manager here!");
|
||||
@ -169,10 +92,6 @@ public:
|
||||
return mgr->mFileMutex;
|
||||
}
|
||||
|
||||
static already_AddRefed<nsIAtom>
|
||||
GetDatabaseId(const nsACString& aOrigin,
|
||||
const nsAString& aName);
|
||||
|
||||
static nsresult
|
||||
FireWindowOnError(nsPIDOMWindow* aOwner,
|
||||
nsEventChainPostVisitor& aVisitor);
|
||||
@ -185,288 +104,22 @@ private:
|
||||
IndexedDatabaseManager();
|
||||
~IndexedDatabaseManager();
|
||||
|
||||
nsresult AcquireExclusiveAccess(const nsACString& aOrigin,
|
||||
IDBDatabase* aDatabase,
|
||||
AsyncConnectionHelper* aHelper,
|
||||
nsIRunnable* aRunnable,
|
||||
WaitingOnDatabasesCallback aCallback,
|
||||
void* aClosure);
|
||||
nsresult
|
||||
Init();
|
||||
|
||||
// Called when a database is created.
|
||||
bool RegisterDatabase(IDBDatabase* aDatabase);
|
||||
|
||||
// Called when a database is being unlinked or destroyed.
|
||||
void UnregisterDatabase(IDBDatabase* aDatabase);
|
||||
|
||||
// Called when a database has been closed.
|
||||
void OnDatabaseClosed(IDBDatabase* aDatabase);
|
||||
|
||||
nsresult ClearDatabasesForApp(uint32_t aAppId, bool aBrowserOnly);
|
||||
|
||||
// Responsible for clearing the database files for a particular origin on the
|
||||
// IO thread. Created when nsIIDBIndexedDatabaseManager::ClearDatabasesForURI
|
||||
// is called. Runs three times, first on the main thread, next on the IO
|
||||
// thread, and then finally again on the main thread. While on the IO thread
|
||||
// the runnable will actually remove the origin's database files and the
|
||||
// directory that contains them before dispatching itself back to the main
|
||||
// thread. When back on the main thread the runnable will notify the
|
||||
// IndexedDatabaseManager that the job has been completed.
|
||||
class OriginClearRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
enum CallbackState {
|
||||
// Not yet run.
|
||||
Pending = 0,
|
||||
|
||||
// Running on the main thread in the callback for OpenAllowed.
|
||||
OpenAllowed,
|
||||
|
||||
// Running on the IO thread.
|
||||
IO,
|
||||
|
||||
// Running on the main thread after all work is done.
|
||||
Complete
|
||||
};
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
OriginClearRunnable(const OriginOrPatternString& aOriginOrPattern)
|
||||
: mOriginOrPattern(aOriginOrPattern),
|
||||
mCallbackState(Pending)
|
||||
{ }
|
||||
|
||||
void AdvanceState()
|
||||
{
|
||||
switch (mCallbackState) {
|
||||
case Pending:
|
||||
mCallbackState = OpenAllowed;
|
||||
return;
|
||||
case OpenAllowed:
|
||||
mCallbackState = IO;
|
||||
return;
|
||||
case IO:
|
||||
mCallbackState = Complete;
|
||||
return;
|
||||
default:
|
||||
NS_NOTREACHED("Can't advance past Complete!");
|
||||
}
|
||||
}
|
||||
|
||||
static void InvalidateOpenedDatabases(
|
||||
nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
|
||||
void* aClosure);
|
||||
|
||||
void DeleteFiles(IndexedDatabaseManager* aManager);
|
||||
|
||||
private:
|
||||
OriginOrPatternString mOriginOrPattern;
|
||||
CallbackState mCallbackState;
|
||||
};
|
||||
|
||||
// Responsible for calculating the amount of space taken up by databases of a
|
||||
// certain origin. Created when nsIIDBIndexedDatabaseManager::GetUsageForURI
|
||||
// is called. May be canceled with
|
||||
// nsIIDBIndexedDatabaseManager::CancelGetUsageForURI. Runs twice, first on
|
||||
// the IO thread, then again on the main thread. While on the IO thread the
|
||||
// runnable will calculate the size of all files in the origin's directory
|
||||
// before dispatching itself back to the main thread. When on the main thread
|
||||
// the runnable will call the callback and then notify the
|
||||
// IndexedDatabaseManager that the job has been completed.
|
||||
class AsyncUsageRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
enum CallbackState {
|
||||
// Not yet run.
|
||||
Pending = 0,
|
||||
|
||||
// Running on the main thread in the callback for OpenAllowed.
|
||||
OpenAllowed,
|
||||
|
||||
// Running on the IO thread.
|
||||
IO,
|
||||
|
||||
// Running on the main thread after all work is done.
|
||||
Complete,
|
||||
|
||||
// Running on the main thread after skipping the work
|
||||
Shortcut
|
||||
};
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
AsyncUsageRunnable(uint32_t aAppId,
|
||||
bool aInMozBrowserOnly,
|
||||
const OriginOrPatternString& aOrigin,
|
||||
nsIURI* aURI,
|
||||
nsIIndexedDatabaseUsageCallback* aCallback);
|
||||
|
||||
// Sets the canceled flag so that the callback is never called.
|
||||
void Cancel();
|
||||
|
||||
void AdvanceState()
|
||||
{
|
||||
switch (mCallbackState) {
|
||||
case Pending:
|
||||
mCallbackState = OpenAllowed;
|
||||
return;
|
||||
case OpenAllowed:
|
||||
mCallbackState = IO;
|
||||
return;
|
||||
case IO:
|
||||
mCallbackState = Complete;
|
||||
return;
|
||||
default:
|
||||
NS_NOTREACHED("Can't advance past Complete!");
|
||||
}
|
||||
}
|
||||
|
||||
nsresult TakeShortcut();
|
||||
|
||||
// Run calls the RunInternal method and makes sure that we always dispatch
|
||||
// to the main thread in case of an error.
|
||||
inline nsresult RunInternal();
|
||||
|
||||
nsresult GetUsageForDirectory(nsIFile* aDirectory,
|
||||
uint64_t* aUsage);
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIIndexedDatabaseUsageCallback> mCallback;
|
||||
uint64_t mUsage;
|
||||
uint64_t mFileUsage;
|
||||
uint32_t mAppId;
|
||||
int32_t mCanceled;
|
||||
OriginOrPatternString mOrigin;
|
||||
CallbackState mCallbackState;
|
||||
bool mInMozBrowserOnly;
|
||||
};
|
||||
|
||||
// Called when AsyncUsageRunnable has finished its Run() method.
|
||||
inline void OnUsageCheckComplete(AsyncUsageRunnable* aRunnable);
|
||||
|
||||
// A struct that contains the information corresponding to a pending or
|
||||
// running operation that requires synchronization (e.g. opening a db,
|
||||
// clearing dbs for an origin, etc).
|
||||
struct SynchronizedOp
|
||||
{
|
||||
SynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId);
|
||||
~SynchronizedOp();
|
||||
|
||||
// Test whether this SynchronizedOp needs to wait for the given op.
|
||||
bool MustWaitFor(const SynchronizedOp& aOp);
|
||||
|
||||
void DelayRunnable(nsIRunnable* aRunnable);
|
||||
void DispatchDelayedRunnables();
|
||||
|
||||
const OriginOrPatternString mOriginOrPattern;
|
||||
nsCOMPtr<nsIAtom> mId;
|
||||
nsRefPtr<AsyncConnectionHelper> mHelper;
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > mDelayedRunnables;
|
||||
nsTArray<IDBDatabase*> mDatabases;
|
||||
};
|
||||
|
||||
// A callback runnable used by the TransactionPool when it's safe to proceed
|
||||
// with a SetVersion/DeleteDatabase/etc.
|
||||
class WaitForTransactionsToFinishRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
WaitForTransactionsToFinishRunnable(SynchronizedOp* aOp,
|
||||
uint32_t aCountdown)
|
||||
: mOp(aOp), mCountdown(aCountdown)
|
||||
{
|
||||
NS_ASSERTION(mOp, "Why don't we have a runnable?");
|
||||
NS_ASSERTION(mOp->mDatabases.IsEmpty(), "We're here too early!");
|
||||
NS_ASSERTION(mOp->mHelper || mOp->mRunnable,
|
||||
"What are we supposed to do when we're done?");
|
||||
NS_ASSERTION(mCountdown, "Wrong countdown!");
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
private:
|
||||
// The IndexedDatabaseManager holds this alive.
|
||||
SynchronizedOp* mOp;
|
||||
uint32_t mCountdown;
|
||||
};
|
||||
|
||||
class WaitForLockedFilesToFinishRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
WaitForLockedFilesToFinishRunnable()
|
||||
: mBusy(true)
|
||||
{ }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
bool IsBusy() const
|
||||
{
|
||||
return mBusy;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mBusy;
|
||||
};
|
||||
|
||||
class AsyncDeleteFileRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
AsyncDeleteFileRunnable(FileManager* aFileManager, int64_t aFileId);
|
||||
|
||||
private:
|
||||
nsRefPtr<FileManager> mFileManager;
|
||||
int64_t mFileId;
|
||||
};
|
||||
|
||||
static nsresult RunSynchronizedOp(IDBDatabase* aDatabase,
|
||||
SynchronizedOp* aOp);
|
||||
|
||||
SynchronizedOp* FindSynchronizedOp(const nsACString& aPattern,
|
||||
nsIAtom* aId);
|
||||
|
||||
bool IsClearOriginPending(const nsACString& aPattern)
|
||||
{
|
||||
return !!FindSynchronizedOp(aPattern, nullptr);
|
||||
}
|
||||
|
||||
// Maintains a list of live databases per origin.
|
||||
nsClassHashtable<nsCStringHashKey, nsTArray<IDBDatabase*> > mLiveDatabases;
|
||||
void
|
||||
Destroy();
|
||||
|
||||
// Maintains a list of all file managers per origin. This list isn't
|
||||
// protected by any mutex but it is only ever touched on the IO thread.
|
||||
nsClassHashtable<nsCStringHashKey,
|
||||
nsTArray<nsRefPtr<FileManager> > > mFileManagers;
|
||||
|
||||
// Maintains a list of origins that we're currently enumerating to gather
|
||||
// usage statistics.
|
||||
nsAutoTArray<nsRefPtr<AsyncUsageRunnable>, 1> mUsageRunnables;
|
||||
|
||||
// Maintains a list of synchronized operatons that are in progress or queued.
|
||||
nsAutoTArray<nsAutoPtr<SynchronizedOp>, 5> mSynchronizedOps;
|
||||
|
||||
// Thread on which IO is performed.
|
||||
nsCOMPtr<nsIThread> mIOThread;
|
||||
|
||||
// A timer that gets activated at shutdown to ensure we close all databases.
|
||||
nsCOMPtr<nsITimer> mShutdownTimer;
|
||||
|
||||
// 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;
|
||||
|
||||
// Lock protecting FileManager.mFileInfos and nsDOMFileBase.mFileInfos
|
||||
// It's s also used to atomically update FileInfo.mRefCnt, FileInfo.mDBRefCnt
|
||||
// and FileInfo.mSliceRefCnt
|
||||
mozilla::Mutex mFileMutex;
|
||||
|
||||
nsString mDatabaseBasePath;
|
||||
|
||||
static bool sIsMainProcess;
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@ EXPORTS_NAMESPACES = mozilla/dom/indexedDB
|
||||
CPPSRCS = \
|
||||
AsyncConnectionHelper.cpp \
|
||||
CheckPermissionsHelper.cpp \
|
||||
Client.cpp \
|
||||
DatabaseInfo.cpp \
|
||||
FileInfo.cpp \
|
||||
FileManager.cpp \
|
||||
@ -43,7 +44,10 @@ CPPSRCS = \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_mozilla/dom/indexedDB = \
|
||||
Client.h \
|
||||
DatabaseInfo.h \
|
||||
FileManager.h \
|
||||
FileInfo.h \
|
||||
IDBCursor.h \
|
||||
IDBDatabase.h \
|
||||
IDBEvents.h \
|
||||
@ -59,8 +63,6 @@ EXPORTS_mozilla/dom/indexedDB = \
|
||||
IndexedDatabaseManager.h \
|
||||
Key.h \
|
||||
KeyPath.h \
|
||||
FileManager.h \
|
||||
FileInfo.h \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "nsIFile.h"
|
||||
|
||||
#include "mozilla/dom/quota/AcquireListener.h"
|
||||
#include "mozilla/dom/quota/OriginOrPatternString.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "nsEscape.h"
|
||||
@ -15,6 +17,7 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "snappy/snappy.h"
|
||||
|
||||
#include "Client.h"
|
||||
#include "nsIBFCacheEntry.h"
|
||||
#include "IDBEvents.h"
|
||||
#include "IDBFactory.h"
|
||||
@ -1323,7 +1326,8 @@ UpgradeSchemaFrom11_0To12_0(mozIStorageConnection* aConnection)
|
||||
class VersionChangeEventsRunnable;
|
||||
|
||||
class SetVersionHelper : public AsyncConnectionHelper,
|
||||
public IDBTransactionListener
|
||||
public IDBTransactionListener,
|
||||
public AcquireListener
|
||||
{
|
||||
friend class VersionChangeEventsRunnable;
|
||||
|
||||
@ -1346,6 +1350,9 @@ public:
|
||||
virtual nsresult GetSuccessResult(JSContext* aCx,
|
||||
jsval* aVal) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
OnExclusiveAccessAcquired() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual nsresult Init() MOZ_OVERRIDE;
|
||||
|
||||
@ -1393,7 +1400,8 @@ private:
|
||||
uint64_t mCurrentVersion;
|
||||
};
|
||||
|
||||
class DeleteDatabaseHelper : public AsyncConnectionHelper
|
||||
class DeleteDatabaseHelper : public AsyncConnectionHelper,
|
||||
public AcquireListener
|
||||
{
|
||||
friend class VersionChangeEventsRunnable;
|
||||
public:
|
||||
@ -1408,6 +1416,8 @@ public:
|
||||
mASCIIOrigin(aASCIIOrigin)
|
||||
{ }
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
nsresult GetSuccessResult(JSContext* aCx,
|
||||
jsval* aVal);
|
||||
|
||||
@ -1419,6 +1429,9 @@ public:
|
||||
AsyncConnectionHelper::ReleaseMainThreadObjects();
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
OnExclusiveAccessAcquired() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
|
||||
nsresult Init();
|
||||
@ -1470,11 +1483,11 @@ class VersionChangeEventsRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
VersionChangeEventsRunnable(
|
||||
IDBDatabase* aRequestingDatabase,
|
||||
IDBOpenDBRequest* aRequest,
|
||||
nsTArray<nsRefPtr<IDBDatabase> >& aWaitingDatabases,
|
||||
int64_t aOldVersion,
|
||||
int64_t aNewVersion)
|
||||
IDBDatabase* aRequestingDatabase,
|
||||
IDBOpenDBRequest* aRequest,
|
||||
nsTArray<nsCOMPtr<nsIOfflineStorage> >& aWaitingDatabases,
|
||||
int64_t aOldVersion,
|
||||
int64_t aNewVersion)
|
||||
: mRequestingDatabase(aRequestingDatabase),
|
||||
mRequest(aRequest),
|
||||
mOldVersion(aOldVersion),
|
||||
@ -1497,7 +1510,9 @@ public:
|
||||
// closed. Also kick bfcached documents out of bfcache.
|
||||
uint32_t count = mWaitingDatabases.Length();
|
||||
for (uint32_t index = 0; index < count; index++) {
|
||||
nsRefPtr<IDBDatabase>& database = mWaitingDatabases[index];
|
||||
IDBDatabase* database =
|
||||
IDBDatabase::FromStorage(mWaitingDatabases[index]);
|
||||
NS_ASSERTION(database, "This shouldn't be null!");
|
||||
|
||||
if (database->IsClosed()) {
|
||||
continue;
|
||||
@ -1519,12 +1534,12 @@ public:
|
||||
// We can't kick the document out of the bfcache because it's not yet
|
||||
// fully in the bfcache. Instead we'll abort everything for the window
|
||||
// and mark it as not-bfcacheable.
|
||||
IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(manager, "Huh?");
|
||||
manager->AbortCloseDatabasesForWindow(owner);
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Huh?");
|
||||
quotaManager->AbortCloseStoragesForWindow(owner);
|
||||
|
||||
NS_ASSERTION(database->IsClosed(),
|
||||
"AbortCloseDatabasesForWindow should have closed database");
|
||||
"AbortCloseStoragesForWindow should have closed database");
|
||||
ownerDoc->DisallowBFCaching();
|
||||
continue;
|
||||
}
|
||||
@ -1559,12 +1574,12 @@ public:
|
||||
|
||||
template <class T>
|
||||
static
|
||||
void QueueVersionChange(nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
|
||||
void QueueVersionChange(nsTArray<nsCOMPtr<nsIOfflineStorage> >& aDatabases,
|
||||
void* aClosure);
|
||||
private:
|
||||
nsRefPtr<IDBDatabase> mRequestingDatabase;
|
||||
nsRefPtr<IDBOpenDBRequest> mRequest;
|
||||
nsTArray<nsRefPtr<IDBDatabase> > mWaitingDatabases;
|
||||
nsTArray<nsCOMPtr<nsIOfflineStorage> > mWaitingDatabases;
|
||||
int64_t mOldVersion;
|
||||
int64_t mNewVersion;
|
||||
};
|
||||
@ -1576,7 +1591,7 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(OpenDatabaseHelper, nsIRunnable)
|
||||
nsresult
|
||||
OpenDatabaseHelper::Init()
|
||||
{
|
||||
mDatabaseId = IndexedDatabaseManager::GetDatabaseId(mASCIIOrigin, mName);
|
||||
mDatabaseId = QuotaManager::GetStorageId(mASCIIOrigin, mName);
|
||||
NS_ENSURE_TRUE(mDatabaseId, NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
@ -1609,7 +1624,7 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||
#ifdef DEBUG
|
||||
{
|
||||
bool correctThread;
|
||||
NS_ASSERTION(NS_SUCCEEDED(IndexedDatabaseManager::Get()->IOThread()->
|
||||
NS_ASSERTION(NS_SUCCEEDED(QuotaManager::Get()->IOThread()->
|
||||
IsOnCurrentThread(&correctThread)) &&
|
||||
correctThread,
|
||||
"Running on the wrong thread!");
|
||||
@ -1618,7 +1633,7 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||
|
||||
mState = eFiringEvents; // In case we fail somewhere along the line.
|
||||
|
||||
if (IndexedDatabaseManager::IsShuttingDown()) {
|
||||
if (QuotaManager::IsShuttingDown()) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
@ -1631,14 +1646,34 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||
|
||||
nsCOMPtr<nsIFile> dbDirectory;
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||
|
||||
nsresult rv = mgr->EnsureOriginIsInitialized(mASCIIOrigin,
|
||||
mPrivilege,
|
||||
getter_AddRefs(dbDirectory));
|
||||
nsresult rv =
|
||||
quotaManager->EnsureOriginIsInitialized(mASCIIOrigin,
|
||||
mPrivilege,
|
||||
getter_AddRefs(dbDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
rv = dbDirectory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
bool exists;
|
||||
rv = dbDirectory->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (!exists) {
|
||||
rv = dbDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
bool isDirectory;
|
||||
NS_ASSERTION(NS_SUCCEEDED(dbDirectory->IsDirectory(&isDirectory)) &&
|
||||
isDirectory, "Should have caught this earlier!");
|
||||
}
|
||||
#endif
|
||||
|
||||
nsAutoString filename;
|
||||
rv = GetDatabaseFilename(mName, filename);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
@ -1710,6 +1745,9 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||
mState = eSetVersionPending;
|
||||
}
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
|
||||
nsRefPtr<FileManager> fileManager = mgr->GetFileManager(mASCIIOrigin, mName);
|
||||
if (!fileManager) {
|
||||
fileManager = new FileManager(mASCIIOrigin, mPrivilege, mName);
|
||||
@ -1917,12 +1955,13 @@ OpenDatabaseHelper::StartSetVersion()
|
||||
new SetVersionHelper(transaction, mOpenDBRequest, this, mRequestedVersion,
|
||||
mCurrentVersion);
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||
|
||||
rv = mgr->AcquireExclusiveAccess(mDatabase, mDatabase->Origin(), helper,
|
||||
rv = quotaManager->AcquireExclusiveAccess(
|
||||
mDatabase, mDatabase->Origin(), helper,
|
||||
&VersionChangeEventsRunnable::QueueVersionChange<SetVersionHelper>,
|
||||
helper);
|
||||
helper);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
// The SetVersionHelper is responsible for dispatching us back to the
|
||||
@ -1946,12 +1985,13 @@ OpenDatabaseHelper::StartDelete()
|
||||
new DeleteDatabaseHelper(mOpenDBRequest, this, mCurrentVersion, mName,
|
||||
mASCIIOrigin);
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never be null!");
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||
|
||||
rv = mgr->AcquireExclusiveAccess(mDatabase, mDatabase->Origin(), helper,
|
||||
rv = quotaManager->AcquireExclusiveAccess(
|
||||
mDatabase, mDatabase->Origin(), helper,
|
||||
&VersionChangeEventsRunnable::QueueVersionChange<DeleteDatabaseHelper>,
|
||||
helper);
|
||||
helper);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
// The DeleteDatabaseHelper is responsible for dispatching us back to the
|
||||
@ -2040,10 +2080,10 @@ OpenDatabaseHelper::Run()
|
||||
DispatchSuccessEvent();
|
||||
}
|
||||
|
||||
IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(manager, "This should never be null!");
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never be null!");
|
||||
|
||||
manager->AllowNextSynchronizedOp(
|
||||
quotaManager->AllowNextSynchronizedOp(
|
||||
OriginOrPatternString::FromOrigin(mASCIIOrigin),
|
||||
mDatabaseId);
|
||||
|
||||
@ -2298,12 +2338,21 @@ SetVersionHelper::GetSuccessResult(JSContext* aCx,
|
||||
aVal);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SetVersionHelper::OnExclusiveAccessAcquired()
|
||||
{
|
||||
nsresult rv = DispatchToTransactionPool();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
template <class T>
|
||||
void
|
||||
VersionChangeEventsRunnable::QueueVersionChange(
|
||||
nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
|
||||
void* aClosure)
|
||||
nsTArray<nsCOMPtr<nsIOfflineStorage> >& aDatabases,
|
||||
void* aClosure)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aDatabases.IsEmpty(), "Why are we here?");
|
||||
@ -2366,23 +2415,28 @@ SetVersionHelper::NotifyTransactionPostComplete(IDBTransaction* aTransaction)
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(DeleteDatabaseHelper, AsyncConnectionHelper);
|
||||
|
||||
nsresult
|
||||
DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
{
|
||||
NS_ASSERTION(!aConnection, "How did we get a connection here?");
|
||||
|
||||
const FactoryPrivilege& privilege = mOpenHelper->Privilege();
|
||||
const StoragePrivilege& privilege = mOpenHelper->Privilege();
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never fail!");
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "This should never fail!");
|
||||
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv = mgr->GetDirectoryForOrigin(mASCIIOrigin,
|
||||
getter_AddRefs(directory));
|
||||
nsresult rv = quotaManager->GetDirectoryForOrigin(mASCIIOrigin,
|
||||
getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
NS_ASSERTION(directory, "What?");
|
||||
|
||||
rv = directory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
nsAutoString filename;
|
||||
rv = GetDatabaseFilename(mName, filename);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
@ -2460,6 +2514,18 @@ DeleteDatabaseHelper::GetSuccessResult(JSContext* aCx, jsval* aVal)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeleteDatabaseHelper::OnExclusiveAccessAcquired()
|
||||
{
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "We should definitely have a manager here");
|
||||
|
||||
nsresult rv = Dispatch(quotaManager->IOThread());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeleteDatabaseHelper::Init()
|
||||
{
|
||||
|
@ -24,6 +24,8 @@ BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class OpenDatabaseHelper : public HelperBase
|
||||
{
|
||||
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
||||
|
||||
public:
|
||||
OpenDatabaseHelper(IDBOpenDBRequest* aRequest,
|
||||
const nsAString& aName,
|
||||
@ -31,7 +33,7 @@ public:
|
||||
uint64_t aRequestedVersion,
|
||||
bool aForDeletion,
|
||||
mozilla::dom::ContentParent* aContentParent,
|
||||
FactoryPrivilege aPrivilege)
|
||||
StoragePrivilege aPrivilege)
|
||||
: HelperBase(aRequest), mOpenDBRequest(aRequest), mName(aName),
|
||||
mASCIIOrigin(aASCIIOrigin), mRequestedVersion(aRequestedVersion),
|
||||
mForDeletion(aForDeletion), mPrivilege(aPrivilege), mDatabaseId(nullptr),
|
||||
@ -77,7 +79,7 @@ public:
|
||||
return mDatabase;
|
||||
}
|
||||
|
||||
const FactoryPrivilege& Privilege() const
|
||||
const StoragePrivilege& Privilege() const
|
||||
{
|
||||
return mPrivilege;
|
||||
}
|
||||
@ -109,7 +111,7 @@ protected:
|
||||
nsCString mASCIIOrigin;
|
||||
uint64_t mRequestedVersion;
|
||||
bool mForDeletion;
|
||||
FactoryPrivilege mPrivilege;
|
||||
StoragePrivilege mPrivilege;
|
||||
nsCOMPtr<nsIAtom> mDatabaseId;
|
||||
mozilla::dom::ContentParent* mContentParent;
|
||||
|
||||
|
@ -279,8 +279,7 @@ TransactionThreadPool::GetQueueForTransaction(IDBTransaction* aTransaction)
|
||||
return *info->queue;
|
||||
}
|
||||
|
||||
TransactionInfo* transactionInfo = new TransactionInfo(aTransaction,
|
||||
objectStoreNames);
|
||||
TransactionInfo* transactionInfo = new TransactionInfo(aTransaction);
|
||||
|
||||
dbTransactionInfo->transactions.Put(aTransaction, transactionInfo);;
|
||||
|
||||
@ -352,31 +351,23 @@ TransactionThreadPool::Dispatch(IDBTransaction* aTransaction,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
TransactionThreadPool::WaitForAllDatabasesToComplete(
|
||||
nsTArray<IDBDatabase*>& aDatabases,
|
||||
nsIRunnable* aCallback)
|
||||
void
|
||||
TransactionThreadPool::WaitForDatabasesToComplete(
|
||||
nsTArray<IDBDatabase*>& aDatabases,
|
||||
nsIRunnable* aCallback)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!aDatabases.IsEmpty(), "No databases to wait on!");
|
||||
NS_ASSERTION(aCallback, "Null pointer!");
|
||||
|
||||
DatabasesCompleteCallback* callback = mCompleteCallbacks.AppendElement();
|
||||
if (!callback) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return false;
|
||||
}
|
||||
|
||||
callback->mCallback = aCallback;
|
||||
if (!callback->mDatabases.SwapElements(aDatabases)) {
|
||||
NS_ERROR("This should never fail!");
|
||||
}
|
||||
callback->mDatabases.SwapElements(aDatabases);
|
||||
|
||||
if (MaybeFireCallback(*callback)) {
|
||||
mCompleteCallbacks.RemoveElementAt(mCompleteCallbacks.Length() - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
@ -430,12 +421,12 @@ TransactionThreadPool::AbortTransactionsForDatabase(IDBDatabase* aDatabase)
|
||||
|
||||
struct NS_STACK_CLASS TransactionSearchInfo
|
||||
{
|
||||
TransactionSearchInfo(IDBDatabase* aDatabase)
|
||||
TransactionSearchInfo(nsIOfflineStorage* aDatabase)
|
||||
: db(aDatabase), found(false)
|
||||
{
|
||||
}
|
||||
|
||||
IDBDatabase* db;
|
||||
nsIOfflineStorage* db;
|
||||
bool found;
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
#include "IDBTransaction.h"
|
||||
|
||||
@ -46,8 +45,8 @@ public:
|
||||
bool aFinish,
|
||||
nsIRunnable* aFinishRunnable);
|
||||
|
||||
bool WaitForAllDatabasesToComplete(nsTArray<IDBDatabase*>& aDatabases,
|
||||
nsIRunnable* aCallback);
|
||||
void WaitForDatabasesToComplete(nsTArray<IDBDatabase*>& aDatabases,
|
||||
nsIRunnable* aCallback);
|
||||
|
||||
// Abort all transactions, unless they are already in the process of being
|
||||
// committed, for aDatabase.
|
||||
@ -83,8 +82,7 @@ protected:
|
||||
|
||||
struct TransactionInfo
|
||||
{
|
||||
TransactionInfo(IDBTransaction* aTransaction,
|
||||
const nsTArray<nsString>& aObjectStoreNames)
|
||||
TransactionInfo(IDBTransaction* aTransaction)
|
||||
{
|
||||
MOZ_COUNT_CTOR(TransactionInfo);
|
||||
|
||||
@ -93,7 +91,6 @@ protected:
|
||||
|
||||
transaction = aTransaction;
|
||||
queue = new TransactionQueue(aTransaction);
|
||||
objectStoreNames.AppendElements(aObjectStoreNames);
|
||||
}
|
||||
|
||||
~TransactionInfo()
|
||||
@ -103,7 +100,6 @@ protected:
|
||||
|
||||
nsRefPtr<IDBTransaction> transaction;
|
||||
nsRefPtr<TransactionQueue> queue;
|
||||
nsTArray<nsString> objectStoreNames;
|
||||
nsTHashtable<nsPtrHashKey<TransactionInfo> > blockedOn;
|
||||
nsTHashtable<nsPtrHashKey<TransactionInfo> > blocking;
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
|
||||
#include "AsyncConnectionHelper.h"
|
||||
#include "DatabaseInfo.h"
|
||||
@ -19,11 +20,11 @@
|
||||
#include "IDBIndex.h"
|
||||
#include "IDBObjectStore.h"
|
||||
#include "IDBTransaction.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using mozilla::dom::quota::QuotaManager;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -285,8 +286,7 @@ IndexedDBDatabaseChild::EnsureDatabase(
|
||||
databaseId = mDatabase->Id();
|
||||
}
|
||||
else {
|
||||
databaseId =
|
||||
IndexedDatabaseManager::GetDatabaseId(aDBInfo.origin, aDBInfo.name);
|
||||
databaseId = QuotaManager::GetStorageId(aDBInfo.origin, aDBInfo.name);
|
||||
}
|
||||
NS_ENSURE_TRUE(databaseId, false);
|
||||
|
||||
|
@ -6,63 +6,9 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, function, uuid(38f15cc7-2df0-4a90-8b7f-1606b2243522)]
|
||||
interface nsIIndexedDatabaseUsageCallback : nsISupports
|
||||
{
|
||||
void onUsageResult(in nsIURI aURI,
|
||||
in unsigned long long aUsage,
|
||||
in unsigned long long aFileUsage,
|
||||
in unsigned long aAppId,
|
||||
in boolean aInMozBrowserOnly);
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(e5168115-baff-4559-887e-7c0405cc9e63)]
|
||||
[scriptable, builtinclass, uuid(538d1085-517e-405a-a0f0-eb575cb0b8e5)]
|
||||
interface nsIIndexedDatabaseManager : nsISupports
|
||||
{
|
||||
/**
|
||||
* Schedules an asynchronous callback that will return the total amount of
|
||||
* disk space being used by databases for the given origin.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI whose usage is being queried.
|
||||
* @param aCallback
|
||||
* The callback that will be called when the usage is available.
|
||||
*/
|
||||
[optional_argc]
|
||||
void getUsageForURI(in nsIURI aURI,
|
||||
in nsIIndexedDatabaseUsageCallback aCallback,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Cancels an asynchronous usage check initiated by a previous call to
|
||||
* getUsageForURI().
|
||||
*
|
||||
* @param aURI
|
||||
* The URI whose usage is being queried.
|
||||
* @param aCallback
|
||||
* The callback that will be called when the usage is available.
|
||||
*/
|
||||
[optional_argc]
|
||||
void cancelGetUsageForURI(in nsIURI aURI,
|
||||
in nsIIndexedDatabaseUsageCallback aCallback,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Removes all databases stored for the given URI. The files may not be
|
||||
* deleted immediately depending on prohibitive concurrent operations.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI whose databases are to be cleared.
|
||||
*/
|
||||
[optional_argc]
|
||||
void clearDatabasesForURI(in nsIURI aURI,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Defines indexedDB and IDBKeyrange with its static functions on
|
||||
* aObject and initializes DOM exception providers if needed.
|
||||
|
@ -2,19 +2,18 @@
|
||||
* 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/. */
|
||||
|
||||
const nsIIndexedDatabaseManager =
|
||||
Components.interfaces.nsIIndexedDatabaseManager;
|
||||
const nsIQuotaManager = Components.interfaces.nsIQuotaManager;
|
||||
|
||||
let gURI = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService).newURI("http://localhost", null, null);
|
||||
|
||||
function onIndexedDBUsageCallback(uri, usage, fileUsage) {}
|
||||
function onUsageCallback(uri, usage, fileUsage) {}
|
||||
|
||||
function onLoad()
|
||||
{
|
||||
var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"]
|
||||
.getService(nsIIndexedDatabaseManager);
|
||||
dbManager.getUsageForURI(gURI, onIndexedDBUsageCallback);
|
||||
dbManager.cancelGetUsageForURI(gURI, onIndexedDBUsageCallback);
|
||||
var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"]
|
||||
.getService(nsIQuotaManager);
|
||||
var quotaRequest = quotaManager.getUsageForURI(gURI, onUsageCallback);
|
||||
quotaRequest.cancel();
|
||||
Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService)
|
||||
.notifyObservers(window, "bug839193-loaded", null);
|
||||
|
@ -173,8 +173,8 @@ function grabFileUsageAndContinueHandler(usage, fileUsage)
|
||||
function getUsage(usageHandler)
|
||||
{
|
||||
let comp = SpecialPowers.wrap(Components);
|
||||
let idbManager = comp.classes["@mozilla.org/dom/indexeddb/manager;1"]
|
||||
.getService(comp.interfaces.nsIIndexedDatabaseManager);
|
||||
let quotaManager = comp.classes["@mozilla.org/dom/quota/manager;1"]
|
||||
.getService(comp.interfaces.nsIQuotaManager);
|
||||
|
||||
let uri = SpecialPowers.getDocumentURIObject(window.document);
|
||||
let callback = {
|
||||
@ -183,7 +183,7 @@ function getUsage(usageHandler)
|
||||
}
|
||||
};
|
||||
|
||||
idbManager.getUsageForURI(uri, callback);
|
||||
quotaManager.getUsageForURI(uri, callback);
|
||||
}
|
||||
|
||||
function scheduleGC()
|
||||
|
@ -40,18 +40,18 @@ function clearAllDatabases(callback) {
|
||||
|
||||
let comp = SpecialPowers.wrap(Components);
|
||||
|
||||
let idbManager =
|
||||
comp.classes["@mozilla.org/dom/indexeddb/manager;1"]
|
||||
.getService(comp.interfaces.nsIIndexedDatabaseManager);
|
||||
let quotaManager =
|
||||
comp.classes["@mozilla.org/dom/quota/manager;1"]
|
||||
.getService(comp.interfaces.nsIQuotaManager);
|
||||
|
||||
let uri = SpecialPowers.getDocumentURIObject(document);
|
||||
|
||||
idbManager.clearDatabasesForURI(uri);
|
||||
idbManager.getUsageForURI(uri, function(uri, usage, fileUsage) {
|
||||
quotaManager.clearStoragesForURI(uri);
|
||||
quotaManager.getUsageForURI(uri, function(uri, usage, fileUsage) {
|
||||
if (usage) {
|
||||
ok(false,
|
||||
"getUsageForURI returned non-zero usage after clearing all " +
|
||||
"databases!");
|
||||
"storages!");
|
||||
}
|
||||
runCallback();
|
||||
});
|
||||
|
29
dom/quota/AcquireListener.h
Normal file
29
dom/quota/AcquireListener.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_acquirelistener_h__
|
||||
#define mozilla_dom_quota_acquirelistener_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
class AcquireListener
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD_(nsrefcnt)
|
||||
AddRef() = 0;
|
||||
|
||||
NS_IMETHOD_(nsrefcnt)
|
||||
Release() = 0;
|
||||
|
||||
virtual nsresult
|
||||
OnExclusiveAccessAcquired() = 0;
|
||||
};
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_quota_acquirelistener_h__
|
106
dom/quota/ArrayCluster.h
Normal file
106
dom/quota/ArrayCluster.h
Normal file
@ -0,0 +1,106 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_arraycluster_h__
|
||||
#define mozilla_dom_quota_arraycluster_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
#include "Client.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
template <class ValueType, uint32_t Length = Client::TYPE_MAX>
|
||||
class ArrayCluster
|
||||
{
|
||||
public:
|
||||
ArrayCluster()
|
||||
{
|
||||
mArrays.AppendElements(Length);
|
||||
}
|
||||
|
||||
nsTArray<ValueType>&
|
||||
ArrayAt(uint32_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aIndex < Length, "Bad index!");
|
||||
return mArrays[aIndex];
|
||||
}
|
||||
|
||||
nsTArray<ValueType>&
|
||||
operator[](uint32_t aIndex)
|
||||
{
|
||||
return ArrayAt(aIndex);
|
||||
}
|
||||
|
||||
bool
|
||||
IsEmpty()
|
||||
{
|
||||
for (uint32_t index = 0; index < Length; index++) {
|
||||
if (!mArrays[index].IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
AppendElementsTo(uint32_t aIndex, nsTArray<T>& aArray)
|
||||
{
|
||||
NS_ASSERTION(aIndex < Length, "Bad index!");
|
||||
aArray.AppendElements(mArrays[aIndex]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
AppendElementsTo(uint32_t aIndex, ArrayCluster<T, Length>& aArrayCluster)
|
||||
{
|
||||
NS_ASSERTION(aIndex < Length, "Bad index!");
|
||||
aArrayCluster[aIndex].AppendElements(mArrays[aIndex]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
AppendElementsTo(nsTArray<T>& aArray)
|
||||
{
|
||||
for (uint32_t index = 0; index < Length; index++) {
|
||||
aArray.AppendElements(mArrays[index]);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
AppendElementsTo(ArrayCluster<T, Length>& aArrayCluster)
|
||||
{
|
||||
for (uint32_t index = 0; index < Length; index++) {
|
||||
aArrayCluster[index].AppendElements(mArrays[index]);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
SwapElements(ArrayCluster<T, Length>& aArrayCluster)
|
||||
{
|
||||
for (uint32_t index = 0; index < Length; index++) {
|
||||
mArrays[index].SwapElements(aArrayCluster.mArrays[index]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Clear()
|
||||
{
|
||||
for (uint32_t index = 0; index < Length; index++) {
|
||||
mArrays[index].Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoTArray<nsTArray<ValueType>, Length> mArrays;
|
||||
};
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_quota_arraycluster_h__
|
@ -14,7 +14,7 @@
|
||||
#include "nsIURI.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
@ -29,7 +29,6 @@
|
||||
|
||||
USING_QUOTA_NAMESPACE
|
||||
using namespace mozilla::services;
|
||||
using mozilla::dom::indexedDB::IndexedDatabaseManager;
|
||||
using mozilla::MutexAutoLock;
|
||||
|
||||
namespace {
|
||||
@ -167,7 +166,7 @@ CheckQuotaHelper::Run()
|
||||
}
|
||||
}
|
||||
else if (mPromptResult == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
uint32_t quota = IndexedDatabaseManager::GetIndexedDBQuotaMB();
|
||||
uint32_t quota = QuotaManager::GetStorageQuotaMB();
|
||||
|
||||
nsString quotaString;
|
||||
quotaString.AppendInt(quota);
|
||||
|
@ -49,4 +49,4 @@ private:
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_indexeddb_checkquotahelper_h__
|
||||
#endif // mozilla_dom_quota_checkquotahelper_h__
|
||||
|
110
dom/quota/Client.h
Normal file
110
dom/quota/Client.h
Normal file
@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_client_h__
|
||||
#define mozilla_dom_quota_client_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
class nsIOfflineStorage;
|
||||
class nsIRunnable;
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
class UsageRunnable;
|
||||
|
||||
// An abstract interface for quota manager clients.
|
||||
// Each storage API must provide an implementation of this interface in order
|
||||
// to participate in centralized quota and storage handling.
|
||||
class Client
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD_(nsrefcnt)
|
||||
AddRef() = 0;
|
||||
|
||||
NS_IMETHOD_(nsrefcnt)
|
||||
Release() = 0;
|
||||
|
||||
enum Type {
|
||||
IDB = 0,
|
||||
//LS,
|
||||
//APPCACHE,
|
||||
TYPE_MAX
|
||||
};
|
||||
|
||||
virtual Type
|
||||
GetType() = 0;
|
||||
|
||||
static nsresult
|
||||
TypeToText(Type aType, nsAString& aText)
|
||||
{
|
||||
switch (aType) {
|
||||
case IDB:
|
||||
aText.AssignLiteral("idb");
|
||||
break;
|
||||
|
||||
case TYPE_MAX:
|
||||
default:
|
||||
NS_NOTREACHED("Bad id value!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
TypeFromText(const nsAString& aText, Type& aType)
|
||||
{
|
||||
if (aText.EqualsLiteral("idb")) {
|
||||
aType = IDB;
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable) = 0;
|
||||
|
||||
virtual nsresult
|
||||
GetUsageForOrigin(const nsACString& aOrigin,
|
||||
UsageRunnable* aUsageRunnable) = 0;
|
||||
|
||||
virtual bool
|
||||
IsFileServiceUtilized() = 0;
|
||||
|
||||
virtual bool
|
||||
IsTransactionServiceActivated() = 0;
|
||||
|
||||
virtual void
|
||||
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
|
||||
nsIRunnable* aCallback) = 0;
|
||||
|
||||
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__
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "FileStreams.h"
|
||||
|
||||
#include "QuotaManager.h"
|
||||
|
||||
USING_QUOTA_NAMESPACE
|
||||
|
||||
template <class FileStreamBase>
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#include "nsFileStreams.h"
|
||||
|
||||
#include "QuotaManager.h"
|
||||
#include "QuotaObject.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
|
@ -12,6 +12,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
LIBRARY_NAME = domquota_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
FAIL_ON_WARNINGS := 1
|
||||
|
||||
include $(topsrcdir)/dom/dom-config.mk
|
||||
|
||||
@ -21,12 +22,31 @@ CPPSRCS = \
|
||||
CheckQuotaHelper.cpp \
|
||||
FileStreams.cpp \
|
||||
QuotaManager.cpp \
|
||||
QuotaObject.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsIOfflineStorage.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_mozilla/dom/quota = \
|
||||
AcquireListener.h \
|
||||
ArrayCluster.h \
|
||||
Client.h \
|
||||
FileStreams.h \
|
||||
OriginOrPatternString.h \
|
||||
QuotaCommon.h \
|
||||
QuotaManager.h \
|
||||
QuotaObject.h \
|
||||
StoragePrivilege.h \
|
||||
UsageRunnable.h \
|
||||
Utilities.h \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/caps/include \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
54
dom/quota/OriginOrPatternString.h
Normal file
54
dom/quota/OriginOrPatternString.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_originorpatternstring_h__
|
||||
#define mozilla_dom_quota_originorpatternstring_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
class OriginOrPatternString : public nsCString
|
||||
{
|
||||
public:
|
||||
static OriginOrPatternString
|
||||
FromOrigin(const nsACString& aOrigin)
|
||||
{
|
||||
return OriginOrPatternString(aOrigin, true);
|
||||
}
|
||||
|
||||
static OriginOrPatternString
|
||||
FromPattern(const nsACString& aPattern)
|
||||
{
|
||||
return OriginOrPatternString(aPattern, false);
|
||||
}
|
||||
|
||||
bool
|
||||
IsOrigin() const
|
||||
{
|
||||
return mIsOrigin;
|
||||
}
|
||||
|
||||
bool
|
||||
IsPattern() const
|
||||
{
|
||||
return !mIsOrigin;
|
||||
}
|
||||
|
||||
private:
|
||||
OriginOrPatternString(const nsACString& aOriginOrPattern, bool aIsOrigin)
|
||||
: nsCString(aOriginOrPattern), mIsOrigin(aIsOrigin)
|
||||
{ }
|
||||
|
||||
bool
|
||||
operator==(const OriginOrPatternString& aOther) MOZ_DELETE;
|
||||
|
||||
bool mIsOrigin;
|
||||
};
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_quota_originorpatternstring_h__
|
File diff suppressed because it is too large
Load Diff
@ -9,95 +9,62 @@
|
||||
|
||||
#include "QuotaCommon.h"
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIQuotaManager.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "ArrayCluster.h"
|
||||
#include "Client.h"
|
||||
#include "StoragePrivilege.h"
|
||||
|
||||
#define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIOfflineStorage;
|
||||
class nsIPrincipal;
|
||||
class nsIThread;
|
||||
class nsITimer;
|
||||
class nsIURI;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
class AcquireListener;
|
||||
class AsyncUsageRunnable;
|
||||
class CheckQuotaHelper;
|
||||
class OriginClearRunnable;
|
||||
class OriginInfo;
|
||||
class QuotaManager;
|
||||
class OriginOrPatternString;
|
||||
class QuotaObject;
|
||||
struct SynchronizedOp;
|
||||
|
||||
class QuotaObject
|
||||
class QuotaManager MOZ_FINAL : public nsIQuotaManager,
|
||||
public nsIObserver
|
||||
{
|
||||
friend class OriginInfo;
|
||||
friend class QuotaManager;
|
||||
|
||||
public:
|
||||
void
|
||||
AddRef();
|
||||
|
||||
void
|
||||
Release();
|
||||
|
||||
void
|
||||
UpdateSize(int64_t aSize);
|
||||
|
||||
bool
|
||||
MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount);
|
||||
|
||||
private:
|
||||
QuotaObject(OriginInfo* aOriginInfo, const nsAString& aPath, int64_t aSize)
|
||||
: mOriginInfo(aOriginInfo), mPath(aPath), mSize(aSize)
|
||||
{ }
|
||||
|
||||
virtual ~QuotaObject()
|
||||
{ }
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
|
||||
OriginInfo* mOriginInfo;
|
||||
nsString mPath;
|
||||
int64_t mSize;
|
||||
};
|
||||
|
||||
class OriginInfo
|
||||
{
|
||||
friend class QuotaManager;
|
||||
friend class QuotaObject;
|
||||
|
||||
public:
|
||||
OriginInfo(const nsACString& aOrigin, int64_t aLimit, int64_t aUsage)
|
||||
: mOrigin(aOrigin), mLimit(aLimit), mUsage(aUsage)
|
||||
{
|
||||
mQuotaObjects.Init();
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OriginInfo)
|
||||
|
||||
private:
|
||||
void
|
||||
#ifdef DEBUG
|
||||
LockedClearOriginInfos();
|
||||
#else
|
||||
LockedClearOriginInfos()
|
||||
{
|
||||
mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static PLDHashOperator
|
||||
ClearOriginInfoCallback(const nsAString& aKey,
|
||||
QuotaObject* aValue, void* aUserArg);
|
||||
|
||||
nsDataHashtable<nsStringHashKey, QuotaObject*> mQuotaObjects;
|
||||
|
||||
nsCString mOrigin;
|
||||
int64_t mLimit;
|
||||
int64_t mUsage;
|
||||
};
|
||||
|
||||
class QuotaManager
|
||||
{
|
||||
friend class nsAutoPtr<QuotaManager>;
|
||||
friend class AsyncUsageRunnable;
|
||||
friend class OriginClearRunnable;
|
||||
friend class OriginInfo;
|
||||
friend class QuotaObject;
|
||||
|
||||
enum MozBrowserPatternFlag
|
||||
{
|
||||
MozBrowser = 0,
|
||||
NotMozBrowser,
|
||||
IgnoreMozBrowser
|
||||
};
|
||||
|
||||
typedef void
|
||||
(*WaitingOnStoragesCallback)(nsTArray<nsCOMPtr<nsIOfflineStorage> >&, void*);
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIQUOTAMANAGER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// Returns a non-owning reference.
|
||||
static QuotaManager*
|
||||
GetOrCreate();
|
||||
@ -106,6 +73,13 @@ public:
|
||||
static QuotaManager*
|
||||
Get();
|
||||
|
||||
// Returns an owning reference! No one should call this but the factory.
|
||||
static QuotaManager*
|
||||
FactoryCreate();
|
||||
|
||||
// Returns true if we've begun the shutdown process.
|
||||
static bool IsShuttingDown();
|
||||
|
||||
void
|
||||
InitQuotaForOrigin(const nsACString& aOrigin,
|
||||
int64_t aLimit,
|
||||
@ -148,12 +122,143 @@ public:
|
||||
quotaManager->CancelPromptsForWindowInternal(aWindow);
|
||||
}
|
||||
|
||||
// Called when a storage is created.
|
||||
bool
|
||||
RegisterStorage(nsIOfflineStorage* aStorage);
|
||||
|
||||
// Called when a storage is being unlinked or destroyed.
|
||||
void
|
||||
UnregisterStorage(nsIOfflineStorage* aStorage);
|
||||
|
||||
// Called when a storage has been closed.
|
||||
void
|
||||
OnStorageClosed(nsIOfflineStorage* aStorage);
|
||||
|
||||
// Called when a window is being purged from the bfcache or the user leaves
|
||||
// a page which isn't going into the bfcache. Forces any live storage
|
||||
// objects to close themselves and aborts any running transactions.
|
||||
void
|
||||
AbortCloseStoragesForWindow(nsPIDOMWindow* aWindow);
|
||||
|
||||
// Used to check if there are running transactions in a given window.
|
||||
bool
|
||||
HasOpenTransactions(nsPIDOMWindow* aWindow);
|
||||
|
||||
// Waits for storages to be cleared and for version change transactions to
|
||||
// complete before dispatching the given runnable.
|
||||
nsresult
|
||||
WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId,
|
||||
nsIRunnable* aRunnable);
|
||||
|
||||
// Acquire exclusive access to the storage given (waits for all others to
|
||||
// close). If storages need to close first, the callback will be invoked
|
||||
// with an array of said storages.
|
||||
nsresult
|
||||
AcquireExclusiveAccess(nsIOfflineStorage* aStorage,
|
||||
const nsACString& aOrigin,
|
||||
AcquireListener* aListener,
|
||||
WaitingOnStoragesCallback aCallback,
|
||||
void* aClosure)
|
||||
{
|
||||
NS_ASSERTION(aStorage, "Need a storage here!");
|
||||
return AcquireExclusiveAccess(aOrigin, aStorage, aListener, aCallback,
|
||||
aClosure);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AcquireExclusiveAccess(const nsACString& aOrigin,
|
||||
AcquireListener* aListener,
|
||||
WaitingOnStoragesCallback aCallback,
|
||||
void* aClosure)
|
||||
{
|
||||
return AcquireExclusiveAccess(aOrigin, nullptr, aListener, aCallback,
|
||||
aClosure);
|
||||
}
|
||||
|
||||
void
|
||||
AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
|
||||
nsIAtom* aId);
|
||||
|
||||
bool
|
||||
IsClearOriginPending(const nsACString& aPattern)
|
||||
{
|
||||
return !!FindSynchronizedOp(aPattern, nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetDirectoryForOrigin(const nsACString& aASCIIOrigin,
|
||||
nsIFile** aDirectory) const;
|
||||
|
||||
nsresult
|
||||
EnsureOriginIsInitialized(const nsACString& aOrigin,
|
||||
StoragePrivilege aPrivilege,
|
||||
nsIFile** aDirectory);
|
||||
|
||||
void
|
||||
UninitializeOriginsByPattern(const nsACString& aPattern);
|
||||
|
||||
nsIThread*
|
||||
IOThread()
|
||||
{
|
||||
NS_ASSERTION(mIOThread, "This should never be null!");
|
||||
return mIOThread;
|
||||
}
|
||||
|
||||
already_AddRefed<Client>
|
||||
GetClient(Client::Type aClientType);
|
||||
|
||||
const nsString&
|
||||
GetBaseDirectory() const
|
||||
{
|
||||
return mStorageBasePath;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
GetStorageQuotaMB();
|
||||
|
||||
static already_AddRefed<nsIAtom>
|
||||
GetStorageId(const nsACString& aOrigin,
|
||||
const nsAString& aName);
|
||||
|
||||
static nsresult
|
||||
GetASCIIOriginFromURI(nsIURI* aURI,
|
||||
uint32_t aAppId,
|
||||
bool aInMozBrowser,
|
||||
nsACString& aASCIIOrigin);
|
||||
|
||||
static nsresult
|
||||
GetASCIIOriginFromPrincipal(nsIPrincipal* aPrincipal,
|
||||
nsACString& aASCIIOrigin);
|
||||
|
||||
static nsresult
|
||||
GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow,
|
||||
nsACString& aASCIIOrigin);
|
||||
|
||||
static void
|
||||
GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly,
|
||||
const nsACString& aOrigin, nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId,
|
||||
aBrowserOnly ? MozBrowser : NotMozBrowser,
|
||||
aOrigin, _retval);
|
||||
}
|
||||
|
||||
static void
|
||||
GetOriginPatternStringMaybeIgnoreBrowser(uint32_t aAppId, bool aBrowserOnly,
|
||||
nsAutoCString& _retval)
|
||||
{
|
||||
return GetOriginPatternString(aAppId,
|
||||
aBrowserOnly ? MozBrowser : IgnoreMozBrowser,
|
||||
EmptyCString(), _retval);
|
||||
}
|
||||
|
||||
private:
|
||||
QuotaManager();
|
||||
|
||||
virtual ~QuotaManager();
|
||||
|
||||
bool
|
||||
nsresult
|
||||
Init();
|
||||
|
||||
void
|
||||
@ -167,6 +272,33 @@ private:
|
||||
bool
|
||||
LockedQuotaIsLifted();
|
||||
|
||||
nsresult
|
||||
AcquireExclusiveAccess(const nsACString& aOrigin,
|
||||
nsIOfflineStorage* aStorage,
|
||||
AcquireListener* aListener,
|
||||
WaitingOnStoragesCallback aCallback,
|
||||
void* aClosure);
|
||||
|
||||
nsresult
|
||||
RunSynchronizedOp(nsIOfflineStorage* aStorage,
|
||||
SynchronizedOp* aOp);
|
||||
|
||||
SynchronizedOp*
|
||||
FindSynchronizedOp(const nsACString& aPattern,
|
||||
nsISupports* aId);
|
||||
|
||||
nsresult
|
||||
ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly);
|
||||
|
||||
nsresult
|
||||
MaybeUpgradeOriginDirectory(nsIFile* aDirectory);
|
||||
|
||||
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;
|
||||
|
||||
@ -177,6 +309,27 @@ private:
|
||||
// A map of Windows to the corresponding quota helper.
|
||||
nsRefPtrHashtable<nsPtrHashKey<nsPIDOMWindow>,
|
||||
CheckQuotaHelper> mCheckQuotaHelpers;
|
||||
|
||||
// Maintains a list of live storages per origin.
|
||||
nsClassHashtable<nsCStringHashKey,
|
||||
ArrayCluster<nsIOfflineStorage*> > mLiveStorages;
|
||||
|
||||
// Maintains a list of synchronized operatons that are in progress or queued.
|
||||
nsAutoTArray<nsAutoPtr<SynchronizedOp>, 5> mSynchronizedOps;
|
||||
|
||||
// Thread on which IO is performed.
|
||||
nsCOMPtr<nsIThread> mIOThread;
|
||||
|
||||
// A timer that gets activated at shutdown to ensure we close all storages.
|
||||
nsCOMPtr<nsITimer> mShutdownTimer;
|
||||
|
||||
// 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 mStorageBasePath;
|
||||
};
|
||||
|
||||
class AutoEnterWindow
|
||||
|
159
dom/quota/QuotaObject.cpp
Normal file
159
dom/quota/QuotaObject.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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 "QuotaObject.h"
|
||||
|
||||
#include "QuotaManager.h"
|
||||
|
||||
USING_QUOTA_NAMESPACE
|
||||
|
||||
void
|
||||
QuotaObject::AddRef()
|
||||
{
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
if (!quotaManager) {
|
||||
NS_ERROR("Null quota manager, this shouldn't happen, possible leak!");
|
||||
|
||||
NS_AtomicIncrementRefcnt(mRefCnt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(quotaManager->mQuotaMutex);
|
||||
|
||||
++mRefCnt;
|
||||
}
|
||||
|
||||
void
|
||||
QuotaObject::Release()
|
||||
{
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
if (!quotaManager) {
|
||||
NS_ERROR("Null quota manager, this shouldn't happen, possible leak!");
|
||||
|
||||
nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt);
|
||||
if (count == 0) {
|
||||
mRefCnt = 1;
|
||||
delete this;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(quotaManager->mQuotaMutex);
|
||||
|
||||
--mRefCnt;
|
||||
|
||||
if (mRefCnt > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOriginInfo) {
|
||||
mOriginInfo->mQuotaObjects.Remove(mPath);
|
||||
}
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void
|
||||
QuotaObject::UpdateSize(int64_t aSize)
|
||||
{
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||
|
||||
MutexAutoLock lock(quotaManager->mQuotaMutex);
|
||||
|
||||
if (mOriginInfo) {
|
||||
mOriginInfo->mUsage -= mSize;
|
||||
mSize = aSize;
|
||||
mOriginInfo->mUsage += mSize;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount)
|
||||
{
|
||||
int64_t end = aOffset + aCount;
|
||||
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||
|
||||
MutexAutoLock lock(quotaManager->mQuotaMutex);
|
||||
|
||||
if (mSize >= end || !mOriginInfo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t newUsage = mOriginInfo->mUsage - mSize + end;
|
||||
if (newUsage > mOriginInfo->mLimit) {
|
||||
// This will block the thread, but it will also drop the mutex while
|
||||
// waiting. The mutex will be reacquired again when the waiting is finished.
|
||||
if (!quotaManager->LockedQuotaIsLifted()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Threads raced, the origin info removal has been done by some other
|
||||
// thread.
|
||||
if (!mOriginInfo) {
|
||||
// The other thread could allocate more space.
|
||||
if (end > mSize) {
|
||||
mSize = end;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCString origin = mOriginInfo->mOrigin;
|
||||
|
||||
mOriginInfo->LockedClearOriginInfos();
|
||||
NS_ASSERTION(!mOriginInfo,
|
||||
"Should have cleared in LockedClearOriginInfos!");
|
||||
|
||||
quotaManager->mOriginInfos.Remove(origin);
|
||||
|
||||
// Some other thread could increase the size without blocking (increasing
|
||||
// the origin usage without hitting the limit), but no more than this one.
|
||||
NS_ASSERTION(mSize < end, "This shouldn't happen!");
|
||||
|
||||
mSize = end;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
mOriginInfo->mUsage = newUsage;
|
||||
mSize = end;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
OriginInfo::LockedClearOriginInfos()
|
||||
{
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||
|
||||
quotaManager->mQuotaMutex.AssertCurrentThreadOwns();
|
||||
|
||||
mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
// static
|
||||
PLDHashOperator
|
||||
OriginInfo::ClearOriginInfoCallback(const nsAString& aKey,
|
||||
QuotaObject* aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
|
||||
NS_ASSERTION(aValue, "Null pointer!");
|
||||
|
||||
aValue->mOriginInfo = nullptr;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
90
dom/quota/QuotaObject.h
Normal file
90
dom/quota/QuotaObject.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_quotaobject_h__
|
||||
#define mozilla_dom_quota_quotaobject_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
class OriginInfo;
|
||||
class QuotaManager;
|
||||
|
||||
class QuotaObject
|
||||
{
|
||||
friend class OriginInfo;
|
||||
friend class QuotaManager;
|
||||
|
||||
public:
|
||||
void
|
||||
AddRef();
|
||||
|
||||
void
|
||||
Release();
|
||||
|
||||
void
|
||||
UpdateSize(int64_t aSize);
|
||||
|
||||
bool
|
||||
MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount);
|
||||
|
||||
private:
|
||||
QuotaObject(OriginInfo* aOriginInfo, const nsAString& aPath, int64_t aSize)
|
||||
: mOriginInfo(aOriginInfo), mPath(aPath), mSize(aSize)
|
||||
{ }
|
||||
|
||||
virtual ~QuotaObject()
|
||||
{ }
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
|
||||
OriginInfo* mOriginInfo;
|
||||
nsString mPath;
|
||||
int64_t mSize;
|
||||
};
|
||||
|
||||
class OriginInfo
|
||||
{
|
||||
friend class QuotaManager;
|
||||
friend class QuotaObject;
|
||||
|
||||
public:
|
||||
OriginInfo(const nsACString& aOrigin, int64_t aLimit, int64_t aUsage)
|
||||
: mOrigin(aOrigin), mLimit(aLimit), mUsage(aUsage)
|
||||
{
|
||||
mQuotaObjects.Init();
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OriginInfo)
|
||||
|
||||
private:
|
||||
void
|
||||
#ifdef DEBUG
|
||||
LockedClearOriginInfos();
|
||||
#else
|
||||
LockedClearOriginInfos()
|
||||
{
|
||||
mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static PLDHashOperator
|
||||
ClearOriginInfoCallback(const nsAString& aKey,
|
||||
QuotaObject* aValue, void* aUserArg);
|
||||
|
||||
nsDataHashtable<nsStringHashKey, QuotaObject*> mQuotaObjects;
|
||||
|
||||
nsCString mOrigin;
|
||||
int64_t mLimit;
|
||||
int64_t mUsage;
|
||||
};
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_quota_quotaobject_h__
|
191
dom/quota/StorageMatcher.h
Normal file
191
dom/quota/StorageMatcher.h
Normal file
@ -0,0 +1,191 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_patternmatcher_h__
|
||||
#define mozilla_dom_quota_patternmatcher_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
#include "ArrayCluster.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
template <class ValueType, class BaseType = ArrayCluster<nsIOfflineStorage*>>
|
||||
class StorageMatcher : public ValueType
|
||||
{
|
||||
typedef StorageMatcher<ValueType, BaseType> SelfType;
|
||||
|
||||
struct Closure
|
||||
{
|
||||
Closure(SelfType& aSelf)
|
||||
: mSelf(aSelf), mPattern(EmptyCString()), mIndexes(nullptr)
|
||||
{ }
|
||||
|
||||
Closure(SelfType& aSelf, const nsACString& aPattern)
|
||||
: mSelf(aSelf), mPattern(aPattern), mIndexes(nullptr)
|
||||
{ }
|
||||
|
||||
Closure(SelfType& aSelf, const nsTArray<uint32_t>* aIndexes)
|
||||
: mSelf(aSelf), mPattern(EmptyCString()), mIndexes(aIndexes)
|
||||
{ }
|
||||
|
||||
Closure(SelfType& aSelf, const nsACString& aPattern,
|
||||
const nsTArray<uint32_t>* aIndexes)
|
||||
: mSelf(aSelf), mPattern(aPattern), mIndexes(aIndexes)
|
||||
{ }
|
||||
|
||||
SelfType& mSelf;
|
||||
const nsACString& mPattern;
|
||||
const nsTArray<uint32_t>* mIndexes;
|
||||
};
|
||||
|
||||
public:
|
||||
template <class T, class U, class V>
|
||||
void
|
||||
Find(const nsBaseHashtable<T, U, V>& aHashtable,
|
||||
const nsACString& aPattern)
|
||||
{
|
||||
SelfType::Clear();
|
||||
|
||||
Closure closure(*this, aPattern);
|
||||
aHashtable.EnumerateRead(SelfType::MatchPattern, &closure);
|
||||
}
|
||||
|
||||
template <class T, class U, class V>
|
||||
void
|
||||
Find(const nsBaseHashtable<T, U, V>& aHashtable,
|
||||
const nsTArray<uint32_t>* aIndexes)
|
||||
{
|
||||
SelfType::Clear();
|
||||
|
||||
Closure closure(*this, aIndexes);
|
||||
aHashtable.EnumerateRead(SelfType::MatchIndexes, &closure);
|
||||
}
|
||||
|
||||
template <class T, class U, class V>
|
||||
void
|
||||
Find(const nsBaseHashtable<T, U, V>& aHashtable,
|
||||
uint32_t aIndex)
|
||||
{
|
||||
nsAutoTArray<uint32_t, 1> indexes;
|
||||
indexes.AppendElement(aIndex);
|
||||
|
||||
Find(aHashtable, &indexes);
|
||||
}
|
||||
|
||||
template <class T, class U, class V>
|
||||
void
|
||||
Find(const nsBaseHashtable<T, U, V>& aHashtable,
|
||||
const nsACString& aPattern,
|
||||
const nsTArray<uint32_t>* aIndexes)
|
||||
{
|
||||
SelfType::Clear();
|
||||
|
||||
Closure closure(*this, aPattern, aIndexes);
|
||||
aHashtable.EnumerateRead(SelfType::MatchPatternAndIndexes, &closure);
|
||||
}
|
||||
|
||||
template <class T, class U, class V>
|
||||
void
|
||||
Find(const nsBaseHashtable<T, U, V>& aHashtable,
|
||||
const nsACString& aPattern,
|
||||
uint32_t aIndex)
|
||||
{
|
||||
nsAutoTArray<uint32_t, 1> indexes;
|
||||
indexes.AppendElement(aIndex);
|
||||
|
||||
Find(aHashtable, aPattern, &indexes);
|
||||
}
|
||||
|
||||
template <class T, class U, class V>
|
||||
void
|
||||
Find(const nsBaseHashtable<T, U, V>& aHashtable)
|
||||
{
|
||||
SelfType::Clear();
|
||||
|
||||
Closure closure(*this);
|
||||
aHashtable.EnumerateRead(SelfType::MatchAll, &closure);
|
||||
}
|
||||
|
||||
private:
|
||||
static PLDHashOperator
|
||||
MatchPattern(const nsACString& aKey,
|
||||
BaseType* aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
MOZ_ASSERT(!aKey.IsEmpty(), "Empty key!");
|
||||
MOZ_ASSERT(aValue, "Null pointer!");
|
||||
MOZ_ASSERT(aUserArg, "Null pointer!");
|
||||
|
||||
Closure* closure = static_cast<Closure*>(aUserArg);
|
||||
|
||||
if (PatternMatchesOrigin(closure->mPattern, aKey)) {
|
||||
aValue->AppendElementsTo(closure->mSelf);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
MatchIndexes(const nsACString& aKey,
|
||||
BaseType* aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
MOZ_ASSERT(!aKey.IsEmpty(), "Empty key!");
|
||||
MOZ_ASSERT(aValue, "Null pointer!");
|
||||
MOZ_ASSERT(aUserArg, "Null pointer!");
|
||||
|
||||
Closure* closure = static_cast<Closure*>(aUserArg);
|
||||
|
||||
for (uint32_t index = 0; index < closure->mIndexes->Length(); index++) {
|
||||
aValue->AppendElementsTo(closure->mIndexes->ElementAt(index),
|
||||
closure->mSelf);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
MatchPatternAndIndexes(const nsACString& aKey,
|
||||
BaseType* aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
MOZ_ASSERT(!aKey.IsEmpty(), "Empty key!");
|
||||
MOZ_ASSERT(aValue, "Null pointer!");
|
||||
MOZ_ASSERT(aUserArg, "Null pointer!");
|
||||
|
||||
Closure* closure = static_cast<Closure*>(aUserArg);
|
||||
|
||||
if (PatternMatchesOrigin(closure->mPattern, aKey)) {
|
||||
for (uint32_t index = 0; index < closure->mIndexes->Length(); index++) {
|
||||
aValue->AppendElementsTo(closure->mIndexes->ElementAt(index),
|
||||
closure->mSelf);
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
MatchAll(const nsACString& aKey,
|
||||
BaseType* aValue,
|
||||
void* aUserArg)
|
||||
{
|
||||
MOZ_ASSERT(!aKey.IsEmpty(), "Empty key!");
|
||||
MOZ_ASSERT(aValue, "Null pointer!");
|
||||
MOZ_ASSERT(aUserArg, "Null pointer!");
|
||||
|
||||
Closure* closure = static_cast<Closure*>(aUserArg);
|
||||
aValue->AppendElementsTo(closure->mSelf);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_quota_patternmatcher_h__
|
21
dom/quota/StoragePrivilege.h
Normal file
21
dom/quota/StoragePrivilege.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_storageprivilege_h__
|
||||
#define mozilla_dom_quota_storageprivilege_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
enum StoragePrivilege {
|
||||
Content,
|
||||
Chrome
|
||||
};
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_quota_storageprivilege_h__
|
81
dom/quota/UsageRunnable.h
Normal file
81
dom/quota/UsageRunnable.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_usagerunnable_h__
|
||||
#define mozilla_dom_quota_usagerunnable_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
#include "Utilities.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
class UsageRunnable
|
||||
{
|
||||
public:
|
||||
UsageRunnable()
|
||||
: mCanceled(0), mDatabaseUsage(0), mFileUsage(0)
|
||||
{ }
|
||||
|
||||
virtual ~UsageRunnable()
|
||||
{ }
|
||||
|
||||
bool
|
||||
Canceled()
|
||||
{
|
||||
return mCanceled;
|
||||
}
|
||||
|
||||
void
|
||||
AppendToDatabaseUsage(uint64_t aUsage)
|
||||
{
|
||||
IncrementUsage(&mDatabaseUsage, aUsage);
|
||||
}
|
||||
|
||||
void
|
||||
AppendToFileUsage(uint64_t aUsage)
|
||||
{
|
||||
IncrementUsage(&mFileUsage, aUsage);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
DatabaseUsage()
|
||||
{
|
||||
return mDatabaseUsage;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
FileUsage()
|
||||
{
|
||||
return mFileUsage;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
TotalUsage()
|
||||
{
|
||||
uint64_t totalUsage = mDatabaseUsage;
|
||||
IncrementUsage(&totalUsage, mFileUsage);
|
||||
return totalUsage;
|
||||
}
|
||||
|
||||
void
|
||||
ResetUsage()
|
||||
{
|
||||
mDatabaseUsage = 0;
|
||||
mFileUsage = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
int32_t mCanceled;
|
||||
|
||||
private:
|
||||
uint64_t mDatabaseUsage;
|
||||
uint64_t mFileUsage;
|
||||
};
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_quota_usagerunnable_h__
|
36
dom/quota/Utilities.h
Normal file
36
dom/quota/Utilities.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_quota_utilities_h__
|
||||
#define mozilla_dom_quota_utilities_h__
|
||||
|
||||
#include "mozilla/dom/quota/QuotaCommon.h"
|
||||
|
||||
BEGIN_QUOTA_NAMESPACE
|
||||
|
||||
inline void
|
||||
IncrementUsage(uint64_t* aUsage, uint64_t aDelta)
|
||||
{
|
||||
// Watch for overflow!
|
||||
if ((UINT64_MAX - *aUsage) < aDelta) {
|
||||
NS_WARNING("Usage exceeds the maximum!");
|
||||
*aUsage = UINT64_MAX;
|
||||
}
|
||||
else {
|
||||
*aUsage += aDelta;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
PatternMatchesOrigin(const nsACString& aPatternString, const nsACString& aOrigin)
|
||||
{
|
||||
// Aren't we smart!
|
||||
return StringBeginsWith(aOrigin, aPatternString);
|
||||
}
|
||||
|
||||
END_QUOTA_NAMESPACE
|
||||
|
||||
#endif // mozilla_dom_quota_utilities_h__
|
@ -3,6 +3,12 @@
|
||||
# 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/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIQuotaManager.idl',
|
||||
'nsIQuotaRequest.idl',
|
||||
'nsIUsageCallback.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_quota'
|
||||
|
||||
MODULE = 'dom'
|
||||
|
92
dom/quota/nsIOfflineStorage.h
Normal file
92
dom/quota/nsIOfflineStorage.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
#ifndef nsIOfflineStorage_h__
|
||||
#define nsIOfflineStorage_h__
|
||||
|
||||
#include "nsIFileStorage.h"
|
||||
|
||||
#define NS_OFFLINESTORAGE_IID \
|
||||
{0xe531b6e0, 0x55b8, 0x4f39, \
|
||||
{ 0x95, 0xbb, 0x97, 0x21, 0x4c, 0xb0, 0xf6, 0x1a } }
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace quota {
|
||||
class Client;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class nsIOfflineStorage : public nsIFileStorage
|
||||
{
|
||||
public:
|
||||
typedef mozilla::dom::quota::Client Client;
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_OFFLINESTORAGE_IID)
|
||||
|
||||
NS_IMETHOD_(Client*)
|
||||
GetClient() = 0;
|
||||
|
||||
NS_IMETHOD_(bool)
|
||||
IsOwned(nsPIDOMWindow* aOwner) = 0;
|
||||
|
||||
NS_IMETHOD_(const nsACString&)
|
||||
Origin() = 0;
|
||||
|
||||
// Implementation of this method should close the storage (without aborting
|
||||
// running operations nor discarding pending operations).
|
||||
NS_IMETHOD_(nsresult)
|
||||
Close() = 0;
|
||||
|
||||
// Whether or not the storage has had Close called on it.
|
||||
NS_IMETHOD_(bool)
|
||||
IsClosed() = 0;
|
||||
|
||||
// Implementation of this method should close the storage, all running
|
||||
// operations should be aborted and pending operations should be discarded.
|
||||
NS_IMETHOD_(void)
|
||||
Invalidate() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIOfflineStorage, NS_OFFLINESTORAGE_IID)
|
||||
|
||||
#define NS_DECL_NSIOFFLINESTORAGE \
|
||||
NS_IMETHOD_(Client*) \
|
||||
GetClient() MOZ_OVERRIDE; \
|
||||
\
|
||||
NS_IMETHOD_(bool) \
|
||||
IsOwned(nsPIDOMWindow* aOwner) MOZ_OVERRIDE; \
|
||||
\
|
||||
NS_IMETHOD_(const nsACString&) \
|
||||
Origin() MOZ_OVERRIDE; \
|
||||
\
|
||||
NS_IMETHOD_(nsresult) \
|
||||
Close() MOZ_OVERRIDE; \
|
||||
\
|
||||
NS_IMETHOD_(bool) \
|
||||
IsClosed() MOZ_OVERRIDE; \
|
||||
\
|
||||
NS_IMETHOD_(void) \
|
||||
Invalidate() MOZ_OVERRIDE;
|
||||
|
||||
#define NS_DECL_NSIOFFLINESTORAGE_NOCLOSE \
|
||||
NS_IMETHOD_(Client*) \
|
||||
GetClient() MOZ_OVERRIDE; \
|
||||
\
|
||||
NS_IMETHOD_(bool) \
|
||||
IsOwned(nsPIDOMWindow* aOwner) MOZ_OVERRIDE; \
|
||||
\
|
||||
NS_IMETHOD_(const nsACString&) \
|
||||
Origin() MOZ_OVERRIDE; \
|
||||
\
|
||||
NS_IMETHOD_(bool) \
|
||||
IsClosed() MOZ_OVERRIDE; \
|
||||
\
|
||||
NS_IMETHOD_(void) \
|
||||
Invalidate() MOZ_OVERRIDE;
|
||||
|
||||
#endif // nsIOfflineStorage_h__
|
44
dom/quota/nsIQuotaManager.idl
Normal file
44
dom/quota/nsIQuotaManager.idl
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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 "nsISupports.idl"
|
||||
|
||||
interface nsIQuotaRequest;
|
||||
interface nsIURI;
|
||||
interface nsIUsageCallback;
|
||||
|
||||
[scriptable, builtinclass, uuid(8d74e6f8-81c3-4045-9bb7-70bdb7b11b25)]
|
||||
interface nsIQuotaManager : nsISupports
|
||||
{
|
||||
/**
|
||||
* Schedules an asynchronous callback that will return the total amount of
|
||||
* disk space being used by storages for the given origin.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI whose usage is being queried.
|
||||
* @param aCallback
|
||||
* The callback that will be called when the usage is available.
|
||||
*/
|
||||
[optional_argc]
|
||||
nsIQuotaRequest
|
||||
getUsageForURI(in nsIURI aURI,
|
||||
in nsIUsageCallback aCallback,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
|
||||
/**
|
||||
* Removes all storages stored for the given URI. The files may not be
|
||||
* deleted immediately depending on prohibitive concurrent operations.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI whose storages are to be cleared.
|
||||
*/
|
||||
[optional_argc]
|
||||
void
|
||||
clearStoragesForURI(in nsIURI aURI,
|
||||
[optional] in unsigned long aAppId,
|
||||
[optional] in boolean aInMozBrowserOnly);
|
||||
};
|
14
dom/quota/nsIQuotaRequest.idl
Normal file
14
dom/quota/nsIQuotaRequest.idl
Normal file
@ -0,0 +1,14 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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 "nsISupports.idl"
|
||||
|
||||
[scriptable, function, uuid(d96769ed-63ac-4070-ac5a-4b0e1728618a)]
|
||||
interface nsIQuotaRequest : nsISupports
|
||||
{
|
||||
void
|
||||
cancel();
|
||||
};
|
20
dom/quota/nsIUsageCallback.idl
Normal file
20
dom/quota/nsIUsageCallback.idl
Normal file
@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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 "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, function, uuid(7b0f9928-0ddc-42c7-b9f2-6b2308b90b18)]
|
||||
interface nsIUsageCallback : nsISupports
|
||||
{
|
||||
void
|
||||
onUsageResult(in nsIURI aURI,
|
||||
in unsigned long long aUsage,
|
||||
in unsigned long long aFileUsage,
|
||||
in unsigned long aAppId,
|
||||
in boolean aInMozBrowserOnly);
|
||||
};
|
@ -215,13 +215,17 @@ members = [
|
||||
'nsIIDBTransaction.*',
|
||||
'nsIIDBOpenDBRequest.*',
|
||||
'nsIIDBVersionChangeEvent.*',
|
||||
'nsIIndexedDatabaseUsageCallback.*',
|
||||
'nsIIndexedDatabaseManager.*',
|
||||
|
||||
'nsIDOMDOMError.*',
|
||||
|
||||
# dom/file
|
||||
'nsIDOMLockedFile.*',
|
||||
|
||||
# dom/quota
|
||||
'nsIQuotaManager.*',
|
||||
'nsIQuotaRequest.*',
|
||||
'nsIUsageCallback.*',
|
||||
]
|
||||
|
||||
# Most interfaces can be found by searching the includePath; to find
|
||||
|
@ -95,4 +95,8 @@
|
||||
#define DOMREQUEST_SERVICE_CID \
|
||||
{ 0x3160e271, 0x138d, 0x4cc7, { 0x9d, 0x63, 0x64, 0x29, 0xf1, 0x69, 0x57, 0xc7 } }
|
||||
|
||||
// {5a75c25a-5e7e-4d90-8f7c-07eb15cc0aa8}
|
||||
#define QUOTA_MANAGER_CID \
|
||||
{ 0x5a75c25a, 0x5e7e, 0x4d90, { 0x8f, 0x7c, 0x07, 0xeb, 0x15, 0xcc, 0x0a, 0xa8 } }
|
||||
|
||||
#endif /* nsLayoutCID_h__ */
|
||||
|
@ -90,6 +90,7 @@
|
||||
#include "mozilla/dom/EventSource.h"
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||
#include "mozilla/dom/network/TCPSocketChild.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/OSFileConstants.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
@ -248,6 +249,7 @@ using namespace mozilla::dom::mobilemessage;
|
||||
using mozilla::dom::alarm::AlarmHalService;
|
||||
using mozilla::dom::indexedDB::IndexedDatabaseManager;
|
||||
using mozilla::dom::power::PowerManagerService;
|
||||
using mozilla::dom::quota::QuotaManager;
|
||||
using mozilla::dom::TCPSocketChild;
|
||||
using mozilla::dom::time::TimeService;
|
||||
|
||||
@ -280,6 +282,8 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(IndexedDatabaseManager,
|
||||
IndexedDatabaseManager::FactoryCreate)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DOMRequestService,
|
||||
DOMRequestService::FactoryCreate)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(QuotaManager,
|
||||
QuotaManager::FactoryCreate)
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(SystemWorkerManager,
|
||||
SystemWorkerManager::FactoryCreate)
|
||||
@ -783,6 +787,7 @@ NS_DEFINE_NAMED_CID(NS_DOMJSON_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_TEXTEDITOR_CID);
|
||||
NS_DEFINE_NAMED_CID(INDEXEDDB_MANAGER_CID);
|
||||
NS_DEFINE_NAMED_CID(DOMREQUEST_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(QUOTA_MANAGER_CID);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID);
|
||||
#endif
|
||||
@ -1069,6 +1074,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
||||
{ &kNS_TEXTEDITOR_CID, false, NULL, nsPlaintextEditorConstructor },
|
||||
{ &kINDEXEDDB_MANAGER_CID, false, NULL, IndexedDatabaseManagerConstructor },
|
||||
{ &kDOMREQUEST_SERVICE_CID, false, NULL, DOMRequestServiceConstructor },
|
||||
{ &kQUOTA_MANAGER_CID, false, NULL, QuotaManagerConstructor },
|
||||
#ifdef MOZ_B2G_RIL
|
||||
{ &kSYSTEMWORKERMANAGER_CID, true, NULL, SystemWorkerManagerConstructor },
|
||||
#endif
|
||||
@ -1216,6 +1222,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
||||
{ "@mozilla.org/editor/texteditor;1", &kNS_TEXTEDITOR_CID },
|
||||
{ INDEXEDDB_MANAGER_CONTRACTID, &kINDEXEDDB_MANAGER_CID },
|
||||
{ DOMREQUEST_SERVICE_CONTRACTID, &kDOMREQUEST_SERVICE_CID },
|
||||
{ QUOTA_MANAGER_CONTRACTID, &kQUOTA_MANAGER_CID },
|
||||
#ifdef MOZ_B2G_RIL
|
||||
{ SYSTEMWORKERMANAGER_CONTRACTID, &kSYSTEMWORKERMANAGER_CID },
|
||||
#endif
|
||||
@ -1294,7 +1301,7 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = {
|
||||
{ "net-channel-event-sinks", "CSPService", CSPSERVICE_CONTRACTID },
|
||||
{ JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY, "PrivilegeManager", NS_SECURITYNAMESET_CONTRACTID },
|
||||
{ "app-startup", "Script Security Manager", "service," NS_SCRIPTSECURITYMANAGER_CONTRACTID },
|
||||
{ TOPIC_WEB_APP_CLEAR_DATA, "IndexedDatabaseManager", "service," INDEXEDDB_MANAGER_CONTRACTID },
|
||||
{ TOPIC_WEB_APP_CLEAR_DATA, "QuotaManager", "service," QUOTA_MANAGER_CONTRACTID },
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
{ "app-startup", "Volume Service", "service," NS_VOLUMESERVICE_CONTRACTID },
|
||||
#endif
|
||||
|
@ -131,6 +131,7 @@
|
||||
@BINPATH@/components/dom_json.xpt
|
||||
@BINPATH@/components/dom_browserelement.xpt
|
||||
@BINPATH@/components/dom_power.xpt
|
||||
@BINPATH@/components/dom_quota.xpt
|
||||
@BINPATH@/components/dom_range.xpt
|
||||
@BINPATH@/components/dom_settings.xpt
|
||||
@BINPATH@/components/dom_sidebar.xpt
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/dom/quota/QuotaObject.h"
|
||||
|
||||
/**
|
||||
* This preference is a workaround to allow users/sysadmins to identify
|
||||
|
@ -209,9 +209,9 @@ this.ForgetAboutSite = {
|
||||
}
|
||||
}
|
||||
|
||||
// Indexed DB
|
||||
let (idbm = Cc["@mozilla.org/dom/indexeddb/manager;1"].
|
||||
getService(Ci.nsIIndexedDatabaseManager)) {
|
||||
// Offline Storages
|
||||
let (qm = Cc["@mozilla.org/dom/quota/manager;1"].
|
||||
getService(Ci.nsIQuotaManager)) {
|
||||
// delete data from both HTTP and HTTPS sites
|
||||
let caUtils = {};
|
||||
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
|
||||
@ -220,8 +220,8 @@ this.ForgetAboutSite = {
|
||||
caUtils);
|
||||
let httpURI = caUtils.makeURI("http://" + aDomain);
|
||||
let httpsURI = caUtils.makeURI("https://" + aDomain);
|
||||
idbm.clearDatabasesForURI(httpURI);
|
||||
idbm.clearDatabasesForURI(httpsURI);
|
||||
qm.clearStoragesForURI(httpURI);
|
||||
qm.clearStoragesForURI(httpsURI);
|
||||
}
|
||||
|
||||
// Everybody else (including extensions)
|
||||
|
Loading…
x
Reference in New Issue
Block a user