summaryrefslogtreecommitdiffstats
path: root/dom/indexedDB
diff options
context:
space:
mode:
Diffstat (limited to 'dom/indexedDB')
-rw-r--r--dom/indexedDB/ActorsChild.cpp11
-rw-r--r--dom/indexedDB/ActorsParent.cpp280
-rw-r--r--dom/indexedDB/FileManager.h3
-rw-r--r--dom/indexedDB/IDBCursor.cpp9
-rw-r--r--dom/indexedDB/IDBDatabase.cpp3
-rw-r--r--dom/indexedDB/IDBFactory.cpp23
-rw-r--r--dom/indexedDB/IDBIndex.cpp1
-rw-r--r--dom/indexedDB/IDBKeyRange.cpp3
-rw-r--r--dom/indexedDB/IDBObjectStore.cpp37
-rw-r--r--dom/indexedDB/IDBRequest.cpp2
-rw-r--r--dom/indexedDB/IDBWrapperCache.cpp2
-rw-r--r--dom/indexedDB/IndexedDatabaseManager.cpp75
-rw-r--r--dom/indexedDB/IndexedDatabaseManager.h17
-rw-r--r--dom/indexedDB/Key.cpp38
-rw-r--r--dom/indexedDB/Key.h15
-rw-r--r--dom/indexedDB/KeyPath.cpp99
-rw-r--r--dom/indexedDB/KeyPath.h12
-rw-r--r--dom/indexedDB/test/helpers.js4
-rw-r--r--dom/indexedDB/test/mochitest.ini2
-rw-r--r--dom/indexedDB/test/test_globalObjects_other.xul10
-rw-r--r--dom/indexedDB/test/test_lowDiskSpace.html19
-rw-r--r--dom/indexedDB/test/unit/test_lowDiskSpace.js754
-rw-r--r--dom/indexedDB/test/unit/xpcshell-head-parent-process.js3
-rw-r--r--dom/indexedDB/test/unit/xpcshell-parent-process.ini1
24 files changed, 221 insertions, 1202 deletions
diff --git a/dom/indexedDB/ActorsChild.cpp b/dom/indexedDB/ActorsChild.cpp
index 3e8f97348..30dc9b6da 100644
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -2385,9 +2385,14 @@ BackgroundVersionChangeTransactionChild::RecvComplete(const nsresult& aResult)
database->Close();
}
+ RefPtr<IDBOpenDBRequest> request = mOpenDBRequest;
+ MOZ_ASSERT(request);
+
mTransaction->FireCompleteOrAbortEvents(aResult);
- mOpenDBRequest->SetTransaction(nullptr);
+ request->SetTransaction(nullptr);
+ request = nullptr;
+
mOpenDBRequest = nullptr;
NoteComplete();
@@ -3456,6 +3461,8 @@ BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse)
RefPtr<IDBCursor> cursor;
mStrongCursor.swap(cursor);
+
+ RefPtr<IDBTransaction> transaction = mTransaction;
switch (aResponse.type()) {
case CursorResponse::Tnsresult:
@@ -3486,7 +3493,7 @@ BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse)
MOZ_CRASH("Should never get here!");
}
- mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
+ transaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
return true;
}
diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
index e6fe9e2a8..74afef452 100644
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -23,6 +23,7 @@
#include "mozilla/AppProcessChecker.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/Casting.h"
+#include "mozilla/CheckedInt.h"
#include "mozilla/EndianUtils.h"
#include "mozilla/ErrorNames.h"
#include "mozilla/LazyIdleThread.h"
@@ -249,8 +250,6 @@ const char kSQLiteJournalSuffix[] = ".sqlite-journal";
const char kSQLiteSHMSuffix[] = ".sqlite-shm";
const char kSQLiteWALSuffix[] = ".sqlite-wal";
-const char kPrefIndexedDBEnabled[] = "dom.indexedDB.enabled";
-
const char kPrefFileHandleEnabled[] = "dom.fileHandle.enabled";
#define IDB_PREFIX "indexedDB"
@@ -784,29 +783,25 @@ MakeCompressedIndexDataValues(
MOZ_ASSERT(!keyBuffer.IsEmpty());
- // Don't let |infoLength| overflow.
- if (NS_WARN_IF(UINT32_MAX - keyBuffer.Length() <
- CompressedByteCountForIndexId(info.mIndexId) +
- CompressedByteCountForNumber(keyBufferLength) +
- CompressedByteCountForNumber(sortKeyBufferLength))) {
- IDB_REPORT_INTERNAL_ERR();
- return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
- }
-
- const uint32_t infoLength =
- CompressedByteCountForIndexId(info.mIndexId) +
+ const CheckedUint32 infoLength =
+ CheckedUint32(CompressedByteCountForIndexId(info.mIndexId)) +
CompressedByteCountForNumber(keyBufferLength) +
CompressedByteCountForNumber(sortKeyBufferLength) +
keyBufferLength +
sortKeyBufferLength;
+ // Don't let |infoLength| overflow.
+ if (NS_WARN_IF(!infoLength.isValid())) {
+ IDB_REPORT_INTERNAL_ERR();
+ return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
+ }
// Don't let |blobDataLength| overflow.
- if (NS_WARN_IF(UINT32_MAX - infoLength < blobDataLength)) {
+ if (NS_WARN_IF(UINT32_MAX - infoLength.value() < blobDataLength)) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
- blobDataLength += infoLength;
+ blobDataLength += infoLength.value();
}
UniqueFreePtr<uint8_t> blobData(
@@ -4134,7 +4129,6 @@ GetDatabaseFileURL(nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
- uint32_t aTelemetryId,
nsIFileURL** aResult)
{
MOZ_ASSERT(aDatabaseFile);
@@ -4166,18 +4160,10 @@ GetDatabaseFileURL(nsIFile* aDatabaseFile,
nsAutoCString type;
PersistenceTypeToText(aPersistenceType, type);
- nsAutoCString telemetryFilenameClause;
- if (aTelemetryId) {
- telemetryFilenameClause.AssignLiteral("&telemetryFilename=indexedDB-");
- telemetryFilenameClause.AppendInt(aTelemetryId);
- telemetryFilenameClause.AppendLiteral(".sqlite");
- }
-
rv = fileUrl->SetQuery(NS_LITERAL_CSTRING("persistenceType=") + type +
NS_LITERAL_CSTRING("&group=") + aGroup +
NS_LITERAL_CSTRING("&origin=") + aOrigin +
- NS_LITERAL_CSTRING("&cache=private") +
- telemetryFilenameClause);
+ NS_LITERAL_CSTRING("&cache=private"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -4427,7 +4413,6 @@ CreateStorageConnection(nsIFile* aDBFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
- uint32_t aTelemetryId,
mozIStorageConnection** aConnection)
{
AssertIsOnIOThread();
@@ -4442,24 +4427,11 @@ CreateStorageConnection(nsIFile* aDBFile,
nsresult rv;
bool exists;
- if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
- rv = aDBFile->Exists(&exists);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
-
- if (!exists) {
- NS_WARNING("Refusing to create database because disk space is low!");
- return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
- }
- }
-
nsCOMPtr<nsIFileURL> dbFileUrl;
rv = GetDatabaseFileURL(aDBFile,
aPersistenceType,
aGroup,
aOrigin,
- aTelemetryId,
getter_AddRefs(dbFileUrl));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -4895,7 +4867,6 @@ GetStorageConnection(nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
- uint32_t aTelemetryId,
mozIStorageConnection** aConnection)
{
MOZ_ASSERT(!NS_IsMainThread());
@@ -4923,7 +4894,6 @@ GetStorageConnection(nsIFile* aDatabaseFile,
aPersistenceType,
aGroup,
aOrigin,
- aTelemetryId,
getter_AddRefs(dbFileUrl));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -4960,7 +4930,6 @@ GetStorageConnection(const nsAString& aDatabaseFilePath,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
- uint32_t aTelemetryId,
mozIStorageConnection** aConnection)
{
MOZ_ASSERT(!NS_IsMainThread());
@@ -4979,7 +4948,6 @@ GetStorageConnection(const nsAString& aDatabaseFilePath,
aPersistenceType,
aGroup,
aOrigin,
- aTelemetryId,
aConnection);
}
@@ -6301,7 +6269,6 @@ private:
const nsCString mId;
const nsString mFilePath;
uint32_t mActiveMutableFileCount;
- const uint32_t mTelemetryId;
const PersistenceType mPersistenceType;
const bool mFileHandleDisabled;
const bool mChromeWriteAccessAllowed;
@@ -6318,7 +6285,6 @@ public:
const Maybe<ContentParentId>& aOptionalContentParentId,
const nsACString& aGroup,
const nsACString& aOrigin,
- uint32_t aTelemetryId,
FullDatabaseMetadata* aMetadata,
FileManager* aFileManager,
already_AddRefed<DirectoryLock> aDirectoryLock,
@@ -6377,12 +6343,6 @@ public:
return mId;
}
- uint32_t
- TelemetryId() const
- {
- return mTelemetryId;
- }
-
PersistenceType
Type() const
{
@@ -7678,8 +7638,6 @@ class OpenDatabaseOp final
// cycles.
VersionChangeOp* mVersionChangeOp;
- uint32_t mTelemetryId;
-
public:
OpenDatabaseOp(Factory* aFactory,
already_AddRefed<ContentParent> aContentParent,
@@ -10307,13 +10265,6 @@ typedef nsDataHashtable<nsIDHashKey, DatabaseLoggingInfo*>
StaticAutoPtr<DatabaseLoggingInfoHashtable> gLoggingInfoHashtable;
-typedef nsDataHashtable<nsUint32HashKey, uint32_t> TelemetryIdHashtable;
-
-StaticAutoPtr<TelemetryIdHashtable> gTelemetryIdHashtable;
-
-// Protects all reads and writes to gTelemetryIdHashtable.
-StaticAutoPtr<Mutex> gTelemetryIdMutex;
-
#ifdef DEBUG
StaticRefPtr<DEBUGThreadSlower> gDEBUGThreadSlower;
@@ -10409,88 +10360,6 @@ DecreaseBusyCount()
}
}
-uint32_t
-TelemetryIdForFile(nsIFile* aFile)
-{
- // May be called on any thread!
-
- MOZ_ASSERT(aFile);
- MOZ_ASSERT(gTelemetryIdMutex);
-
- // The storage directory is structured like this:
- //
- // <profile>/storage/<persistence>/<origin>/idb/<filename>.sqlite
- //
- // For the purposes of this function we're only concerned with the
- // <persistence>, <origin>, and <filename> pieces.
-
- nsString filename;
- MOZ_ALWAYS_SUCCEEDS(aFile->GetLeafName(filename));
-
- // Make sure we were given a database file.
- NS_NAMED_LITERAL_STRING(sqliteExtension, ".sqlite");
-
- MOZ_ASSERT(StringEndsWith(filename, sqliteExtension));
-
- filename.Truncate(filename.Length() - sqliteExtension.Length());
-
- // Get the "idb" directory.
- nsCOMPtr<nsIFile> idbDirectory;
- MOZ_ALWAYS_SUCCEEDS(aFile->GetParent(getter_AddRefs(idbDirectory)));
-
- DebugOnly<nsString> idbLeafName;
- MOZ_ASSERT(NS_SUCCEEDED(idbDirectory->GetLeafName(idbLeafName)));
- MOZ_ASSERT(static_cast<nsString&>(idbLeafName).EqualsLiteral("idb"));
-
- // Get the <origin> directory.
- nsCOMPtr<nsIFile> originDirectory;
- MOZ_ALWAYS_SUCCEEDS(
- idbDirectory->GetParent(getter_AddRefs(originDirectory)));
-
- nsString origin;
- MOZ_ALWAYS_SUCCEEDS(originDirectory->GetLeafName(origin));
-
- // Any databases in these directories are owned by the application and should
- // not have their filenames masked. Hopefully they also appear in the
- // Telemetry.cpp whitelist.
- if (origin.EqualsLiteral("chrome") ||
- origin.EqualsLiteral("moz-safe-about+home")) {
- return 0;
- }
-
- // Get the <persistence> directory.
- nsCOMPtr<nsIFile> persistenceDirectory;
- MOZ_ALWAYS_SUCCEEDS(
- originDirectory->GetParent(getter_AddRefs(persistenceDirectory)));
-
- nsString persistence;
- MOZ_ALWAYS_SUCCEEDS(persistenceDirectory->GetLeafName(persistence));
-
- NS_NAMED_LITERAL_STRING(separator, "*");
-
- uint32_t hashValue = HashString(persistence + separator +
- origin + separator +
- filename);
-
- MutexAutoLock lock(*gTelemetryIdMutex);
-
- if (!gTelemetryIdHashtable) {
- gTelemetryIdHashtable = new TelemetryIdHashtable();
- }
-
- uint32_t id;
- if (!gTelemetryIdHashtable->Get(hashValue, &id)) {
- static uint32_t sNextId = 1;
-
- // We're locked, no need for atomics.
- id = sNextId++;
-
- gTelemetryIdHashtable->Put(hashValue, id);
- }
-
- return id;
-}
-
} // namespace
/*******************************************************************************
@@ -12270,7 +12139,6 @@ ConnectionPool::GetOrCreateConnection(const Database* aDatabase,
aDatabase->Type(),
aDatabase->Group(),
aDatabase->Origin(),
- aDatabase->TelemetryId(),
getter_AddRefs(storageConnection));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -14139,7 +14007,6 @@ Database::Database(Factory* aFactory,
const Maybe<ContentParentId>& aOptionalContentParentId,
const nsACString& aGroup,
const nsACString& aOrigin,
- uint32_t aTelemetryId,
FullDatabaseMetadata* aMetadata,
FileManager* aFileManager,
already_AddRefed<DirectoryLock> aDirectoryLock,
@@ -14156,7 +14023,6 @@ Database::Database(Factory* aFactory,
, mId(aMetadata->mDatabaseId)
, mFilePath(aMetadata->mFilePath)
, mActiveMutableFileCount(0)
- , mTelemetryId(aTelemetryId)
, mPersistenceType(aMetadata->mCommonMetadata.persistenceType())
, mFileHandleDisabled(aFileHandleDisabled)
, mChromeWriteAccessAllowed(aChromeWriteAccessAllowed)
@@ -17396,8 +17262,7 @@ FileManager::InitDirectory(nsIFile* aDirectory,
nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
- const nsACString& aOrigin,
- uint32_t aTelemetryId)
+ const nsACString& aOrigin)
{
AssertIsOnIOThread();
MOZ_ASSERT(aDirectory);
@@ -17469,7 +17334,6 @@ FileManager::InitDirectory(nsIFile* aDirectory,
aPersistenceType,
aGroup,
aOrigin,
- aTelemetryId,
getter_AddRefs(connection));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -17653,11 +17517,6 @@ QuotaClient::QuotaClient()
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(!sInstance, "We expect this to be a singleton!");
- MOZ_ASSERT(!gTelemetryIdMutex);
-
- // Always create this so that later access to gTelemetryIdHashtable can be
- // properly synchronized.
- gTelemetryIdMutex = new Mutex("IndexedDB gTelemetryIdMutex");
sInstance = this;
}
@@ -17666,14 +17525,8 @@ QuotaClient::~QuotaClient()
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(sInstance == this, "We expect this to be a singleton!");
- MOZ_ASSERT(gTelemetryIdMutex);
MOZ_ASSERT(!mMaintenanceThreadPool);
- // No one else should be able to touch gTelemetryIdHashtable now that the
- // QuotaClient has gone away.
- gTelemetryIdHashtable = nullptr;
- gTelemetryIdMutex = nullptr;
-
sInstance = nullptr;
}
@@ -17947,8 +17800,7 @@ QuotaClient::InitOrigin(PersistenceType aPersistenceType,
initInfo.mDatabaseFile,
aPersistenceType,
aGroup,
- aOrigin,
- TelemetryIdForFile(initInfo.mDatabaseFile));
+ aOrigin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -19041,7 +18893,6 @@ DatabaseMaintenance::PerformMaintenanceOnDatabase()
mPersistenceType,
mGroup,
mOrigin,
- TelemetryIdForFile(databaseFile),
getter_AddRefs(connection));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
@@ -19240,23 +19091,6 @@ DatabaseMaintenance::DetermineMaintenanceAction(
return NS_OK;
}
- bool lowDiskSpace = IndexedDatabaseManager::InLowDiskSpaceMode();
-
- if (QuotaManager::IsRunningXPCShellTests()) {
- // If we're running XPCShell then we want to test both the low disk space
- // and normal disk space code paths so pick semi-randomly based on the
- // current time.
- lowDiskSpace = ((PR_Now() / PR_USEC_PER_MSEC) % 2) == 0;
- }
-
- // If we're low on disk space then the best we can hope for is that an
- // incremental vacuum might free some space. That is a journaled operation so
- // it may not be possible even then.
- if (lowDiskSpace) {
- *aMaintenanceAction = MaintenanceAction::IncrementalVacuum;
- return NS_OK;
- }
-
// This method shouldn't make any permanent changes to the database, so make
// sure everything gets rolled back when we leave.
mozStorageTransaction transaction(aConnection,
@@ -21172,16 +21006,6 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
}
- if (NS_WARN_IF(!Preferences::GetBool(kPrefIndexedDBEnabled, false))) {
- if (aContentParent) {
- // The DOM in the other process should have kept us from receiving any
- // indexedDB messages so assume that the child is misbehaving.
- aContentParent->KillHard("IndexedDB CheckPermission 1");
- }
-
- return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
- }
-
const ContentPrincipalInfo& contentPrincipalInfo =
principalInfo.get_ContentPrincipalInfo();
if (contentPrincipalInfo.attrs().mPrivateBrowsingId != 0) {
@@ -21668,7 +21492,6 @@ OpenDatabaseOp::OpenDatabaseOp(Factory* aFactory,
, mMetadata(new FullDatabaseMetadata(aParams.metadata()))
, mRequestedVersion(aParams.metadata().version())
, mVersionChangeOp(nullptr)
- , mTelemetryId(0)
{
if (mContentParent) {
// This is a little scary but it looks safe to call this off the main thread
@@ -21777,8 +21600,6 @@ OpenDatabaseOp::DoDatabaseWork()
return rv;
}
- mTelemetryId = TelemetryIdForFile(dbFile);
-
#ifdef DEBUG
nsString databaseFilePath;
rv = dbFile->GetPath(databaseFilePath);
@@ -21809,7 +21630,6 @@ OpenDatabaseOp::DoDatabaseWork()
persistenceType,
mGroup,
mOrigin,
- mTelemetryId,
getter_AddRefs(connection));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -22692,7 +22512,6 @@ OpenDatabaseOp::EnsureDatabaseActor()
mOptionalContentParentId,
mGroup,
mOrigin,
- mTelemetryId,
mMetadata,
mFileManager,
mDirectoryLock.forget(),
@@ -23869,32 +23688,38 @@ TransactionDatabaseOperationBase::SendPreprocessInfoOrResults(
MOZ_ASSERT(mTransaction);
if (NS_WARN_IF(IsActorDestroyed())) {
- // Don't send any notifications if the actor was destroyed already.
+ // Normally we wouldn't need to send any notifications if the actor was
+ // already destroyed, but this can be a VersionChangeOp which needs to
+ // notify its parent operation (OpenDatabaseOp) about the failure.
+ // So SendFailureResult needs to be called even when the actor was
+ // destroyed. Normal operations redundantly check if the actor was
+ // destroyed in SendSuccessResult and SendFailureResult, therefore it's
+ // ok to call it in all cases here.
if (NS_SUCCEEDED(mResultCode)) {
IDB_REPORT_INTERNAL_ERR();
mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
- } else {
- if (mTransaction->IsInvalidated() || mTransaction->IsAborted()) {
- // Aborted transactions always see their requests fail with ABORT_ERR,
- // even if the request succeeded or failed with another error.
- mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
- } else if (NS_SUCCEEDED(mResultCode)) {
- if (aSendPreprocessInfo) {
- // This should not release the IPDL reference.
- mResultCode = SendPreprocessInfo();
- } else {
- // This may release the IPDL reference.
- mResultCode = SendSuccessResult();
- }
+ } else if (mTransaction->IsInvalidated() || mTransaction->IsAborted()) {
+ // Aborted transactions always see their requests fail with ABORT_ERR,
+ // even if the request succeeded or failed with another error.
+ mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
+ }
+
+ if (NS_SUCCEEDED(mResultCode)) {
+ if (aSendPreprocessInfo) {
+ // This should not release the IPDL reference.
+ mResultCode = SendPreprocessInfo();
+ } else {
+ // This may release the IPDL reference.
+ mResultCode = SendSuccessResult();
}
+ }
- if (NS_FAILED(mResultCode)) {
- // This should definitely release the IPDL reference.
- if (!SendFailureResult(mResultCode)) {
- // Abort the transaction.
- mTransaction->Abort(mResultCode, /* aForce */ false);
- }
+ if (NS_FAILED(mResultCode)) {
+ // This should definitely release the IPDL reference.
+ if (!SendFailureResult(mResultCode)) {
+ // Abort the transaction.
+ mTransaction->Abort(mResultCode, /* aForce */ false);
}
}
@@ -24379,11 +24204,6 @@ CreateFileOp::DoDatabaseWork()
"CreateFileOp::DoDatabaseWork",
js::ProfileEntry::Category::STORAGE);
- if (NS_WARN_IF(IndexedDatabaseManager::InLowDiskSpaceMode())) {
- NS_WARNING("Refusing to create file because disk space is low!");
- return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
- }
-
if (NS_WARN_IF(QuotaManager::IsShuttingDown()) || !OperationMayProceed()) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@@ -24524,10 +24344,6 @@ CreateObjectStoreOp::DoDatabaseWork(DatabaseConnection* aConnection)
"CreateObjectStoreOp::DoDatabaseWork",
js::ProfileEntry::Category::STORAGE);
- if (NS_WARN_IF(IndexedDatabaseManager::InLowDiskSpaceMode())) {
- return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
- }
-
#ifdef DEBUG
{
// Make sure that we're not creating an object store with the same name as
@@ -24851,10 +24667,6 @@ RenameObjectStoreOp::DoDatabaseWork(DatabaseConnection* aConnection)
"RenameObjectStoreOp::DoDatabaseWork",
js::ProfileEntry::Category::STORAGE);
- if (NS_WARN_IF(IndexedDatabaseManager::InLowDiskSpaceMode())) {
- return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
- }
-
#ifdef DEBUG
{
// Make sure that we're not renaming an object store with the same name as
@@ -24944,7 +24756,6 @@ CreateIndexOp::InsertDataFromObjectStore(DatabaseConnection* aConnection)
{
MOZ_ASSERT(aConnection);
aConnection->AssertIsOnConnectionThread();
- MOZ_ASSERT(!IndexedDatabaseManager::InLowDiskSpaceMode());
MOZ_ASSERT(mMaybeUniqueIndexTable);
PROFILER_LABEL("IndexedDB",
@@ -24995,7 +24806,6 @@ CreateIndexOp::InsertDataFromObjectStoreInternal(
{
MOZ_ASSERT(aConnection);
aConnection->AssertIsOnConnectionThread();
- MOZ_ASSERT(!IndexedDatabaseManager::InLowDiskSpaceMode());
MOZ_ASSERT(mMaybeUniqueIndexTable);
DebugOnly<void*> storageConnection = aConnection->GetStorageConnection();
@@ -25072,10 +24882,6 @@ CreateIndexOp::DoDatabaseWork(DatabaseConnection* aConnection)
"CreateIndexOp::DoDatabaseWork",
js::ProfileEntry::Category::STORAGE);
- if (NS_WARN_IF(IndexedDatabaseManager::InLowDiskSpaceMode())) {
- return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
- }
-
#ifdef DEBUG
{
// Make sure that we're not creating an index with the same name and object
@@ -25952,10 +25758,6 @@ RenameIndexOp::DoDatabaseWork(DatabaseConnection* aConnection)
"RenameIndexOp::DoDatabaseWork",
js::ProfileEntry::Category::STORAGE);
- if (NS_WARN_IF(IndexedDatabaseManager::InLowDiskSpaceMode())) {
- return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
- }
-
#ifdef DEBUG
{
// Make sure that we're not renaming an index with the same name as another
@@ -26440,10 +26242,6 @@ ObjectStoreAddOrPutRequestOp::DoDatabaseWork(DatabaseConnection* aConnection)
"ObjectStoreAddOrPutRequestOp::DoDatabaseWork",
js::ProfileEntry::Category::STORAGE);
- if (NS_WARN_IF(IndexedDatabaseManager::InLowDiskSpaceMode())) {
- return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
- }
-
DatabaseConnection::AutoSavepoint autoSave;
nsresult rv = autoSave.Start(Transaction());
if (NS_WARN_IF(NS_FAILED(rv))) {
diff --git a/dom/indexedDB/FileManager.h b/dom/indexedDB/FileManager.h
index da917f431..0fba46ec0 100644
--- a/dom/indexedDB/FileManager.h
+++ b/dom/indexedDB/FileManager.h
@@ -58,8 +58,7 @@ public:
nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
- const nsACString& aOrigin,
- uint32_t aTelemetryId);
+ const nsACString& aOrigin);
static nsresult
GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
diff --git a/dom/indexedDB/IDBCursor.cpp b/dom/indexedDB/IDBCursor.cpp
index 7ae35e981..be0295dc7 100644
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -430,7 +430,7 @@ IDBCursor::Continue(JSContext* aCx,
}
Key key;
- aRv = key.SetFromJSVal(aCx, aKey);
+ aRv = key.SetFromJSVal(aCx, aKey, /* aCallGetters */ true);
if (aRv.Failed()) {
return;
}
@@ -536,7 +536,7 @@ IDBCursor::ContinuePrimaryKey(JSContext* aCx,
}
Key key;
- aRv = key.SetFromJSVal(aCx, aKey);
+ aRv = key.SetFromJSVal(aCx, aKey, /* aCallGetters */ true);
if (aRv.Failed()) {
return;
}
@@ -558,7 +558,7 @@ IDBCursor::ContinuePrimaryKey(JSContext* aCx,
}
Key primaryKey;
- aRv = primaryKey.SetFromJSVal(aCx, aPrimaryKey);
+ aRv = primaryKey.SetFromJSVal(aCx, aPrimaryKey, /* aCallGetters */ true);
if (aRv.Failed()) {
return;
}
@@ -718,7 +718,7 @@ IDBCursor::Update(JSContext* aCx, JS::Handle<JS::Value> aValue,
const KeyPath& keyPath = objectStore->GetKeyPath();
Key key;
- aRv = keyPath.ExtractKey(aCx, aValue, key);
+ aRv = keyPath.ExtractKey(aCx, aValue, key, /* aCallGetters */ false);
if (aRv.Failed()) {
return nullptr;
}
@@ -948,7 +948,6 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceObjectStore)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceIndex)
diff --git a/dom/indexedDB/IDBDatabase.cpp b/dom/indexedDB/IDBDatabase.cpp
index 5592e7f93..6ef352801 100644
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -1257,6 +1257,9 @@ IDBDatabase::LastRelease()
AssertIsOnOwningThread();
CloseInternal();
+
+ // Make sure that file actors created after the database was closed are expired.
+ ExpireFileActors(/* aExpireAll */ true);
if (mBackgroundActor) {
mBackgroundActor->SendDeleteMeInternal();
diff --git a/dom/indexedDB/IDBFactory.cpp b/dom/indexedDB/IDBFactory.cpp
index 663828978..66471fe24 100644
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -47,12 +47,6 @@ namespace dom {
using namespace mozilla::dom::quota;
using namespace mozilla::ipc;
-namespace {
-
-const char kPrefIndexedDBEnabled[] = "dom.indexedDB.enabled";
-
-} // namespace
-
class IDBFactory::BackgroundCreateCallback final
: public nsIIPCBackgroundChildCreateCallback
{
@@ -130,12 +124,6 @@ IDBFactory::CreateForWindow(nsPIDOMWindowInner* aWindow,
nsCOMPtr<nsIPrincipal> principal;
nsresult rv = AllowedForWindowInternal(aWindow, getter_AddRefs(principal));
- if (!(NS_SUCCEEDED(rv) && nsContentUtils::IsSystemPrincipal(principal)) &&
- NS_WARN_IF(!Preferences::GetBool(kPrefIndexedDBEnabled, false))) {
- *aFactory = nullptr;
- return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
- }
-
if (rv == NS_ERROR_DOM_NOT_SUPPORTED_ERR) {
NS_WARNING("IndexedDB is not permitted in a third-party window.");
*aFactory = nullptr;
@@ -246,12 +234,6 @@ IDBFactory::CreateForMainThreadJSInternal(
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipalInfo);
- if (aPrincipalInfo->type() != PrincipalInfo::TSystemPrincipalInfo &&
- NS_WARN_IF(!Preferences::GetBool(kPrefIndexedDBEnabled, false))) {
- *aFactory = nullptr;
- return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
- }
-
IndexedDatabaseManager* mgr = IndexedDatabaseManager::GetOrCreate();
if (NS_WARN_IF(!mgr)) {
IDB_REPORT_INTERNAL_ERR();
@@ -500,13 +482,13 @@ IDBFactory::Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
JS::Handle<JS::Value> aSecond, ErrorResult& aRv)
{
Key first, second;
- nsresult rv = first.SetFromJSVal(aCx, aFirst);
+ nsresult rv = first.SetFromJSVal(aCx, aFirst, /* aCallGetters */ true);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return 0;
}
- rv = second.SetFromJSVal(aCx, aSecond);
+ rv = second.SetFromJSVal(aCx, aSecond, /* aCallGetters */ true);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return 0;
@@ -883,7 +865,6 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBFactory)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBFactory)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
diff --git a/dom/indexedDB/IDBIndex.cpp b/dom/indexedDB/IDBIndex.cpp
index 657e744c9..af50926e6 100644
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -652,7 +652,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBIndex)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
diff --git a/dom/indexedDB/IDBKeyRange.cpp b/dom/indexedDB/IDBKeyRange.cpp
index 2de48a70c..168fb4a5a 100644
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -24,7 +24,7 @@ GetKeyFromJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal,
Key& aKey)
{
- nsresult rv = aKey.SetFromJSVal(aCx, aVal);
+ nsresult rv = aKey.SetFromJSVal(aCx, aVal, /* aCallGetters */ true);
if (NS_FAILED(rv)) {
MOZ_ASSERT(NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM_INDEXEDDB);
return rv;
@@ -239,7 +239,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(IDBKeyRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBKeyRange)
diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp
index 8a0b292ad..cbac30894 100644
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1084,7 +1084,7 @@ IDBObjectStore::AppendIndexUpdateInfo(
if (!aMultiEntry) {
Key key;
- rv = aKeyPath.ExtractKey(aCx, aVal, key);
+ rv = aKeyPath.ExtractKey(aCx, aVal, key, /* aCallGetters */ false);
// If an index's keyPath doesn't match an object, we ignore that object.
if (rv == NS_ERROR_DOM_INDEXEDDB_DATA_ERR || key.IsUnset()) {
@@ -1114,7 +1114,7 @@ IDBObjectStore::AppendIndexUpdateInfo(
}
bool isArray;
- if (!JS_IsArrayObject(aCx, val, &isArray)) {
+ if (NS_WARN_IF(!JS_IsArrayObject(aCx, val, &isArray))) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
@@ -1127,14 +1127,31 @@ IDBObjectStore::AppendIndexUpdateInfo(
}
for (uint32_t arrayIndex = 0; arrayIndex < arrayLength; arrayIndex++) {
- JS::Rooted<JS::Value> arrayItem(aCx);
- if (NS_WARN_IF(!JS_GetElement(aCx, array, arrayIndex, &arrayItem))) {
+ JS::RootedId indexId(aCx);
+ if (NS_WARN_IF(!JS_IndexToId(aCx, arrayIndex, &indexId))) {
+ IDB_REPORT_INTERNAL_ERR();
+ return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
+ }
+
+ bool hasOwnProperty;
+ if (NS_WARN_IF(
+ !JS_HasOwnPropertyById(aCx, array, indexId, &hasOwnProperty))) {
+ IDB_REPORT_INTERNAL_ERR();
+ return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
+ }
+
+ if (!hasOwnProperty) {
+ continue;
+ }
+
+ JS::RootedValue arrayItem(aCx);
+ if (NS_WARN_IF(!JS_GetPropertyById(aCx, array, indexId, &arrayItem))) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
Key value;
- if (NS_FAILED(value.SetFromJSVal(aCx, arrayItem)) ||
+ if (NS_FAILED(value.SetFromJSVal(aCx, arrayItem, /* aCallGetters */ false)) ||
value.IsUnset()) {
// Not a value we can do anything with, ignore it.
continue;
@@ -1153,7 +1170,7 @@ IDBObjectStore::AppendIndexUpdateInfo(
}
else {
Key value;
- if (NS_FAILED(value.SetFromJSVal(aCx, val)) ||
+ if (NS_FAILED(value.SetFromJSVal(aCx, val, /* aCallGetters */ false)) ||
value.IsUnset()) {
// Not a value we can do anything with, ignore it.
return NS_OK;
@@ -1324,12 +1341,12 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
if (!HasValidKeyPath()) {
// Out-of-line keys must be passed in.
- rv = aKey.SetFromJSVal(aCx, aKeyVal);
+ rv = aKey.SetFromJSVal(aCx, aKeyVal, /* aCallGetters */ true);
if (NS_FAILED(rv)) {
return rv;
}
} else if (!isAutoIncrement) {
- rv = GetKeyPath().ExtractKey(aCx, aValue, aKey);
+ rv = GetKeyPath().ExtractKey(aCx, aValue, aKey, /* aCallGetters */ false);
if (NS_FAILED(rv)) {
return rv;
}
@@ -1368,7 +1385,8 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
aValue,
aKey,
&GetAddInfoCallback,
- &data);
+ &data,
+ /* aCallGetters */ false);
} else {
rv = GetAddInfoCallback(aCx, &data);
}
@@ -1758,7 +1776,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBObjectStore)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBObjectStore)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexes)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeletedIndexes)
diff --git a/dom/indexedDB/IDBRequest.cpp b/dom/indexedDB/IDBRequest.cpp
index 919d3adc7..e0e318059 100644
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -417,8 +417,6 @@ IDBRequest::GetError(ErrorResult& aRv)
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
- // Don't need NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS because
- // DOMEventTargetHelper does it for us.
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceAsObjectStore)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceAsIndex)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceAsCursor)
diff --git a/dom/indexedDB/IDBWrapperCache.cpp b/dom/indexedDB/IDBWrapperCache.cpp
index df62514c8..ccc2bb43e 100644
--- a/dom/indexedDB/IDBWrapperCache.cpp
+++ b/dom/indexedDB/IDBWrapperCache.cpp
@@ -18,8 +18,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(IDBWrapperCache)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBWrapperCache,
DOMEventTargetHelper)
- // Don't need NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS because
- // DOMEventTargetHelper does it for us.
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBWrapperCache,
diff --git a/dom/indexedDB/IndexedDatabaseManager.cpp b/dom/indexedDB/IndexedDatabaseManager.cpp
index 62ba51c08..213de5cc9 100644
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -8,11 +8,9 @@
#include "chrome/common/ipc_channel.h" // for IPC::Channel::kMaximumMessageSize
#include "nsIConsoleService.h"
-#include "nsIDiskSpaceWatcher.h"
#include "nsIDOMWindow.h"
#include "nsIEventTarget.h"
#include "nsIFile.h"
-#include "nsIObserverService.h"
#include "nsIScriptError.h"
#include "nsIScriptGlobalObject.h"
@@ -64,11 +62,6 @@
#define IDB_STR "indexedDB"
-// The two possible values for the data argument when receiving the disk space
-// observer notification.
-#define LOW_DISK_SPACE_DATA_FULL "full"
-#define LOW_DISK_SPACE_DATA_FREE "free"
-
namespace mozilla {
namespace dom {
namespace indexedDB {
@@ -313,8 +306,6 @@ Atomic<IndexedDatabaseManager::LoggingMode>
IndexedDatabaseManager::sLoggingMode(
IndexedDatabaseManager::Logging_Disabled);
-mozilla::Atomic<bool> IndexedDatabaseManager::sLowDiskSpaceMode(false);
-
// static
IndexedDatabaseManager*
IndexedDatabaseManager::GetOrCreate()
@@ -329,24 +320,6 @@ IndexedDatabaseManager::GetOrCreate()
if (!gDBManager) {
sIsMainProcess = XRE_IsParentProcess();
- if (sIsMainProcess && Preferences::GetBool("disk_space_watcher.enabled", false)) {
- // See if we're starting up in low disk space conditions.
- nsCOMPtr<nsIDiskSpaceWatcher> watcher =
- do_GetService(DISKSPACEWATCHER_CONTRACTID);
- if (watcher) {
- bool isDiskFull;
- if (NS_SUCCEEDED(watcher->GetIsDiskFull(&isDiskFull))) {
- sLowDiskSpaceMode = isDiskFull;
- }
- else {
- NS_WARNING("GetIsDiskFull failed!");
- }
- }
- else {
- NS_WARNING("No disk space watcher component available!");
- }
- }
-
RefPtr<IndexedDatabaseManager> instance(new IndexedDatabaseManager());
nsresult rv = instance->Init();
@@ -380,13 +353,6 @@ IndexedDatabaseManager::Init()
// During Init() we can't yet call IsMainProcess(), just check sIsMainProcess
// directly.
if (sIsMainProcess) {
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- NS_ENSURE_STATE(obs);
-
- nsresult rv =
- obs->AddObserver(this, DISKSPACEWATCHER_OBSERVER_TOPIC, false);
- NS_ENSURE_SUCCESS(rv, rv);
-
mDeleteTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
NS_ENSURE_STATE(mDeleteTimer);
@@ -680,16 +646,6 @@ IndexedDatabaseManager::IsMainProcess()
return sIsMainProcess;
}
-//static
-bool
-IndexedDatabaseManager::InLowDiskSpaceMode()
-{
- NS_ASSERTION(gDBManager,
- "InLowDiskSpaceMode() called before indexedDB has been "
- "initialized!");
- return sLowDiskSpaceMode;
-}
-
// static
IndexedDatabaseManager::LoggingMode
IndexedDatabaseManager::GetLoggingMode()
@@ -1087,36 +1043,7 @@ IndexedDatabaseManager::GetLocale()
NS_IMPL_ADDREF(IndexedDatabaseManager)
NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager, Destroy())
-NS_IMPL_QUERY_INTERFACE(IndexedDatabaseManager, nsIObserver, nsITimerCallback)
-
-NS_IMETHODIMP
-IndexedDatabaseManager::Observe(nsISupports* aSubject, const char* aTopic,
- const char16_t* aData)
-{
- NS_ASSERTION(IsMainProcess(), "Wrong process!");
- NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
- if (!strcmp(aTopic, DISKSPACEWATCHER_OBSERVER_TOPIC)) {
- NS_ASSERTION(aData, "No data?!");
-
- const nsDependentString data(aData);
-
- if (data.EqualsLiteral(LOW_DISK_SPACE_DATA_FULL)) {
- sLowDiskSpaceMode = true;
- }
- else if (data.EqualsLiteral(LOW_DISK_SPACE_DATA_FREE)) {
- sLowDiskSpaceMode = false;
- }
- else {
- NS_NOTREACHED("Unknown data value!");
- }
-
- return NS_OK;
- }
-
- NS_NOTREACHED("Unknown topic!");
- return NS_ERROR_UNEXPECTED;
-}
+NS_IMPL_QUERY_INTERFACE(IndexedDatabaseManager, nsITimerCallback)
NS_IMETHODIMP
IndexedDatabaseManager::Notify(nsITimer* aTimer)
diff --git a/dom/indexedDB/IndexedDatabaseManager.h b/dom/indexedDB/IndexedDatabaseManager.h
index d63c548ec..fb4376426 100644
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -7,8 +7,6 @@
#ifndef mozilla_dom_indexeddatabasemanager_h__
#define mozilla_dom_indexeddatabasemanager_h__
-#include "nsIObserver.h"
-
#include "js/TypeDecls.h"
#include "mozilla/Atomics.h"
#include "mozilla/dom/quota/PersistenceType.h"
@@ -43,8 +41,7 @@ class FileManagerInfo;
} // namespace indexedDB
class IndexedDatabaseManager final
- : public nsIObserver
- , public nsITimerCallback
+ : public nsITimerCallback
{
typedef mozilla::dom::quota::PersistenceType PersistenceType;
typedef mozilla::dom::quota::QuotaManager QuotaManager;
@@ -62,7 +59,6 @@ public:
};
NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
NS_DECL_NSITIMERCALLBACK
// Returns a non-owning reference.
@@ -87,16 +83,6 @@ public:
#endif
static bool
- InLowDiskSpaceMode()
-#ifdef DEBUG
- ;
-#else
- {
- return !!sLowDiskSpaceMode;
- }
-#endif
-
- static bool
InTestingMode();
static bool
@@ -244,7 +230,6 @@ private:
static bool sFullSynchronousMode;
static LazyLogModule sLoggingModule;
static Atomic<LoggingMode> sLoggingMode;
- static mozilla::Atomic<bool> sLowDiskSpaceMode;
};
} // namespace dom
diff --git a/dom/indexedDB/Key.cpp b/dom/indexedDB/Key.cpp
index 0f693b2c6..575734af2 100644
--- a/dom/indexedDB/Key.cpp
+++ b/dom/indexedDB/Key.cpp
@@ -201,8 +201,11 @@ Key::ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const
}
nsresult
-Key::EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
- uint8_t aTypeOffset, uint16_t aRecursionDepth)
+Key::EncodeJSValInternal(JSContext* aCx,
+ JS::Handle<JS::Value> aVal,
+ uint8_t aTypeOffset,
+ uint16_t aRecursionDepth,
+ bool aCallGetters)
{
static_assert(eMaxType * kMaxArrayCollapse < 256,
"Unable to encode jsvals.");
@@ -257,13 +260,18 @@ Key::EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
for (uint32_t index = 0; index < length; index++) {
JS::Rooted<JS::Value> val(aCx);
- if (!JS_GetElement(aCx, obj, index, &val)) {
+ bool ok = aCallGetters ? JS_GetElement(aCx, obj, index, &val)
+ : JS_GetOwnElement(aCx, obj, index, &val);
+ if (!ok) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
- nsresult rv = EncodeJSValInternal(aCx, val, aTypeOffset,
- aRecursionDepth + 1);
+ nsresult rv = EncodeJSValInternal(aCx,
+ val,
+ aTypeOffset,
+ aRecursionDepth + 1,
+ aCallGetters);
if (NS_FAILED(rv)) {
return rv;
}
@@ -406,9 +414,10 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
nsresult
Key::EncodeJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal,
- uint8_t aTypeOffset)
+ uint8_t aTypeOffset,
+ bool aCallGetters)
{
- return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
+ return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0, aCallGetters);
}
void
@@ -741,7 +750,8 @@ Key::SetFromValueArray(mozIStorageValueArray* aValues,
nsresult
Key::SetFromJSVal(JSContext* aCx,
- JS::Handle<JS::Value> aVal)
+ JS::Handle<JS::Value> aVal,
+ bool aCallGetters)
{
mBuffer.Truncate();
@@ -750,7 +760,7 @@ Key::SetFromJSVal(JSContext* aCx,
return NS_OK;
}
- nsresult rv = EncodeJSVal(aCx, aVal, 0);
+ nsresult rv = EncodeJSVal(aCx, aVal, 0, aCallGetters);
if (NS_FAILED(rv)) {
Unset();
return rv;
@@ -793,9 +803,15 @@ Key::ToJSVal(JSContext* aCx,
}
nsresult
-Key::AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal)
+Key::AppendItem(JSContext* aCx,
+ bool aFirstOfArray,
+ JS::Handle<JS::Value> aVal,
+ bool aCallGetters)
{
- nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
+ nsresult rv = EncodeJSVal(aCx,
+ aVal,
+ aFirstOfArray ? eMaxType : 0,
+ aCallGetters);
if (NS_FAILED(rv)) {
Unset();
return rv;
diff --git a/dom/indexedDB/Key.h b/dom/indexedDB/Key.h
index 9d70ce6ad..a4fb65b48 100644
--- a/dom/indexedDB/Key.h
+++ b/dom/indexedDB/Key.h
@@ -203,7 +203,7 @@ public:
}
nsresult
- SetFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal);
+ SetFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal, bool aCallGetters);
nsresult
ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) const;
@@ -212,7 +212,10 @@ public:
ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aVal) const;
nsresult
- AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal);
+ AppendItem(JSContext* aCx,
+ bool aFirstOfArray,
+ JS::Handle<JS::Value> aVal,
+ bool aCallGetters);
nsresult
ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const;
@@ -283,7 +286,10 @@ private:
// Encoding functions. These append the encoded value to the end of mBuffer
nsresult
- EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal, uint8_t aTypeOffset);
+ EncodeJSVal(JSContext* aCx,
+ JS::Handle<JS::Value> aVal,
+ uint8_t aTypeOffset,
+ bool aCallGetters);
void
EncodeString(const nsAString& aString, uint8_t aTypeOffset);
@@ -331,7 +337,8 @@ private:
EncodeJSValInternal(JSContext* aCx,
JS::Handle<JS::Value> aVal,
uint8_t aTypeOffset,
- uint16_t aRecursionDepth);
+ uint16_t aRecursionDepth,
+ bool aCallGetters);
static nsresult
DecodeJSValInternal(const unsigned char*& aPos,
diff --git a/dom/indexedDB/KeyPath.cpp b/dom/indexedDB/KeyPath.cpp
index dc8d10668..0221c9450 100644
--- a/dom/indexedDB/KeyPath.cpp
+++ b/dom/indexedDB/KeyPath.cpp
@@ -14,6 +14,7 @@
#include "xpcpublic.h"
#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/IDBObjectStoreBinding.h"
namespace mozilla {
@@ -100,7 +101,6 @@ GetJSValFromKeyPathString(JSContext* aCx,
const char16_t* keyPathChars = token.BeginReading();
const size_t keyPathLen = token.Length();
- bool hasProp;
if (!targetObject) {
// We're still walking the chain of existing objects
// http://w3c.github.io/IndexedDB/#dfn-evaluate-a-key-path-on-a-value
@@ -116,16 +116,77 @@ GetJSValFromKeyPathString(JSContext* aCx,
}
obj = &currentVal.toObject();
- bool ok = JS_HasUCProperty(aCx, obj, keyPathChars, keyPathLen,
- &hasProp);
+ // We call JS_GetOwnUCPropertyDescriptor on purpose (as opposed to
+ // JS_GetUCPropertyDescriptor) to avoid searching the prototype chain.
+ JS::Rooted<JS::PropertyDescriptor> desc(aCx);
+ bool ok = JS_GetOwnUCPropertyDescriptor(aCx, obj, keyPathChars,
+ keyPathLen, &desc);
IDB_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
- if (hasProp) {
- // Get if the property exists...
- JS::Rooted<JS::Value> intermediate(aCx);
- bool ok = JS_GetUCProperty(aCx, obj, keyPathChars, keyPathLen, &intermediate);
- IDB_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+ JS::Rooted<JS::Value> intermediate(aCx);
+ bool hasProp = false;
+
+ if (desc.object()) {
+ intermediate = desc.value();
+ hasProp = true;
+ } else {
+ // If we get here it means the object doesn't have the property or the
+ // property is available throuch a getter. We don't want to call any
+ // getters to avoid potential re-entrancy.
+ // The blob object is special since its properties are available
+ // only through getters but we still want to support them for key
+ // extraction. So they need to be handled manually.
+ Blob* blob;
+ if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, &obj, blob))) {
+ if (token.EqualsLiteral("size")) {
+ ErrorResult rv;
+ uint64_t size = blob->GetSize(rv);
+ MOZ_ALWAYS_TRUE(!rv.Failed());
+
+ intermediate = JS_NumberValue(size);
+ hasProp = true;
+ } else if (token.EqualsLiteral("type")) {
+ nsString type;
+ blob->GetType(type);
+
+ JSString* string =
+ JS_NewUCStringCopyN(aCx, type.get(), type.Length());
+
+ intermediate = JS::StringValue(string);
+ hasProp = true;
+ } else {
+ RefPtr<File> file = blob->ToFile();
+ if (file) {
+ if (token.EqualsLiteral("name")) {
+ nsString name;
+ file->GetName(name);
+
+ JSString* string =
+ JS_NewUCStringCopyN(aCx, name.get(), name.Length());
+
+ intermediate = JS::StringValue(string);
+ hasProp = true;
+ } else if (token.EqualsLiteral("lastModified")) {
+ ErrorResult rv;
+ int64_t lastModifiedDate = file->GetLastModified(rv);
+ MOZ_ALWAYS_TRUE(!rv.Failed());
+
+ intermediate = JS_NumberValue(lastModifiedDate);
+ hasProp = true;
+ } else if (token.EqualsLiteral("lastModifiedDate")) {
+ ErrorResult rv;
+ Date lastModifiedDate = file->GetLastModifiedDate(rv);
+ MOZ_ALWAYS_TRUE(!rv.Failed());
+
+ lastModifiedDate.ToDateObject(aCx, &intermediate);
+ hasProp = true;
+ }
+ }
+ }
+ }
+ }
+ if (hasProp) {
// Treat explicitly undefined as an error.
if (intermediate.isUndefined()) {
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
@@ -311,11 +372,13 @@ KeyPath::AppendStringWithValidation(const nsAString& aString)
}
nsresult
-KeyPath::ExtractKey(JSContext* aCx, const JS::Value& aValue, Key& aKey) const
+KeyPath::ExtractKey(JSContext* aCx,
+ const JS::Value& aValue,
+ Key& aKey,
+ bool aCallGetters) const
{
uint32_t len = mStrings.Length();
JS::Rooted<JS::Value> value(aCx);
-
aKey.Unset();
for (uint32_t i = 0; i < len; ++i) {
@@ -327,7 +390,10 @@ KeyPath::ExtractKey(JSContext* aCx, const JS::Value& aValue, Key& aKey) const
return rv;
}
- if (NS_FAILED(aKey.AppendItem(aCx, IsArray() && i == 0, value))) {
+ if (NS_FAILED(aKey.AppendItem(aCx,
+ IsArray() && i == 0,
+ value,
+ aCallGetters))) {
NS_ASSERTION(aKey.IsUnset(), "Encoding error should unset");
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
}
@@ -376,9 +442,12 @@ KeyPath::ExtractKeyAsJSVal(JSContext* aCx, const JS::Value& aValue,
}
nsresult
-KeyPath::ExtractOrCreateKey(JSContext* aCx, const JS::Value& aValue,
- Key& aKey, ExtractOrCreateKeyCallback aCallback,
- void* aClosure) const
+KeyPath::ExtractOrCreateKey(JSContext* aCx,
+ const JS::Value& aValue,
+ Key& aKey,
+ ExtractOrCreateKeyCallback aCallback,
+ void* aClosure,
+ bool aCallGetters) const
{
NS_ASSERTION(IsString(), "This doesn't make sense!");
@@ -394,7 +463,7 @@ KeyPath::ExtractOrCreateKey(JSContext* aCx, const JS::Value& aValue,
return rv;
}
- if (NS_FAILED(aKey.AppendItem(aCx, false, value))) {
+ if (NS_FAILED(aKey.AppendItem(aCx, false, value, aCallGetters))) {
NS_ASSERTION(aKey.IsUnset(), "Should be unset");
return value.isUndefined() ? NS_OK : NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
}
diff --git a/dom/indexedDB/KeyPath.h b/dom/indexedDB/KeyPath.h
index c133cdc4a..e6e5f57d4 100644
--- a/dom/indexedDB/KeyPath.h
+++ b/dom/indexedDB/KeyPath.h
@@ -72,7 +72,10 @@ public:
Parse(const Nullable<OwningStringOrStringSequence>& aValue, KeyPath* aKeyPath);
nsresult
- ExtractKey(JSContext* aCx, const JS::Value& aValue, Key& aKey) const;
+ ExtractKey(JSContext* aCx,
+ const JS::Value& aValue,
+ Key& aKey,
+ bool aCallGetters) const;
nsresult
ExtractKeyAsJSVal(JSContext* aCx, const JS::Value& aValue,
@@ -82,9 +85,12 @@ public:
(*ExtractOrCreateKeyCallback)(JSContext* aCx, void* aClosure);
nsresult
- ExtractOrCreateKey(JSContext* aCx, const JS::Value& aValue, Key& aKey,
+ ExtractOrCreateKey(JSContext* aCx,
+ const JS::Value& aValue,
+ Key& aKey,
ExtractOrCreateKeyCallback aCallback,
- void* aClosure) const;
+ void* aClosure,
+ bool aCallGetters) const;
inline bool IsValid() const {
return mType != NONEXISTENT;
diff --git a/dom/indexedDB/test/helpers.js b/dom/indexedDB/test/helpers.js
index e6e27f3f3..ffe66ebcd 100644
--- a/dom/indexedDB/test/helpers.js
+++ b/dom/indexedDB/test/helpers.js
@@ -217,10 +217,6 @@ if (!window.runTest) {
function finishTest()
{
- SpecialPowers.notifyObserversInParentProcess(null,
- "disk-space-watcher",
- "free");
-
SimpleTest.executeSoon(function() {
testGenerator.close();
testHarnessGenerator.close();
diff --git a/dom/indexedDB/test/mochitest.ini b/dom/indexedDB/test/mochitest.ini
index 4ab55a9dc..ca65ea8b6 100644
--- a/dom/indexedDB/test/mochitest.ini
+++ b/dom/indexedDB/test/mochitest.ini
@@ -66,7 +66,6 @@ support-files =
unit/test_locale_aware_indexes.js
unit/test_locale_aware_index_getAll.js
unit/test_locale_aware_index_getAllObjects.js
- unit/test_lowDiskSpace.js
unit/test_maximal_serialized_object_size.js
unit/test_multientry.js
unit/test_names_sorted.js
@@ -214,7 +213,6 @@ skip-if = true
[test_key_requirements.html]
[test_keys.html]
[test_leaving_page.html]
-[test_lowDiskSpace.html]
[test_maximal_serialized_object_size.html]
[test_message_manager_ipc.html]
# This test is only supposed to run in the main process.
diff --git a/dom/indexedDB/test/test_globalObjects_other.xul b/dom/indexedDB/test/test_globalObjects_other.xul
index eb180a9b4..b527d66bd 100644
--- a/dom/indexedDB/test/test_globalObjects_other.xul
+++ b/dom/indexedDB/test/test_globalObjects_other.xul
@@ -31,14 +31,8 @@
Cu.import("resource://gre/modules/Services.jsm");
for (var stage of [ "install", "startup", "shutdown", "uninstall" ]) {
for (var symbol of [ "IDBKeyRange", "indexedDB" ]) {
- let pref;
- try {
- pref = Services.prefs.getBoolPref("indexeddbtest.bootstrap." + stage +
- "." + symbol);
- }
- catch(ex) {
- pref = false;
- }
+ let pref = Services.prefs.getBoolPref("indexeddbtest.bootstrap." + stage +
+ "." + symbol, false);
ok(pref, "Symbol '" + symbol + "' present during '" + stage + "'");
}
}
diff --git a/dom/indexedDB/test/test_lowDiskSpace.html b/dom/indexedDB/test/test_lowDiskSpace.html
deleted file mode 100644
index cffd46549..000000000
--- a/dom/indexedDB/test/test_lowDiskSpace.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-<head>
- <title>Indexed Database Low Disk Space Test</title>
-
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-
- <script type="text/javascript;version=1.7" src="unit/test_lowDiskSpace.js"></script>
- <script type="text/javascript;version=1.7" src="helpers.js"></script>
-
-</head>
-
-<body onload="runTest();"></body>
-
-</html>
diff --git a/dom/indexedDB/test/unit/test_lowDiskSpace.js b/dom/indexedDB/test/unit/test_lowDiskSpace.js
deleted file mode 100644
index eaea5797d..000000000
--- a/dom/indexedDB/test/unit/test_lowDiskSpace.js
+++ /dev/null
@@ -1,754 +0,0 @@
-/**
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-"use strict";
-
-var disableWorkerTest = "This test uses SpecialPowers";
-
-var self = this;
-
-var testGenerator = testSteps();
-
-function testSteps()
-{
- const dbName = self.window ? window.location.pathname : "test_lowDiskSpace";
- const dbVersion = 1;
-
- const objectStoreName = "foo";
- const objectStoreOptions = { keyPath: "foo" };
-
- const indexName = "bar";
- const indexOptions = { unique: true };
-
- const dbData = [
- { foo: 0, bar: 0 },
- { foo: 1, bar: 10 },
- { foo: 2, bar: 20 },
- { foo: 3, bar: 30 },
- { foo: 4, bar: 40 },
- { foo: 5, bar: 50 },
- { foo: 6, bar: 60 },
- { foo: 7, bar: 70 },
- { foo: 8, bar: 80 },
- { foo: 9, bar: 90 }
- ];
-
- let lowDiskMode = false;
- function setLowDiskMode(val) {
- let data = val ? "full" : "free";
-
- if (val == lowDiskMode) {
- info("Low disk mode is: " + data);
- }
- else {
- info("Changing low disk mode to: " + data);
- SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher",
- data);
- lowDiskMode = val;
- }
- }
-
- { // Make sure opening works from the beginning.
- info("Test 1");
-
- setLowDiskMode(false);
-
- let request = indexedDB.open(dbName, dbVersion);
- request.onerror = errorHandler;
- request.onsuccess = grabEventAndContinueHandler;
- let event = yield undefined;
-
- is(event.type, "success", "Opened database without setting low disk mode");
-
- let db = event.target.result;
- db.close();
- }
-
- { // Make sure delete works in low disk mode.
- info("Test 2");
-
- setLowDiskMode(true);
-
- let request = indexedDB.deleteDatabase(dbName);
- request.onerror = errorHandler;
- request.onsuccess = grabEventAndContinueHandler;
- let event = yield undefined;
-
- is(event.type, "success", "Deleted database after setting low disk mode");
- }
-
- { // Make sure creating a db in low disk mode fails.
- info("Test 3");
-
- setLowDiskMode(true);
-
- let request = indexedDB.open(dbName, dbVersion);
- request.onerror = expectedErrorHandler("QuotaExceededError");
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = unexpectedSuccessHandler;
- let event = yield undefined;
-
- is(event.type, "error", "Didn't create new database in low disk mode");
- }
-
- { // Make sure opening an already-existing db in low disk mode succeeds.
- info("Test 4");
-
- setLowDiskMode(false);
-
- let request = indexedDB.open(dbName, dbVersion);
- request.onerror = errorHandler;
- request.onupgradeneeded = grabEventAndContinueHandler;
- request.onsuccess = unexpectedSuccessHandler;
- let event = yield undefined;
-
- is(event.type, "upgradeneeded", "Upgrading database");
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "success", "Created database");
- ok(event.target.result === db, "Got the same database");
-
- db.close();
-
- setLowDiskMode(true);
-
- request = indexedDB.open(dbName);
- request.onerror = errorHandler;
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "success", "Opened existing database in low disk mode");
-
- db = event.target.result;
- db.close();
- }
-
- { // Make sure upgrading an already-existing db in low disk mode succeeds.
- info("Test 5");
-
- setLowDiskMode(true);
-
- let request = indexedDB.open(dbName, dbVersion + 1);
- request.onerror = errorHandler;
- request.onupgradeneeded = grabEventAndContinueHandler;
- request.onsuccess = unexpectedSuccessHandler;
-
- let event = yield undefined;
-
- is(event.type, "upgradeneeded", "Upgrading database");
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "success", "Created database");
- ok(event.target.result === db, "Got the same database");
-
- db.close();
- }
-
- { // Make sure creating objectStores in low disk mode fails.
- info("Test 6");
-
- setLowDiskMode(true);
-
- let request = indexedDB.open(dbName, dbVersion + 2);
- request.onerror = errorHandler;
- request.onupgradeneeded = grabEventAndContinueHandler;
- request.onsuccess = unexpectedSuccessHandler;
-
- let event = yield undefined;
-
- is(event.type, "upgradeneeded", "Upgrading database");
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- let txn = event.target.transaction;
- txn.onerror = expectedErrorHandler("AbortError");
- txn.onabort = grabEventAndContinueHandler;
-
- let objectStore = db.createObjectStore(objectStoreName, objectStoreOptions);
-
- request.onupgradeneeded = unexpectedSuccessHandler;
- event = yield undefined;
-
- is(event.type, "abort", "Got correct event type");
- is(event.target.error.name, "QuotaExceededError", "Got correct error type");
-
- request.onerror = expectedErrorHandler("AbortError");
- event = yield undefined;
- }
-
- { // Make sure creating indexes in low disk mode fails.
- info("Test 7");
-
- setLowDiskMode(false);
-
- let request = indexedDB.open(dbName, dbVersion + 2);
- request.onerror = errorHandler;
- request.onupgradeneeded = grabEventAndContinueHandler;
- request.onsuccess = unexpectedSuccessHandler;
-
- let event = yield undefined;
-
- is(event.type, "upgradeneeded", "Upgrading database");
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- let objectStore = db.createObjectStore(objectStoreName, objectStoreOptions);
-
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "success", "Upgraded database");
- ok(event.target.result === db, "Got the same database");
-
- db.close();
-
- setLowDiskMode(true);
-
- request = indexedDB.open(dbName, dbVersion + 3);
- request.onerror = errorHandler;
- request.onupgradeneeded = grabEventAndContinueHandler;
- request.onsuccess = unexpectedSuccessHandler;
- event = yield undefined;
-
- is(event.type, "upgradeneeded", "Upgrading database");
-
- db = event.target.result;
- db.onerror = errorHandler;
- let txn = event.target.transaction;
- txn.onerror = expectedErrorHandler("AbortError");
- txn.onabort = grabEventAndContinueHandler;
-
- objectStore = event.target.transaction.objectStore(objectStoreName);
- let index = objectStore.createIndex(indexName, indexName, indexOptions);
-
- request.onupgradeneeded = unexpectedSuccessHandler;
- event = yield undefined;
-
- is(event.type, "abort", "Got correct event type");
- is(event.target.error.name, "QuotaExceededError", "Got correct error type");
-
- request.onerror = expectedErrorHandler("AbortError");
- event = yield undefined;
- }
-
- { // Make sure deleting indexes in low disk mode succeeds.
- info("Test 8");
-
- setLowDiskMode(false);
-
- let request = indexedDB.open(dbName, dbVersion + 3);
- request.onerror = errorHandler;
- request.onupgradeneeded = grabEventAndContinueHandler;
- request.onsuccess = unexpectedSuccessHandler;
-
- let event = yield undefined;
-
- is(event.type, "upgradeneeded", "Upgrading database");
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- let objectStore = event.target.transaction.objectStore(objectStoreName);
- let index = objectStore.createIndex(indexName, indexName, indexOptions);
-
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "success", "Upgraded database");
- ok(event.target.result === db, "Got the same database");
-
- db.close();
-
- setLowDiskMode(true);
-
- request = indexedDB.open(dbName, dbVersion + 4);
- request.onerror = errorHandler;
- request.onupgradeneeded = grabEventAndContinueHandler;
- request.onsuccess = unexpectedSuccessHandler;
- event = yield undefined;
-
- is(event.type, "upgradeneeded", "Upgrading database");
-
- db = event.target.result;
- db.onerror = errorHandler;
-
- objectStore = event.target.transaction.objectStore(objectStoreName);
- objectStore.deleteIndex(indexName);
-
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "success", "Upgraded database");
- ok(event.target.result === db, "Got the same database");
-
- db.close();
- }
-
- { // Make sure deleting objectStores in low disk mode succeeds.
- info("Test 9");
-
- setLowDiskMode(true);
-
- let request = indexedDB.open(dbName, dbVersion + 5);
- request.onerror = errorHandler;
- request.onupgradeneeded = grabEventAndContinueHandler;
- request.onsuccess = unexpectedSuccessHandler;
-
- let event = yield undefined;
-
- is(event.type, "upgradeneeded", "Upgrading database");
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- db.deleteObjectStore(objectStoreName);
-
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "success", "Upgraded database");
- ok(event.target.result === db, "Got the same database");
-
- db.close();
-
- // Reset everything.
- indexedDB.deleteDatabase(dbName);
- }
-
-
- { // Add data that the rest of the tests will use.
- info("Adding test data");
-
- setLowDiskMode(false);
-
- let request = indexedDB.open(dbName, dbVersion);
- request.onerror = errorHandler;
- request.onupgradeneeded = grabEventAndContinueHandler;
- request.onsuccess = unexpectedSuccessHandler;
- let event = yield undefined;
-
- is(event.type, "upgradeneeded", "Upgrading database");
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- let objectStore = db.createObjectStore(objectStoreName, objectStoreOptions);
- let index = objectStore.createIndex(indexName, indexName, indexOptions);
-
- for (let data of dbData) {
- objectStore.add(data);
- }
-
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "success", "Upgraded database");
- ok(event.target.result === db, "Got the same database");
-
- db.close();
- }
-
- { // Make sure read operations in readonly transactions succeed in low disk
- // mode.
- info("Test 10");
-
- setLowDiskMode(true);
-
- let request = indexedDB.open(dbName, dbVersion);
- request.onerror = errorHandler;
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- let event = yield undefined;
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- let transaction = db.transaction(objectStoreName);
- let objectStore = transaction.objectStore(objectStoreName);
- let index = objectStore.index(indexName);
-
- let data = dbData[0];
-
- let requestCounter = new RequestCounter();
-
- objectStore.get(data.foo).onsuccess = requestCounter.handler();
- objectStore.mozGetAll().onsuccess = requestCounter.handler();
- objectStore.count().onsuccess = requestCounter.handler();
- index.get(data.bar).onsuccess = requestCounter.handler();
- index.mozGetAll().onsuccess = requestCounter.handler();
- index.getKey(data.bar).onsuccess = requestCounter.handler();
- index.mozGetAllKeys().onsuccess = requestCounter.handler();
- index.count().onsuccess = requestCounter.handler();
-
- let objectStoreDataCount = 0;
-
- request = objectStore.openCursor();
- request.onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- objectStoreDataCount++;
- objectStoreDataCount % 2 ? cursor.continue() : cursor.advance(1);
- }
- else {
- is(objectStoreDataCount, dbData.length, "Saw all data");
- requestCounter.decr();
- }
- };
- requestCounter.incr();
-
- let indexDataCount = 0;
-
- request = index.openCursor();
- request.onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- indexDataCount++;
- indexDataCount % 2 ? cursor.continue() : cursor.advance(1);
- }
- else {
- is(indexDataCount, dbData.length, "Saw all data");
- requestCounter.decr();
- }
- };
- requestCounter.incr();
-
- let indexKeyDataCount = 0;
-
- request = index.openCursor();
- request.onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- indexKeyDataCount++;
- indexKeyDataCount % 2 ? cursor.continue() : cursor.advance(1);
- }
- else {
- is(indexKeyDataCount, dbData.length, "Saw all data");
- requestCounter.decr();
- }
- };
- requestCounter.incr();
-
- // Wait for all requests.
- yield undefined;
-
- transaction.oncomplete = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "complete", "Transaction succeeded");
-
- db.close();
- }
-
- { // Make sure read operations in readwrite transactions succeed in low disk
- // mode.
- info("Test 11");
-
- setLowDiskMode(true);
-
- let request = indexedDB.open(dbName, dbVersion);
- request.onerror = errorHandler;
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- let event = yield undefined;
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- let transaction = db.transaction(objectStoreName, "readwrite");
- let objectStore = transaction.objectStore(objectStoreName);
- let index = objectStore.index(indexName);
-
- let data = dbData[0];
-
- let requestCounter = new RequestCounter();
-
- objectStore.get(data.foo).onsuccess = requestCounter.handler();
- objectStore.mozGetAll().onsuccess = requestCounter.handler();
- objectStore.count().onsuccess = requestCounter.handler();
- index.get(data.bar).onsuccess = requestCounter.handler();
- index.mozGetAll().onsuccess = requestCounter.handler();
- index.getKey(data.bar).onsuccess = requestCounter.handler();
- index.mozGetAllKeys().onsuccess = requestCounter.handler();
- index.count().onsuccess = requestCounter.handler();
-
- let objectStoreDataCount = 0;
-
- request = objectStore.openCursor();
- request.onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- objectStoreDataCount++;
- objectStoreDataCount % 2 ? cursor.continue() : cursor.advance(1);
- }
- else {
- is(objectStoreDataCount, dbData.length, "Saw all data");
- requestCounter.decr();
- }
- };
- requestCounter.incr();
-
- let indexDataCount = 0;
-
- request = index.openCursor();
- request.onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- indexDataCount++;
- indexDataCount % 2 ? cursor.continue() : cursor.advance(1);
- }
- else {
- is(indexDataCount, dbData.length, "Saw all data");
- requestCounter.decr();
- }
- };
- requestCounter.incr();
-
- let indexKeyDataCount = 0;
-
- request = index.openCursor();
- request.onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- indexKeyDataCount++;
- indexKeyDataCount % 2 ? cursor.continue() : cursor.advance(1);
- }
- else {
- is(indexKeyDataCount, dbData.length, "Saw all data");
- requestCounter.decr();
- }
- };
- requestCounter.incr();
-
- // Wait for all requests.
- yield undefined;
-
- transaction.oncomplete = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "complete", "Transaction succeeded");
-
- db.close();
- }
-
- { // Make sure write operations in readwrite transactions fail in low disk
- // mode.
- info("Test 12");
-
- setLowDiskMode(true);
-
- let request = indexedDB.open(dbName, dbVersion);
- request.onerror = errorHandler;
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- let event = yield undefined;
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- let transaction = db.transaction(objectStoreName, "readwrite");
- let objectStore = transaction.objectStore(objectStoreName);
- let index = objectStore.index(indexName);
-
- let data = dbData[0];
- let newData = { foo: 999, bar: 999 };
-
- let requestCounter = new RequestCounter();
-
- objectStore.add(newData).onerror = requestCounter.errorHandler();
- objectStore.put(newData).onerror = requestCounter.errorHandler();
-
- objectStore.get(data.foo).onsuccess = requestCounter.handler();
- objectStore.mozGetAll().onsuccess = requestCounter.handler();
- objectStore.count().onsuccess = requestCounter.handler();
- index.get(data.bar).onsuccess = requestCounter.handler();
- index.mozGetAll().onsuccess = requestCounter.handler();
- index.getKey(data.bar).onsuccess = requestCounter.handler();
- index.mozGetAllKeys().onsuccess = requestCounter.handler();
- index.count().onsuccess = requestCounter.handler();
-
- let objectStoreDataCount = 0;
-
- request = objectStore.openCursor();
- request.onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- objectStoreDataCount++;
- cursor.update(cursor.value).onerror = requestCounter.errorHandler();
- objectStoreDataCount % 2 ? cursor.continue() : cursor.advance(1);
- }
- else {
- is(objectStoreDataCount, dbData.length, "Saw all data");
- requestCounter.decr();
- }
- };
- requestCounter.incr();
-
- let indexDataCount = 0;
-
- request = index.openCursor();
- request.onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- indexDataCount++;
- cursor.update(cursor.value).onerror = requestCounter.errorHandler();
- indexDataCount % 2 ? cursor.continue() : cursor.advance(1);
- }
- else {
- is(indexDataCount, dbData.length, "Saw all data");
- requestCounter.decr();
- }
- };
- requestCounter.incr();
-
- let indexKeyDataCount = 0;
-
- request = index.openCursor();
- request.onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- indexKeyDataCount++;
- cursor.update(cursor.value).onerror = requestCounter.errorHandler();
- indexKeyDataCount % 2 ? cursor.continue() : cursor.advance(1);
- }
- else {
- is(indexKeyDataCount, dbData.length, "Saw all data");
- requestCounter.decr();
- }
- };
- requestCounter.incr();
-
- // Wait for all requests.
- yield undefined;
-
- transaction.oncomplete = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "complete", "Transaction succeeded");
-
- db.close();
- }
-
- { // Make sure deleting operations in readwrite transactions succeed in low
- // disk mode.
- info("Test 13");
-
- setLowDiskMode(true);
-
- let request = indexedDB.open(dbName, dbVersion);
- request.onerror = errorHandler;
- request.onupgradeneeded = unexpectedSuccessHandler;
- request.onsuccess = grabEventAndContinueHandler;
- let event = yield undefined;
-
- let db = event.target.result;
- db.onerror = errorHandler;
-
- let transaction = db.transaction(objectStoreName, "readwrite");
- let objectStore = transaction.objectStore(objectStoreName);
- let index = objectStore.index(indexName);
-
- let dataIndex = 0;
- let data = dbData[dataIndex++];
-
- let requestCounter = new RequestCounter();
-
- objectStore.delete(data.foo).onsuccess = requestCounter.handler();
-
- objectStore.openCursor().onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- cursor.delete().onsuccess = requestCounter.handler();
- }
- requestCounter.decr();
- };
- requestCounter.incr();
-
- index.openCursor(null, "prev").onsuccess = function(event) {
- let cursor = event.target.result;
- if (cursor) {
- cursor.delete().onsuccess = requestCounter.handler();
- }
- requestCounter.decr();
- };
- requestCounter.incr();
-
- yield undefined;
-
- objectStore.count().onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.target.result, dbData.length - 3, "Actually deleted something");
-
- objectStore.clear();
- objectStore.count().onsuccess = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.target.result, 0, "Actually cleared");
-
- transaction.oncomplete = grabEventAndContinueHandler;
- event = yield undefined;
-
- is(event.type, "complete", "Transaction succeeded");
-
- db.close();
- }
-
- finishTest();
- yield undefined;
-}
-
-function RequestCounter(expectedType) {
- this._counter = 0;
-}
-RequestCounter.prototype = {
- incr: function() {
- this._counter++;
- },
-
- decr: function() {
- if (!--this._counter) {
- continueToNextStepSync();
- }
- },
-
- handler: function(type, preventDefault) {
- this.incr();
- return function(event) {
- is(event.type, type || "success", "Correct type");
- this.decr();
- }.bind(this);
- },
-
- errorHandler: function(eventType, errorName) {
- this.incr();
- return function(event) {
- is(event.type, eventType || "error", "Correct type");
- is(event.target.error.name, errorName || "QuotaExceededError",
- "Correct error name");
- event.preventDefault();
- event.stopPropagation();
- this.decr();
- }.bind(this);
- }
-};
diff --git a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
index def791f52..fe69b1f7b 100644
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
+++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
@@ -66,9 +66,6 @@ function finishTest()
resetWasm();
resetExperimental();
resetTesting();
-
- SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher",
- "free");
}
SpecialPowers.removeFiles();
diff --git a/dom/indexedDB/test/unit/xpcshell-parent-process.ini b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
index 04df5f552..2def60c34 100644
--- a/dom/indexedDB/test/unit/xpcshell-parent-process.ini
+++ b/dom/indexedDB/test/unit/xpcshell-parent-process.ini
@@ -46,7 +46,6 @@ skip-if = toolkit == 'android'
[test_invalidate.js]
# disabled for the moment.
skip-if = true
-[test_lowDiskSpace.js]
[test_maximal_serialized_object_size.js]
[test_metadata2Restore.js]
[test_metadataRestore.js]