diff options
Diffstat (limited to 'dom/indexedDB')
46 files changed, 657 insertions, 333 deletions
diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp index bc0baf1157..47360094ca 100644 --- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -291,7 +291,8 @@ static_assert(kSQLiteGrowthIncrement >= 0 && "Must be 0 (disabled) or a positive multiple of the page size!"); // The maximum number of threads that can be used for database activity at a -// single time. +// single time. Please keep in sync with the constants in +// test_connection_idle_maintenance*.js tests const uint32_t kMaxConnectionThreadCount = 20; static_assert(kMaxConnectionThreadCount, "Must have at least one thread!"); @@ -304,7 +305,8 @@ static_assert(kMaxConnectionThreadCount >= kMaxIdleConnectionThreadCount, "Idle thread limit must be less than total thread limit!"); // The length of time that database connections will be held open after all -// transactions have completed before doing idle maintenance. +// transactions have completed before doing idle maintenance. Please keep in +// sync with the timeouts in test_connection_idle_maintenance*.js tests const uint32_t kConnectionIdleMaintenanceMS = 2 * 1000; // 2 seconds // The length of time that database connections will be held open after all @@ -1162,7 +1164,8 @@ class DatabaseConnection final : public CachingDatabaseConnection { return CheckpointInternal(CheckpointMode::Full); } - void DoIdleProcessing(bool aNeedsCheckpoint); + void DoIdleProcessing(bool aNeedsCheckpoint, + const Atomic<bool>& aInterrupted); void Close(); @@ -1189,7 +1192,8 @@ class DatabaseConnection final : public CachingDatabaseConnection { */ Result<bool, nsresult> ReclaimFreePagesWhileIdle( CachedStatement& aFreelistStatement, CachedStatement& aRollbackStatement, - uint32_t aFreelistCount, bool aNeedsCheckpoint); + uint32_t aFreelistCount, bool aNeedsCheckpoint, + const Atomic<bool>& aInterrupted); Result<int64_t, nsresult> GetFileSize(const nsAString& aPath); }; @@ -1362,6 +1366,34 @@ class ConnectionPool final { } }; + struct PerformingIdleMaintenanceDatabaseInfo { + const NotNull<DatabaseInfo*> mDatabaseInfo; + RefPtr<IdleConnectionRunnable> mIdleConnectionRunnable; + + PerformingIdleMaintenanceDatabaseInfo( + DatabaseInfo& aDatabaseInfo, + RefPtr<IdleConnectionRunnable> aIdleConnectionRunnable); + + PerformingIdleMaintenanceDatabaseInfo( + const PerformingIdleMaintenanceDatabaseInfo& aOther) = delete; + PerformingIdleMaintenanceDatabaseInfo( + PerformingIdleMaintenanceDatabaseInfo&& aOther) noexcept + : mDatabaseInfo{aOther.mDatabaseInfo}, + mIdleConnectionRunnable{std::move(aOther.mIdleConnectionRunnable)} { + MOZ_COUNT_CTOR(ConnectionPool::PerformingIdleMaintenanceDatabaseInfo); + } + PerformingIdleMaintenanceDatabaseInfo& operator=( + const PerformingIdleMaintenanceDatabaseInfo& aOther) = delete; + PerformingIdleMaintenanceDatabaseInfo& operator=( + PerformingIdleMaintenanceDatabaseInfo&& aOther) = delete; + + ~PerformingIdleMaintenanceDatabaseInfo(); + + bool operator==(const DatabaseInfo* aDatabaseInfo) const { + return mDatabaseInfo == aDatabaseInfo; + } + }; + class ThreadInfo { public: ThreadInfo(); @@ -1456,7 +1488,8 @@ class ConnectionPool final { nsCOMPtr<nsIThreadPool> mIOTarget; nsTArray<IdleThreadInfo> mIdleThreads; nsTArray<IdleDatabaseInfo> mIdleDatabases; - nsTArray<NotNull<DatabaseInfo*>> mDatabasesPerformingIdleMaintenance; + nsTArray<PerformingIdleMaintenanceDatabaseInfo> + mDatabasesPerformingIdleMaintenance; nsCOMPtr<nsITimer> mIdleTimer; TimeStamp mTargetIdleTime; @@ -1559,6 +1592,7 @@ class ConnectionPool::ConnectionRunnable : public Runnable { class ConnectionPool::IdleConnectionRunnable final : public ConnectionRunnable { const bool mNeedsCheckpoint; + Atomic<bool> mInterrupted; public: IdleConnectionRunnable(DatabaseInfo& aDatabaseInfo, bool aNeedsCheckpoint) @@ -1567,6 +1601,8 @@ class ConnectionPool::IdleConnectionRunnable final : public ConnectionRunnable { NS_INLINE_DECL_REFCOUNTING_INHERITED(IdleConnectionRunnable, ConnectionRunnable) + void Interrupt() { mInterrupted = true; } + private: ~IdleConnectionRunnable() override = default; @@ -2061,6 +2097,7 @@ class TransactionDatabaseOperationBase : public DatabaseOperationBase { class Factory final : public PBackgroundIDBFactoryParent, public AtomicSafeRefCounted<Factory> { + nsCString mSystemLocale; RefPtr<DatabaseLoggingInfo> mLoggingInfo; #ifdef DEBUG @@ -2072,7 +2109,7 @@ class Factory final : public PBackgroundIDBFactoryParent, public: [[nodiscard]] static SafeRefPtr<Factory> Create( - const LoggingInfo& aLoggingInfo); + const LoggingInfo& aLoggingInfo, const nsACString& aSystemLocale); DatabaseLoggingInfo* GetLoggingInfo() const { AssertIsOnBackgroundThread(); @@ -2081,11 +2118,14 @@ class Factory final : public PBackgroundIDBFactoryParent, return mLoggingInfo; } + const nsCString& GetSystemLocale() const { return mSystemLocale; } + MOZ_DECLARE_REFCOUNTED_TYPENAME(mozilla::dom::indexedDB::Factory) MOZ_INLINE_DECL_SAFEREFCOUNTING_INHERITED(Factory, AtomicSafeRefCounted) // Only constructed in Create(). - explicit Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo); + Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo, + const nsACString& aSystemLocale); // IPDL methods are only called by IPDL. void ActorDestroy(ActorDestroyReason aWhy) override; @@ -2961,17 +3001,11 @@ class FactoryOp protected: enum class State { - // Just created on the PBackground thread, dispatched to the main thread. - // Next step is either SendingResults if permission is denied, - // PermissionChallenge if the permission is unknown, or FinishOpen - // if permission is granted. + // Just created on the PBackground thread, dispatched to the current thread. + // Next step is either SendingResults if opening initialization failed, or + // DirectoryOpenPending if the opening initialization succeeded. Initial, - // Ensuring quota manager is created and opening directory on the - // PBackground thread. Next step is either SendingResults if quota manager - // is not available or DirectoryOpenPending if quota manager is available. - FinishOpen, - // Waiting for directory open allowed on the PBackground thread. The next // step is either SendingResults if directory lock failed to acquire, or // DatabaseOpenPending if directory lock is acquired. @@ -3129,10 +3163,6 @@ class FactoryOp virtual void SendBlockedNotification() = 0; private: - mozilla::Result<PermissionValue, nsresult> CheckPermission(); - - nsresult FinishOpen(); - // Test whether this FactoryOp needs to wait for the given op. bool MustWaitFor(const FactoryOp& aExistingOp); }; @@ -6517,7 +6547,7 @@ already_AddRefed<nsIThreadPool> MakeConnectionIOTarget() { ******************************************************************************/ already_AddRefed<PBackgroundIDBFactoryParent> AllocPBackgroundIDBFactoryParent( - const LoggingInfo& aLoggingInfo) { + const LoggingInfo& aLoggingInfo, const nsACString& aSystemLocale) { AssertIsOnBackgroundThread(); if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread())) { @@ -6531,15 +6561,15 @@ already_AddRefed<PBackgroundIDBFactoryParent> AllocPBackgroundIDBFactoryParent( return nullptr; } - SafeRefPtr<Factory> actor = Factory::Create(aLoggingInfo); + SafeRefPtr<Factory> actor = Factory::Create(aLoggingInfo, aSystemLocale); MOZ_ASSERT(actor); return actor.forget(); } bool RecvPBackgroundIDBFactoryConstructor( - PBackgroundIDBFactoryParent* aActor, - const LoggingInfo& /* aLoggingInfo */) { + PBackgroundIDBFactoryParent* aActor, const LoggingInfo& /* aLoggingInfo */, + const nsACString& /* aSystemLocale */) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread()); @@ -6862,7 +6892,8 @@ nsresult DatabaseConnection::CheckpointInternal(CheckpointMode aMode) { return NS_OK; } -void DatabaseConnection::DoIdleProcessing(bool aNeedsCheckpoint) { +void DatabaseConnection::DoIdleProcessing(bool aNeedsCheckpoint, + const Atomic<bool>& aInterrupted) { AssertIsOnConnectionThread(); MOZ_ASSERT(mInReadTransaction); MOZ_ASSERT(!mInWriteTransaction); @@ -6887,22 +6918,23 @@ void DatabaseConnection::DoIdleProcessing(bool aNeedsCheckpoint) { mInReadTransaction = false; } - const bool freedSomePages = freelistCount && [this, &freelistStmt, - &rollbackStmt, freelistCount, - aNeedsCheckpoint] { - // Warn in case of an error, but do not propagate it. Just indicate we - // didn't free any pages. - QM_TRY_INSPECT(const bool& res, - ReclaimFreePagesWhileIdle(freelistStmt, rollbackStmt, - freelistCount, aNeedsCheckpoint), - false); + const bool freedSomePages = + freelistCount && [this, &freelistStmt, &rollbackStmt, freelistCount, + aNeedsCheckpoint, &aInterrupted] { + // Warn in case of an error, but do not propagate it. Just indicate we + // didn't free any pages. + QM_TRY_INSPECT( + const bool& res, + ReclaimFreePagesWhileIdle(freelistStmt, rollbackStmt, freelistCount, + aNeedsCheckpoint, aInterrupted), + false); - // Make sure we didn't leave a transaction running. - MOZ_ASSERT(!mInReadTransaction); - MOZ_ASSERT(!mInWriteTransaction); + // Make sure we didn't leave a transaction running. + MOZ_ASSERT(!mInReadTransaction); + MOZ_ASSERT(!mInWriteTransaction); - return res; - }(); + return res; + }(); // Truncate the WAL if we were asked to or if we managed to free some space. if (aNeedsCheckpoint || freedSomePages) { @@ -6922,7 +6954,8 @@ void DatabaseConnection::DoIdleProcessing(bool aNeedsCheckpoint) { Result<bool, nsresult> DatabaseConnection::ReclaimFreePagesWhileIdle( CachedStatement& aFreelistStatement, CachedStatement& aRollbackStatement, - uint32_t aFreelistCount, bool aNeedsCheckpoint) { + uint32_t aFreelistCount, bool aNeedsCheckpoint, + const Atomic<bool>& aInterrupted) { AssertIsOnConnectionThread(); MOZ_ASSERT(aFreelistStatement); MOZ_ASSERT(aRollbackStatement); @@ -6932,11 +6965,14 @@ Result<bool, nsresult> DatabaseConnection::ReclaimFreePagesWhileIdle( AUTO_PROFILER_LABEL("DatabaseConnection::ReclaimFreePagesWhileIdle", DOM); - // Make sure we don't keep working if anything else needs this thread. - nsIThread* currentThread = NS_GetCurrentThread(); - MOZ_ASSERT(currentThread); + uint32_t pauseOnConnectionThreadMs = StaticPrefs:: + dom_indexedDB_connectionIdleMaintenance_pauseOnConnectionThreadMs(); + if (pauseOnConnectionThreadMs > 0) { + PR_Sleep(PR_MillisecondsToInterval(pauseOnConnectionThreadMs)); + } - if (NS_HasPendingEvents(currentThread)) { + // Make sure we don't keep working if anything else needs this thread. + if (aInterrupted) { return false; } @@ -6968,7 +7004,7 @@ Result<bool, nsresult> DatabaseConnection::ReclaimFreePagesWhileIdle( mInWriteTransaction = true; - bool freedSomePages = false, interrupted = false; + bool freedSomePages = false; const auto rollback = [&aRollbackStatement, this](const auto&) { MOZ_ASSERT(mInWriteTransaction); @@ -6984,14 +7020,12 @@ Result<bool, nsresult> DatabaseConnection::ReclaimFreePagesWhileIdle( uint64_t previousFreelistCount = (uint64_t)aFreelistCount + 1; QM_TRY(CollectWhile( - [&aFreelistCount, &previousFreelistCount, &interrupted, - currentThread]() -> Result<bool, nsresult> { - if (NS_HasPendingEvents(currentThread)) { - // Abort if something else wants to use the thread, and - // roll back this transaction. It's ok if we never make - // progress here because the idle service should - // eventually reclaim this space. - interrupted = true; + [&aFreelistCount, &previousFreelistCount, + &aInterrupted]() -> Result<bool, nsresult> { + if (aInterrupted) { + // On interrupt, abort and roll back this transaction. It's ok + // if we never make progress here because the idle service + // should eventually reclaim this space. return false; } // If we were not able to free anything, we might either see @@ -7001,7 +7035,7 @@ Result<bool, nsresult> DatabaseConnection::ReclaimFreePagesWhileIdle( bool madeProgress = previousFreelistCount != aFreelistCount; previousFreelistCount = aFreelistCount; MOZ_ASSERT(madeProgress); - QM_WARNONLY_TRY(MOZ_TO_RESULT(!madeProgress)); + QM_WARNONLY_TRY(MOZ_TO_RESULT(madeProgress)); return madeProgress && (aFreelistCount != 0); }, [&aFreelistStatement, &aFreelistCount, &incrementalVacuumStmt, @@ -7015,9 +7049,9 @@ Result<bool, nsresult> DatabaseConnection::ReclaimFreePagesWhileIdle( return Ok{}; }) - .andThen([&commitStmt, &freedSomePages, &interrupted, &rollback, + .andThen([&commitStmt, &freedSomePages, &aInterrupted, &rollback, this](Ok) -> Result<Ok, nsresult> { - if (interrupted) { + if (aInterrupted) { rollback(Ok{}); freedSomePages = false; } @@ -7982,8 +8016,9 @@ void ConnectionPool::CloseIdleDatabases() { } if (!mDatabasesPerformingIdleMaintenance.IsEmpty()) { - for (const auto dbInfo : mDatabasesPerformingIdleMaintenance) { - CloseDatabase(*dbInfo); + for (PerformingIdleMaintenanceDatabaseInfo& performingIdleMaintenanceInfo : + mDatabasesPerformingIdleMaintenance) { + CloseDatabase(*performingIdleMaintenanceInfo.mDatabaseInfo); } mDatabasesPerformingIdleMaintenance.Clear(); } @@ -8059,16 +8094,13 @@ bool ConnectionPool::ScheduleTransaction(TransactionInfo& aTransactionInfo, // deliberately const to prevent the attempt to wrongly optimize the // refcounting by passing runnable.forget() to the Dispatch method, see // bug 1598559. - const nsCOMPtr<nsIRunnable> runnable = - new Runnable("IndexedDBDummyRunnable"); for (uint32_t index = mDatabasesPerformingIdleMaintenance.Length(); index > 0; index--) { - const auto dbInfo = mDatabasesPerformingIdleMaintenance[index - 1]; - dbInfo->mThreadInfo.AssertValid(); + const auto& performingIdleMaintenanceInfo = + mDatabasesPerformingIdleMaintenance[index - 1]; - MOZ_ALWAYS_SUCCEEDS(dbInfo->mThreadInfo.ThreadRef().Dispatch( - runnable, NS_DISPATCH_NORMAL)); + performingIdleMaintenanceInfo.mIdleConnectionRunnable->Interrupt(); } } @@ -8369,12 +8401,15 @@ void ConnectionPool::PerformIdleDatabaseMaintenance( aDatabaseInfo.mNeedsCheckpoint = false; aDatabaseInfo.mIdle = false; + auto idleConnectionRunnable = + MakeRefPtr<IdleConnectionRunnable>(aDatabaseInfo, neededCheckpoint); + mDatabasesPerformingIdleMaintenance.AppendElement( - WrapNotNullUnchecked(&aDatabaseInfo)); + PerformingIdleMaintenanceDatabaseInfo{aDatabaseInfo, + idleConnectionRunnable}); MOZ_ALWAYS_SUCCEEDS(aDatabaseInfo.mThreadInfo.ThreadRef().Dispatch( - MakeAndAddRef<IdleConnectionRunnable>(aDatabaseInfo, neededCheckpoint), - NS_DISPATCH_NORMAL)); + idleConnectionRunnable.forget(), NS_DISPATCH_NORMAL)); } void ConnectionPool::CloseDatabase(DatabaseInfo& aDatabaseInfo) const { @@ -8437,7 +8472,8 @@ ConnectionPool::IdleConnectionRunnable::Run() { // The connection could be null if EnsureConnection() didn't run or was not // successful in TransactionDatabaseOperationBase::RunOnConnectionThread(). if (mDatabaseInfo.mConnection) { - mDatabaseInfo.mConnection->DoIdleProcessing(mNeedsCheckpoint); + mDatabaseInfo.mConnection->DoIdleProcessing(mNeedsCheckpoint, + mInterrupted); } MOZ_ALWAYS_SUCCEEDS(owningThread->Dispatch(this, NS_DISPATCH_NORMAL)); @@ -8733,6 +8769,25 @@ ConnectionPool::IdleDatabaseInfo::~IdleDatabaseInfo() { MOZ_COUNT_DTOR(ConnectionPool::IdleDatabaseInfo); } +ConnectionPool::PerformingIdleMaintenanceDatabaseInfo:: + PerformingIdleMaintenanceDatabaseInfo( + DatabaseInfo& aDatabaseInfo, + RefPtr<IdleConnectionRunnable> aIdleConnectionRunnable) + : mDatabaseInfo(WrapNotNullUnchecked(&aDatabaseInfo)), + mIdleConnectionRunnable(std::move(aIdleConnectionRunnable)) { + AssertIsOnBackgroundThread(); + MOZ_ASSERT(mIdleConnectionRunnable); + + MOZ_COUNT_CTOR(ConnectionPool::PerformingIdleMaintenanceDatabaseInfo); +} + +ConnectionPool::PerformingIdleMaintenanceDatabaseInfo:: + ~PerformingIdleMaintenanceDatabaseInfo() { + AssertIsOnBackgroundThread(); + + MOZ_COUNT_DTOR(ConnectionPool::PerformingIdleMaintenanceDatabaseInfo); +} + ConnectionPool::IdleThreadInfo::IdleThreadInfo(ThreadInfo aThreadInfo) : IdleResource(TimeStamp::NowLoRes() + TimeDuration::FromMilliseconds(kConnectionThreadIdleMS)), @@ -8915,8 +8970,10 @@ DatabaseLoggingInfo::~DatabaseLoggingInfo() { * Factory ******************************************************************************/ -Factory::Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo) - : mLoggingInfo(std::move(aLoggingInfo)) +Factory::Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo, + const nsACString& aSystemLocale) + : mSystemLocale(aSystemLocale), + mLoggingInfo(std::move(aLoggingInfo)) #ifdef DEBUG , mActorDestroyed(false) @@ -8929,7 +8986,8 @@ Factory::Factory(RefPtr<DatabaseLoggingInfo> aLoggingInfo) Factory::~Factory() { MOZ_ASSERT(mActorDestroyed); } // static -SafeRefPtr<Factory> Factory::Create(const LoggingInfo& aLoggingInfo) { +SafeRefPtr<Factory> Factory::Create(const LoggingInfo& aLoggingInfo, + const nsACString& aSystemLocale) { AssertIsOnBackgroundThread(); MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread()); @@ -8966,7 +9024,7 @@ SafeRefPtr<Factory> Factory::Create(const LoggingInfo& aLoggingInfo) { return do_AddRef(entry.Data()); }); - return MakeSafeRefPtr<Factory>(std::move(loggingInfo)); + return MakeSafeRefPtr<Factory>(std::move(loggingInfo), aSystemLocale); } void Factory::ActorDestroy(ActorDestroyReason aWhy) { @@ -9045,6 +9103,14 @@ Factory::AllocPBackgroundIDBFactoryRequestParent( return nullptr; } + if (NS_AUUF_OR_WARN_IF( + principalInfo.type() == PrincipalInfo::TContentPrincipalInfo && + QuotaManager::IsOriginInternal( + principalInfo.get_ContentPrincipalInfo().originNoSuffix()) && + metadata.persistenceType() != PERSISTENCE_TYPE_PERSISTENT)) { + return nullptr; + } + Maybe<ContentParentId> contentParentId; uint64_t childID = BackgroundParent::GetChildID(Manager()); @@ -9087,7 +9153,7 @@ mozilla::ipc::IPCResult Factory::RecvPBackgroundIDBFactoryRequestConstructor( auto* op = static_cast<FactoryOp*>(aActor); - MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(op)); + MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(op)); return IPC_OK(); } @@ -12247,8 +12313,9 @@ nsresult QuotaClient::GetUsageForOriginInternal( // If this fails, it probably means we are in a serious situation. // e.g. Filesystem corruption. Will handle this in bug 1521541. QM_TRY(MOZ_TO_RESULT(RemoveDatabaseFilesAndDirectory( - *directory, subdirNameBase, nullptr, aPersistenceType, - aOriginMetadata, u""_ns)), + *directory, subdirNameBase, /* aQuotaManager */ nullptr, + aPersistenceType, aOriginMetadata, + /* aDatabaseName */ u""_ns)), Err(NS_ERROR_UNEXPECTED)); databaseFilenames.Remove(subdirNameBase); @@ -14476,10 +14543,6 @@ void FactoryOp::StringifyState(nsACString& aResult) const { aResult.AppendLiteral("Initial"); return; - case State::FinishOpen: - aResult.AppendLiteral("FinishOpen"); - return; - case State::DirectoryOpenPending: aResult.AppendLiteral("DirectoryOpenPending"); return; @@ -14538,23 +14601,50 @@ void FactoryOp::Stringify(nsACString& aResult) const { } nsresult FactoryOp::Open() { - AssertIsOnMainThread(); + AssertIsOnOwningThread(); MOZ_ASSERT(mState == State::Initial); + MOZ_ASSERT(mOriginMetadata.mOrigin.IsEmpty()); + MOZ_ASSERT(!mDirectoryLock); - if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) || - !OperationMayProceed()) { + if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || + IsActorDestroyed()) { IDB_REPORT_INTERNAL_ERR(); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } + QM_TRY(QuotaManager::EnsureCreated()); + + QuotaManager* const quotaManager = QuotaManager::Get(); + MOZ_ASSERT(quotaManager); + + const DatabaseMetadata& metadata = mCommonParams.metadata(); + + const PersistenceType persistenceType = metadata.persistenceType(); + const PrincipalInfo& principalInfo = mCommonParams.principalInfo(); + + QM_TRY_UNWRAP(auto principalMetadata, + quotaManager->GetInfoFromValidatedPrincipalInfo(principalInfo)); + + mOriginMetadata = {std::move(principalMetadata), persistenceType}; + if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) { MOZ_ASSERT(mCommonParams.metadata().persistenceType() == PERSISTENCE_TYPE_PERSISTENT); + + mEnforcingQuota = false; } else if (principalInfo.type() == PrincipalInfo::TContentPrincipalInfo) { const ContentPrincipalInfo& contentPrincipalInfo = principalInfo.get_ContentPrincipalInfo(); - if (contentPrincipalInfo.attrs().mPrivateBrowsingId != 0) { + + MOZ_ASSERT_IF( + QuotaManager::IsOriginInternal(contentPrincipalInfo.originNoSuffix()), + mCommonParams.metadata().persistenceType() == + PERSISTENCE_TYPE_PERSISTENT); + + mEnforcingQuota = persistenceType != PERSISTENCE_TYPE_PERSISTENT; + + if (mOriginMetadata.mIsPrivate) { if (StaticPrefs::dom_indexedDB_privateBrowsing_enabled()) { // Explicitly disallow moz-extension urls from using the encrypted // indexedDB storage mode when the caller is an extension (see Bug @@ -14573,35 +14663,46 @@ nsresult FactoryOp::Open() { MOZ_ASSERT(false); } - QM_TRY_INSPECT(const auto& permission, CheckPermission()); + QuotaManager::GetStorageId(persistenceType, mOriginMetadata.mOrigin, + Client::IDB, mDatabaseId); - MOZ_ASSERT(permission == PermissionValue::kPermissionAllowed || - permission == PermissionValue::kPermissionDenied); + mDatabaseId.Append('*'); + mDatabaseId.Append(NS_ConvertUTF16toUTF8(metadata.name())); - if (permission == PermissionValue::kPermissionDenied) { - return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; - } + // Need to get database file path before opening the directory. + // XXX: For what reason? + QM_TRY_UNWRAP( + mDatabaseFilePath, + ([this, metadata, quotaManager]() -> mozilla::Result<nsString, nsresult> { + QM_TRY_INSPECT(const auto& dbFile, + quotaManager->GetOriginDirectory(mOriginMetadata)); - { - // These services have to be started on the main thread currently. + QM_TRY(MOZ_TO_RESULT(dbFile->Append( + NS_LITERAL_STRING_FROM_CSTRING(IDB_DIRECTORY_NAME)))); - IndexedDatabaseManager* mgr; - if (NS_WARN_IF(!(mgr = IndexedDatabaseManager::GetOrCreate()))) { - IDB_REPORT_INTERNAL_ERR(); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - } + QM_TRY(MOZ_TO_RESULT( + dbFile->Append(GetDatabaseFilenameBase(metadata.name(), + mOriginMetadata.mIsPrivate) + + kSQLiteSuffix))); - nsCOMPtr<mozIStorageService> ss; - if (NS_WARN_IF(!(ss = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID)))) { - IDB_REPORT_INTERNAL_ERR(); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - } - } + QM_TRY_RETURN( + MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsString, dbFile, GetPath)); + }())); - MOZ_ASSERT(permission == PermissionValue::kPermissionAllowed); + // Open directory + mState = State::DirectoryOpenPending; - mState = State::FinishOpen; - MOZ_ALWAYS_SUCCEEDS(mOwningEventTarget->Dispatch(this, NS_DISPATCH_NORMAL)); + quotaManager->OpenClientDirectory({mOriginMetadata, Client::IDB}) + ->Then( + GetCurrentSerialEventTarget(), __func__, + [self = RefPtr(this)]( + const ClientDirectoryLockPromise::ResolveOrRejectValue& aValue) { + if (aValue.IsResolve()) { + self->DirectoryLockAcquired(aValue.ResolveValue()); + } else { + self->DirectoryLockFailed(); + } + }); return NS_OK; } @@ -14724,37 +14825,6 @@ void FactoryOp::FinishSendResults() { mFactory = nullptr; } -Result<PermissionValue, nsresult> FactoryOp::CheckPermission() { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mState == State::Initial); - - const PrincipalInfo& principalInfo = mCommonParams.principalInfo(); - MOZ_ASSERT(principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo || - principalInfo.type() == PrincipalInfo::TContentPrincipalInfo); - - if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) { - MOZ_ASSERT(mState == State::Initial); - - return PermissionValue::kPermissionAllowed; - } - - QM_TRY_INSPECT( - const auto& permission, - ([persistenceType = mCommonParams.metadata().persistenceType(), - origin = QuotaManager::GetOriginFromValidatedPrincipalInfo( - principalInfo)]() -> mozilla::Result<PermissionValue, nsresult> { - if (persistenceType == PERSISTENCE_TYPE_PERSISTENT) { - if (QuotaManager::IsOriginInternal(origin)) { - return PermissionValue::kPermissionAllowed; - } - return Err(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); - } - return PermissionValue::kPermissionAllowed; - })()); - - return permission; -} - nsresult FactoryOp::SendVersionChangeMessages( DatabaseActorInfo* aDatabaseActorInfo, Maybe<Database&> aOpeningDatabase, uint64_t aOldVersion, const Maybe<uint64_t>& aNewVersion) { @@ -14795,91 +14865,6 @@ nsresult FactoryOp::SendVersionChangeMessages( return NS_OK; } // namespace indexedDB -nsresult FactoryOp::FinishOpen() { - AssertIsOnOwningThread(); - MOZ_ASSERT(mState == State::FinishOpen); - MOZ_ASSERT(mOriginMetadata.mOrigin.IsEmpty()); - MOZ_ASSERT(!mDirectoryLock); - - if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) || - IsActorDestroyed()) { - IDB_REPORT_INTERNAL_ERR(); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - } - - QM_TRY(QuotaManager::EnsureCreated()); - - QuotaManager* const quotaManager = QuotaManager::Get(); - MOZ_ASSERT(quotaManager); - - const PrincipalInfo& principalInfo = mCommonParams.principalInfo(); - - const DatabaseMetadata& metadata = mCommonParams.metadata(); - - const PersistenceType persistenceType = metadata.persistenceType(); - - if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) { - mOriginMetadata = {QuotaManager::GetInfoForChrome(), persistenceType}; - - MOZ_ASSERT(QuotaManager::IsOriginInternal(mOriginMetadata.mOrigin)); - - mEnforcingQuota = false; - } else { - MOZ_ASSERT(principalInfo.type() == PrincipalInfo::TContentPrincipalInfo); - - QM_TRY_UNWRAP( - auto principalMetadata, - quotaManager->GetInfoFromValidatedPrincipalInfo(principalInfo)); - - mOriginMetadata = {std::move(principalMetadata), persistenceType}; - - mEnforcingQuota = persistenceType != PERSISTENCE_TYPE_PERSISTENT; - } - - QuotaManager::GetStorageId(persistenceType, mOriginMetadata.mOrigin, - Client::IDB, mDatabaseId); - - mDatabaseId.Append('*'); - mDatabaseId.Append(NS_ConvertUTF16toUTF8(metadata.name())); - - // Need to get database file path before opening the directory. - // XXX: For what reason? - QM_TRY_UNWRAP( - mDatabaseFilePath, - ([this, metadata, quotaManager]() -> mozilla::Result<nsString, nsresult> { - QM_TRY_INSPECT(const auto& dbFile, - quotaManager->GetOriginDirectory(mOriginMetadata)); - - QM_TRY(MOZ_TO_RESULT(dbFile->Append( - NS_LITERAL_STRING_FROM_CSTRING(IDB_DIRECTORY_NAME)))); - - QM_TRY(MOZ_TO_RESULT( - dbFile->Append(GetDatabaseFilenameBase(metadata.name(), - mOriginMetadata.mIsPrivate) + - kSQLiteSuffix))); - - QM_TRY_RETURN( - MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsString, dbFile, GetPath)); - }())); - - // Open directory - mState = State::DirectoryOpenPending; - - quotaManager->OpenClientDirectory({mOriginMetadata, Client::IDB}) - ->Then( - GetCurrentSerialEventTarget(), __func__, - [self = RefPtr(this)]( - const ClientDirectoryLockPromise::ResolveOrRejectValue& aValue) { - if (aValue.IsResolve()) { - self->DirectoryLockAcquired(aValue.ResolveValue()); - } else { - self->DirectoryLockFailed(); - } - }); - - return NS_OK; -} - bool FactoryOp::MustWaitFor(const FactoryOp& aExistingOp) { AssertIsOnOwningThread(); @@ -14920,10 +14905,6 @@ FactoryOp::Run() { QM_WARNONLY_TRY(MOZ_TO_RESULT(Open()), handleError); break; - case State::FinishOpen: - QM_WARNONLY_TRY(MOZ_TO_RESULT(FinishOpen()), handleError); - break; - case State::DatabaseOpenPending: QM_WARNONLY_TRY(MOZ_TO_RESULT(DatabaseOpen()), handleError); break; @@ -15328,7 +15309,7 @@ nsresult OpenDatabaseOp::LoadDatabaseInformation( QM_TRY_INSPECT( const auto& lastIndexId, - ([&aConnection, + ([this, &aConnection, &objectStores]() -> mozilla::Result<IndexOrObjectStoreId, nsresult> { // Load index information QM_TRY_INSPECT( @@ -15345,7 +15326,7 @@ nsresult OpenDatabaseOp::LoadDatabaseInformation( QM_TRY(CollectWhileHasResult( *stmt, - [&lastIndexId, &objectStores, &aConnection, + [this, &lastIndexId, &objectStores, &aConnection, usedIds = Maybe<nsTHashSet<uint64_t>>{}, usedNames = Maybe<nsTHashSet<nsString>>{}]( auto& stmt) mutable -> mozilla::Result<Ok, nsresult> { @@ -15436,8 +15417,7 @@ nsresult OpenDatabaseOp::LoadDatabaseInformation( indexMetadata->mCommonMetadata.locale(); const bool& isAutoLocale = indexMetadata->mCommonMetadata.autoLocale(); - const nsCString& systemLocale = - IndexedDatabaseManager::GetLocale(); + const nsCString& systemLocale = mFactory->GetSystemLocale(); if (!systemLocale.IsEmpty() && isAutoLocale && !indexedLocale.Equals(systemLocale)) { QM_TRY(MOZ_TO_RESULT(UpdateLocaleAwareIndex( @@ -16985,7 +16965,8 @@ TransactionBase::CommitOp::Run() { connection->FinishWriteTransaction(); if (mTransaction->GetMode() == IDBTransaction::Mode::Cleanup) { - connection->DoIdleProcessing(/* aNeedsCheckpoint */ true); + connection->DoIdleProcessing(/* aNeedsCheckpoint */ true, + /* aInterrupted */ Atomic<bool>(false)); connection->EnableQuotaChecks(); } diff --git a/dom/indexedDB/ActorsParent.h b/dom/indexedDB/ActorsParent.h index ab6c6c142f..45c0bf8688 100644 --- a/dom/indexedDB/ActorsParent.h +++ b/dom/indexedDB/ActorsParent.h @@ -38,10 +38,11 @@ class PBackgroundIDBFactoryParent; class PBackgroundIndexedDBUtilsParent; already_AddRefed<PBackgroundIDBFactoryParent> AllocPBackgroundIDBFactoryParent( - const LoggingInfo& aLoggingInfo); + const LoggingInfo& aLoggingInfo, const nsACString& aSystemLocale); bool RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor, - const LoggingInfo& aLoggingInfo); + const LoggingInfo& aLoggingInfo, + const nsACString& aSystemLocale); bool DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor); diff --git a/dom/indexedDB/ActorsParentCommon.cpp b/dom/indexedDB/ActorsParentCommon.cpp index 637906b6d3..1b92e15dad 100644 --- a/dom/indexedDB/ActorsParentCommon.cpp +++ b/dom/indexedDB/ActorsParentCommon.cpp @@ -728,7 +728,7 @@ nsresult ExecuteSimpleSQLSequence(mozIStorageConnection& aConnection, Span<const nsLiteralCString> aSQLCommands) { for (const auto& aSQLCommand : aSQLCommands) { const auto extraInfo = quota::ScopedLogExtraInfo{ - quota::ScopedLogExtraInfo::kTagQuery, aSQLCommand}; + quota::ScopedLogExtraInfo::kTagQueryTainted, aSQLCommand}; QM_TRY(MOZ_TO_RESULT(aConnection.ExecuteSimpleSQL(aSQLCommand))); } diff --git a/dom/indexedDB/IDBFactory.cpp b/dom/indexedDB/IDBFactory.cpp index be34e1914d..81dce07d7e 100644 --- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -242,6 +242,12 @@ Result<RefPtr<IDBFactory>, nsresult> IDBFactory::CreateForMainThreadJSInternal( return Err(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } + nsresult rv = mgr->EnsureLocale(); + if (NS_WARN_IF(NS_FAILED(rv))) { + IDB_REPORT_INTERNAL_ERR(); + return Err(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + }; + return CreateInternal(aGlobal, std::move(aPrincipalInfo), /* aInnerWindowID */ 0); } @@ -283,10 +289,17 @@ nsresult IDBFactory::AllowedForWindowInternal( MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aWindow); - if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) { + IndexedDatabaseManager* mgr = IndexedDatabaseManager::GetOrCreate(); + if (NS_WARN_IF(!mgr)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } + nsresult rv = mgr->EnsureLocale(); + if (NS_WARN_IF(NS_FAILED(rv))) { + IDB_REPORT_INTERNAL_ERR(); + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + }; + StorageAccess access = StorageAllowedForWindow(aWindow); // the factory callsite records whether the browser is in private browsing. @@ -341,10 +354,16 @@ bool IDBFactory::AllowedForPrincipal(nsIPrincipal* aPrincipal, MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipal); - if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) { + IndexedDatabaseManager* mgr = IndexedDatabaseManager::GetOrCreate(); + if (NS_WARN_IF(!mgr)) { return false; } + nsresult rv = mgr->EnsureLocale(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + }; + if (aPrincipal->IsSystemPrincipal()) { if (aIsSystemPrincipal) { *aIsSystemPrincipal = true; @@ -573,19 +592,20 @@ RefPtr<IDBOpenDBRequest> IDBFactory::OpenInternal( PersistenceType persistenceType; - bool isInternal = principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo; - if (!isInternal && + bool isPersistent = + principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo; + if (!isPersistent && principalInfo.type() == PrincipalInfo::TContentPrincipalInfo) { nsCString origin = principalInfo.get_ContentPrincipalInfo().originNoSuffix(); - isInternal = QuotaManager::IsOriginInternal(origin); + isPersistent = QuotaManager::IsOriginInternal(origin); } const bool isPrivate = principalInfo.type() == PrincipalInfo::TContentPrincipalInfo && principalInfo.get_ContentPrincipalInfo().attrs().mPrivateBrowsingId > 0; - if (isInternal) { + if (isPersistent) { // Chrome privilege and internal origins always get persistent storage. persistenceType = PERSISTENCE_TYPE_PERSISTENT; } else if (isPrivate) { @@ -641,7 +661,8 @@ RefPtr<IDBOpenDBRequest> IDBFactory::OpenInternal( mBackgroundActor = static_cast<BackgroundFactoryChild*>( backgroundActor->SendPBackgroundIDBFactoryConstructor( - actor, idbThreadLocal->GetLoggingInfo())); + actor, idbThreadLocal->GetLoggingInfo(), + IndexedDatabaseManager::GetLocale())); if (NS_WARN_IF(!mBackgroundActor)) { mBackgroundActorFailed = true; diff --git a/dom/indexedDB/IndexedDatabaseManager.cpp b/dom/indexedDB/IndexedDatabaseManager.cpp index 5ee16ec5e9..0558c38826 100644 --- a/dom/indexedDB/IndexedDatabaseManager.cpp +++ b/dom/indexedDB/IndexedDatabaseManager.cpp @@ -296,25 +296,6 @@ nsresult IndexedDatabaseManager::Init() { Preferences::RegisterCallbackAndCall(MaxPreloadExtraRecordsPrefChangeCallback, kPrefMaxPreloadExtraRecords); - nsAutoCString acceptLang; - Preferences::GetLocalizedCString("intl.accept_languages", acceptLang); - - // Split values on commas. - for (const auto& lang : - nsCCharSeparatedTokenizer(acceptLang, ',').ToRange()) { - mozilla::intl::LocaleCanonicalizer::Vector asciiString{}; - auto result = mozilla::intl::LocaleCanonicalizer::CanonicalizeICULevel1( - PromiseFlatCString(lang).get(), asciiString); - if (result.isOk()) { - mLocale.AssignASCII(asciiString); - break; - } - } - - if (mLocale.IsEmpty()) { - mLocale.AssignLiteral("en_US"); - } - return NS_OK; } @@ -652,11 +633,37 @@ void IndexedDatabaseManager::LoggingModePrefChangedCallback( } } +nsresult IndexedDatabaseManager::EnsureLocale() { + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoCString acceptLang; + Preferences::GetLocalizedCString("intl.accept_languages", acceptLang); + + // Split values on commas. + for (const auto& lang : + nsCCharSeparatedTokenizer(acceptLang, ',').ToRange()) { + mozilla::intl::LocaleCanonicalizer::Vector asciiString{}; + auto result = mozilla::intl::LocaleCanonicalizer::CanonicalizeICULevel1( + PromiseFlatCString(lang).get(), asciiString); + if (result.isOk()) { + mLocale.AssignASCII(asciiString); + break; + } + } + + if (mLocale.IsEmpty()) { + mLocale.AssignLiteral("en_US"); + } + + return NS_OK; +} + // static const nsCString& IndexedDatabaseManager::GetLocale() { IndexedDatabaseManager* idbManager = Get(); MOZ_ASSERT(idbManager, "IDBManager is not ready!"); + MOZ_ASSERT(!idbManager->mLocale.IsEmpty()); return idbManager->mLocale; } diff --git a/dom/indexedDB/IndexedDatabaseManager.h b/dom/indexedDB/IndexedDatabaseManager.h index 5bf6485aff..0766143dd6 100644 --- a/dom/indexedDB/IndexedDatabaseManager.h +++ b/dom/indexedDB/IndexedDatabaseManager.h @@ -123,6 +123,9 @@ class IndexedDatabaseManager final { nsresult FlushPendingFileDeletions(); + // XXX This extra explicit initialization should go away with bug 1730706. + nsresult EnsureLocale(); + static const nsCString& GetLocale(); static bool ResolveSandboxBinding(JSContext* aCx); diff --git a/dom/indexedDB/SchemaUpgrades.cpp b/dom/indexedDB/SchemaUpgrades.cpp index 6066390740..234c4c9f04 100644 --- a/dom/indexedDB/SchemaUpgrades.cpp +++ b/dom/indexedDB/SchemaUpgrades.cpp @@ -2861,8 +2861,10 @@ nsresult UpgradeFileIdsFunction::Init(nsIFile* aFMDirectory, // purpose is to store file ids without adding more complexity or code // duplication. auto fileManager = MakeSafeRefPtr<DatabaseFileManager>( - PERSISTENCE_TYPE_INVALID, quota::OriginMetadata{}, u""_ns, ""_ns, false, - false); + PERSISTENCE_TYPE_INVALID, quota::OriginMetadata{}, + /* aDatabaseName */ u""_ns, /* aDatabaseID */ ""_ns, + /* aEnforcingQuota */ false, + /* aIsInPrivateBrowsingMode */ false); nsresult rv = fileManager->Init(aFMDirectory, aConnection); if (NS_WARN_IF(NS_FAILED(rv))) { diff --git a/dom/indexedDB/SerializationHelpers.h b/dom/indexedDB/SerializationHelpers.h index 7bc05720d4..488c1eb044 100644 --- a/dom/indexedDB/SerializationHelpers.h +++ b/dom/indexedDB/SerializationHelpers.h @@ -10,6 +10,7 @@ #include "ipc/EnumSerializer.h" #include "ipc/IPCMessageUtilsSpecializations.h" +#include "mozilla/dom/BindingIPCUtils.h" #include "mozilla/dom/indexedDB/Key.h" #include "mozilla/dom/indexedDB/KeyPath.h" #include "mozilla/dom/IDBCursor.h" @@ -61,10 +62,8 @@ struct ParamTraits<mozilla::dom::indexedDB::KeyPath> { template <> struct ParamTraits<mozilla::dom::IDBCursor::Direction> - : public ContiguousEnumSerializer< - mozilla::dom::IDBCursor::Direction, - mozilla::dom::IDBCursor::Direction::Next, - mozilla::dom::IDBCursor::Direction::EndGuard_> {}; + : public mozilla::dom::WebIDLEnumSerializer< + mozilla::dom::IDBCursor::Direction> {}; template <> struct ParamTraits<mozilla::dom::IDBTransaction::Mode> diff --git a/dom/indexedDB/test/abort_on_reload.html b/dom/indexedDB/test/abort_on_reload.html index 4e4fe3a339..7b3cba6d95 100644 --- a/dom/indexedDB/test/abort_on_reload.html +++ b/dom/indexedDB/test/abort_on_reload.html @@ -3,7 +3,7 @@ <body> <script> function createDb() { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const openRequest = indexedDB.open("test-abort-on-reload", 1); openRequest.onsuccess = () => { const db = openRequest.result; @@ -14,7 +14,7 @@ }; resolve(); }; - openRequest.onupgradeneeded = (evt) => { + openRequest.onupgradeneeded = () => { // Interrupt upgrade window.location.reload(); opener.info('reload requested\n'); @@ -24,7 +24,7 @@ } function reset() { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const request = indexedDB.deleteDatabase("test-abort-on-reload"); request.onsuccess = resolve; }); diff --git a/dom/indexedDB/test/bfcache_page1.html b/dom/indexedDB/test/bfcache_page1.html index e537d42008..a78d4c0d94 100644 --- a/dom/indexedDB/test/bfcache_page1.html +++ b/dom/indexedDB/test/bfcache_page1.html @@ -6,7 +6,7 @@ request.onupgradeneeded = function(e) { var db = e.target.result; // This should never be called - db.onversionchange = function(e) { + db.onversionchange = function() { db.transaction(["mystore"]).objectStore("mystore").put({ hello: "fail" }, 42); }; var trans = e.target.transaction; diff --git a/dom/indexedDB/test/blob_worker_crash_iframe.html b/dom/indexedDB/test/blob_worker_crash_iframe.html index 15d8277515..8f98ba206a 100644 --- a/dom/indexedDB/test/blob_worker_crash_iframe.html +++ b/dom/indexedDB/test/blob_worker_crash_iframe.html @@ -80,7 +80,7 @@ dump("EXCEPTION IN CREATION: " + e + "\n " + e.stack + "\n"); objectStore.delete(42).onsuccess = closeDBTellOwningThread; } - function closeDBTellOwningThread(event) { + function closeDBTellOwningThread() { // Now that worker has latched the blob, clean up the database. db.close(); db = null; diff --git a/dom/indexedDB/test/browser_private_idb.js b/dom/indexedDB/test/browser_private_idb.js index 5627361fc6..fb8108ef35 100644 --- a/dom/indexedDB/test/browser_private_idb.js +++ b/dom/indexedDB/test/browser_private_idb.js @@ -12,7 +12,7 @@ async function idbCheckFunc() { try { console.log("opening db"); const req = factory.open("db", 1); - const result = await new Promise((resolve, reject) => { + const result = await new Promise(resolve => { req.onerror = () => { resolve("error"); }; @@ -21,7 +21,7 @@ async function idbCheckFunc() { resolve("created"); }; // ...so this will lose the race - req.onsuccess = event => { + req.onsuccess = () => { resolve("already-exists"); }; }); diff --git a/dom/indexedDB/test/bug839193.js b/dom/indexedDB/test/bug839193.js index b5b951e32e..d267c00348 100644 --- a/dom/indexedDB/test/bug839193.js +++ b/dom/indexedDB/test/bug839193.js @@ -6,7 +6,7 @@ const nsIQuotaManagerService = Ci.nsIQuotaManagerService; var gURI = Services.io.newURI("http://localhost"); -function onUsageCallback(request) {} +function onUsageCallback() {} function onLoad() { var quotaManagerService = Cc[ diff --git a/dom/indexedDB/test/error_events_abort_transactions_iframe.html b/dom/indexedDB/test/error_events_abort_transactions_iframe.html index 672b7c3a5b..b6df9d8b0b 100644 --- a/dom/indexedDB/test/error_events_abort_transactions_iframe.html +++ b/dom/indexedDB/test/error_events_abort_transactions_iframe.html @@ -29,7 +29,7 @@ finishTest(); } - function unexpectedSuccessHandler(event) { + function unexpectedSuccessHandler() { ok(false, "got success when it was not expected!"); finishTest(); } @@ -43,7 +43,7 @@ }, 0); } - window.onerror = function(message, filename, lineno) { + window.onerror = function(message) { is(message, "ConstraintError", "Expect a constraint error"); }; @@ -82,7 +82,7 @@ request = objectStore.add({}, 1); request.onsuccess = unexpectedSuccessHandler; - request.onerror = function(event) { + request.onerror = function() { // Don't do anything! ConstraintError is expected in window.onerror. }; event = yield undefined; diff --git a/dom/indexedDB/test/event_propagation_iframe.html b/dom/indexedDB/test/event_propagation_iframe.html index 3788958014..2d852b3b98 100644 --- a/dom/indexedDB/test/event_propagation_iframe.html +++ b/dom/indexedDB/test/event_propagation_iframe.html @@ -101,7 +101,7 @@ event = yield undefined; request = objectStore.add({}, 1); - request.onsuccess = function(event) { + request.onsuccess = function() { ok(false, "Did not expect second add to succeed."); }; request.onerror = errorEventCounter; @@ -119,7 +119,7 @@ event = yield undefined; request = objectStore.add({}, 1); - request.onsuccess = function(event) { + request.onsuccess = function() { ok(false, "Did not expect second add to succeed."); }; request.onerror = errorEventCounter; diff --git a/dom/indexedDB/test/exceptions_in_events_iframe.html b/dom/indexedDB/test/exceptions_in_events_iframe.html index 25a4f01e77..b67d4c5b21 100644 --- a/dom/indexedDB/test/exceptions_in_events_iframe.html +++ b/dom/indexedDB/test/exceptions_in_events_iframe.html @@ -31,7 +31,7 @@ finishTest(); } - function unexpectedSuccessHandler(event) { + function unexpectedSuccessHandler() { ok(false, "got success when it was not expected!"); finishTest(); } @@ -105,7 +105,7 @@ ok(db.objectStoreNames.contains("foo"), "Has correct objectStore"); request = objectStore.add({}, 1); - request.onsuccess = function(event) { + request.onsuccess = function() { throw new Error("foo"); }; diff --git a/dom/indexedDB/test/head.js b/dom/indexedDB/test/head.js index 802f093c6b..b06658e466 100644 --- a/dom/indexedDB/test/head.js +++ b/dom/indexedDB/test/head.js @@ -74,7 +74,7 @@ function triggerSecondaryCommand(popup, win) { EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {}, win); } -function dismissNotification(popup) { +function dismissNotification() { info("dismissing notification"); executeSoon(function () { EventUtils.synthesizeKey("KEY_Escape"); diff --git a/dom/indexedDB/test/helpers.js b/dom/indexedDB/test/helpers.js index 3555abf722..2ba2a440df 100644 --- a/dom/indexedDB/test/helpers.js +++ b/dom/indexedDB/test/helpers.js @@ -3,6 +3,8 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable mozilla/no-comparison-or-assignment-inside-ok */ + // testSteps is expected to be defined by the test using this file. /* global testSteps:false */ @@ -482,7 +484,7 @@ function workerScript() { self.executeSoon = function (_fun_) { var channel = new MessageChannel(); channel.port1.postMessage(""); - channel.port2.onmessage = function (event) { + channel.port2.onmessage = function () { _fun_(); }; }; diff --git a/dom/indexedDB/test/leaving_page_iframe.html b/dom/indexedDB/test/leaving_page_iframe.html index 4ed299df33..712fb89991 100644 --- a/dom/indexedDB/test/leaving_page_iframe.html +++ b/dom/indexedDB/test/leaving_page_iframe.html @@ -23,7 +23,7 @@ function madeMod() { parent.postMessage("didcommit", "*"); }; - store.put({ hello: "officer" }, 42).onsuccess = function(e) { + store.put({ hello: "officer" }, 42).onsuccess = function() { // Make this transaction run until the end of time or until the page is // navigated away, whichever comes first. function doGet() { diff --git a/dom/indexedDB/test/mochitest-common.toml b/dom/indexedDB/test/mochitest-common.toml index 4ba2312bd5..d42228da45 100644 --- a/dom/indexedDB/test/mochitest-common.toml +++ b/dom/indexedDB/test/mochitest-common.toml @@ -282,7 +282,7 @@ skip-if = ["true"] # disabled for the moment ["test_names_sorted.html"] skip-if = [ "xorigin && !debug", # Hangs - "os == 'linux' && bits == 64 && !debug", # Bug 1602927 + "os == 'linux' && os_version == '18.04' && bits == 64 && !debug", # Bug 1602927 ] ["test_objectCursors.html"] @@ -382,7 +382,9 @@ skip-if = [ ["test_upgrade_add_index.html"] skip-if = [ - "!debug && bits == 64 && (os == 'linux' || os == 'mac')", + "os == 'linux' && os_version == '18.04' && bits == 64 && !debug", + "apple_silicon && !debug", + "apple_catalina && !debug", "os == 'win'", #Bug 1637715 ] scheme = "https" diff --git a/dom/indexedDB/test/test_abort_on_reload.html b/dom/indexedDB/test/test_abort_on_reload.html index fd31e709c6..43e3178977 100644 --- a/dom/indexedDB/test/test_abort_on_reload.html +++ b/dom/indexedDB/test/test_abort_on_reload.html @@ -17,7 +17,7 @@ openedWindow = window.open("abort_on_reload.html"); } - function messageListener(event) { + function messageListener() { ok(true, "reload recorded"); if (++reloads == 20) { diff --git a/dom/indexedDB/test/test_event_listener_leaks.html b/dom/indexedDB/test/test_event_listener_leaks.html index d1d9a69068..ebe5c202dd 100644 --- a/dom/indexedDB/test/test_event_listener_leaks.html +++ b/dom/indexedDB/test/test_event_listener_leaks.html @@ -37,7 +37,7 @@ async function useIDB(contentWindow) { store.get(0).onsuccess = spin; } - store.put(0, "purgatory").onsuccess = e => { + store.put(0, "purgatory").onsuccess = () => { contentWindow.putCount += 1; spin(); }; diff --git a/dom/indexedDB/test/test_open_for_principal.html b/dom/indexedDB/test/test_open_for_principal.html index bd9da12f74..04cd86126b 100644 --- a/dom/indexedDB/test/test_open_for_principal.html +++ b/dom/indexedDB/test/test_open_for_principal.html @@ -10,6 +10,7 @@ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> <script type="text/javascript"> + // eslint-disable-next-line require-yield function* testSteps() { is("open" in indexedDB, true, "open() defined"); diff --git a/dom/indexedDB/test/third_party_window.html b/dom/indexedDB/test/third_party_window.html index 14b16bf5d4..20d453d7a3 100644 --- a/dom/indexedDB/test/third_party_window.html +++ b/dom/indexedDB/test/third_party_window.html @@ -14,7 +14,7 @@ let iframe = document.getElementById("iframe1"); iframe.src = evt.data.iframeUrl; - iframe.addEventListener("load", e => { + iframe.addEventListener("load", () => { iframe.contentWindow.postMessage(JSON.stringify(evt.data), "*"); }); diff --git a/dom/indexedDB/test/unit/test_blocked_order.js b/dom/indexedDB/test/unit/test_blocked_order.js index 212b1b3254..0301c12df2 100644 --- a/dom/indexedDB/test/unit/test_blocked_order.js +++ b/dom/indexedDB/test/unit/test_blocked_order.js @@ -33,7 +33,7 @@ function* testSteps() { let db = request.result; is(db.version, 1, "Got version 1"); - db.onversionchange = function (event) { + db.onversionchange = function () { info("Closing database " + thisIndex); db.close(); @@ -51,7 +51,7 @@ function* testSteps() { request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; - request.onblocked = function (event) { + request.onblocked = function () { ok(false, "Should not receive a blocked event"); }; @@ -95,7 +95,7 @@ function* testSteps() { let db = request.result; is(db.version, 1, "Got version 1"); - db.onversionchange = function (event) { + db.onversionchange = function () { if (thisIndex == databaseCount - 1) { info("Closing all databases with version 1"); @@ -121,7 +121,7 @@ function* testSteps() { request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; - request.onblocked = function (event) { + request.onblocked = function () { ok(false, "Should not receive a blocked event"); }; diff --git a/dom/indexedDB/test/unit/test_cleanup_transaction.js b/dom/indexedDB/test/unit/test_cleanup_transaction.js index cac3c9bf60..25af4c5729 100644 --- a/dom/indexedDB/test/unit/test_cleanup_transaction.js +++ b/dom/indexedDB/test/unit/test_cleanup_transaction.js @@ -74,12 +74,12 @@ function* testSteps() { event.stopPropagation(); }; - trans.oncomplete = function (event) { + trans.oncomplete = function () { i++; j++; testGenerator.next(true); }; - trans.onabort = function (event) { + trans.onabort = function () { is(trans.error.name, "QuotaExceededError", "Reached quota limit"); testGenerator.next(false); }; diff --git a/dom/indexedDB/test/unit/test_clear.js b/dom/indexedDB/test/unit/test_clear.js index d504ff8851..87eef2c0ab 100644 --- a/dom/indexedDB/test/unit/test_clear.js +++ b/dom/indexedDB/test/unit/test_clear.js @@ -70,7 +70,7 @@ function* testSteps() { request = db.transaction("foo").objectStore("foo").openCursor(); request.onerror = errorHandler; - request.onsuccess = function (event) { + request.onsuccess = function () { let cursor = request.result; if (cursor) { ok(false, "Shouldn't have any entries"); diff --git a/dom/indexedDB/test/unit/test_connection_idle_maintenance.js b/dom/indexedDB/test/unit/test_connection_idle_maintenance.js new file mode 100644 index 0000000000..288f656c65 --- /dev/null +++ b/dom/indexedDB/test/unit/test_connection_idle_maintenance.js @@ -0,0 +1,97 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* exported testSteps */ +async function testSteps() { + // A constant used to deal with small decrease in usage when transactions are + // transferred from the WAL file back into the original database, also called + // as checkpointing. + const cosmologicalConstant = 31768; + + // The length of time that database connections will be held open after all + // transactions have completed before doing idle maintenance. + const connectionIdleMaintenanceMS = 2 * 1000; + + const name = "test_connection_idle_maintenance"; + const abc = "abcdefghijklmnopqrstuvwxyz"; + + // IndexedDB on Android does `PRAGMA auto_vacuum = FULL`, so the freelist + // pages are moved to the end of the database file and the database file is + // truncated to remove the freelist pages at every transaction commit. + if (mozinfo.os == "android") { + info("Test disabled on Android for now"); + return; + } + + info("Creating database"); + + let request = indexedDB.open(name, 1); + + let event = await expectingUpgrade(request); + + let database = event.target.result; + + let objectStore = database.createObjectStore(name); + + // Add lots of data... + for (let i = 0; i < 10000; i++) { + objectStore.add(abc, i); + } + + // And then clear it so that maintenance has some space to reclaim. + objectStore.clear(); + + await expectingSuccess(request); + + info("Getting database usage before maintenance"); + + let databaseUsageBeforeMaintenance = await new Promise(function (resolve) { + getCurrentUsage(function (request) { + resolve(request.result.databaseUsage); + }); + }); + + info("Waiting for maintenance to start"); + + // This time is a double of connectionIdleMaintenanceMS which should be + // pessimistic enough to work with randomly slowed down threads in the chaos + // mode. + await new Promise(function (resolve) { + do_timeout(2 * connectionIdleMaintenanceMS, resolve); + }); + + info("Waiting for maintenance to finish"); + + // This time is a double of connectionIdleMaintenanceMS which should be + // pessimistic enough to work with randomly slowed down threads in the chaos + // mode. + await new Promise(function (resolve) { + do_timeout(2 * connectionIdleMaintenanceMS, resolve); + }); + + info("Getting database usage after maintenance"); + + let databaseUsageAfterMaintenance = await new Promise(function (resolve) { + getCurrentUsage(function (request) { + resolve(request.result.databaseUsage); + }); + }); + + info( + "Database usage before: " + + databaseUsageBeforeMaintenance + + ". " + + "Database usage after: " + + databaseUsageAfterMaintenance + ); + + // Checkpointing done immediately after the maintenance can slightly decrease + // the usage even when the maintenance was not run at all. + ok( + databaseUsageBeforeMaintenance - databaseUsageAfterMaintenance >= + cosmologicalConstant, + "Maintenance significantly decreased database usage" + ); +} diff --git a/dom/indexedDB/test/unit/test_connection_idle_maintenance_stop.js b/dom/indexedDB/test/unit/test_connection_idle_maintenance_stop.js new file mode 100644 index 0000000000..33dc69b210 --- /dev/null +++ b/dom/indexedDB/test/unit/test_connection_idle_maintenance_stop.js @@ -0,0 +1,204 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* exported testSteps */ +async function testSteps() { + // A constant used to deal with small decrease in usage when transactions are + // transferred from the WAL file back into the original database, also called + // as checkpointing. + const cosmologicalConstant = 32768; + + // The maximum number of threads that can be used for database activity at a + // single time. + const maxConnectionThreadCount = 20; + + // The length of time that database connections will be held open after all + // transactions have completed before doing idle maintenance. + const connectionIdleMaintenanceMS = 2 * 1000; + + const name = "test_connection_idle_maintenance_stop"; + const abc = "abcdefghijklmnopqrstuvwxyz"; + + // IndexedDB on Android does `PRAGMA auto_vacuum = FULL`, so the freelist + // pages are moved to the end of the database file and the database file is + // truncated to remove the freelist pages at every transaction commit. + if (mozinfo.os == "android") { + info("Test disabled on Android for now"); + return; + } + + info("Setting pref"); + + Services.prefs.setIntPref( + "dom.indexedDB.connectionIdleMaintenance.pauseOnConnectionThreadMs", + 2 * connectionIdleMaintenanceMS + ); + + info("Forcing only one connection thread to be available"); + + let done = false; + + // Create databases which will continuously keep their connection threads + // busy. + const completePromises = await (async function () { + let promises = []; + + for (let index = 0; index < maxConnectionThreadCount - 1; index++) { + const request = indexedDB.open(name + "-" + index, 1); + + { + const event = await expectingUpgrade(request); + + const database = event.target.result; + + const objectStore = database.createObjectStore(name); + + objectStore.add("foo", 42); + } + + const event = await expectingSuccess(request); + + const database = event.target.result; + + const transaction = database.transaction(name); + + const objectStore = transaction.objectStore(name); + + function doWork() { + const request = objectStore.get(42); + request.onsuccess = function () { + if (!done) { + doWork(); + } + }; + } + + doWork(); + + const promise = new Promise(function (resolve) { + transaction.oncomplete = resolve; + }); + + promises.push(promise); + } + + return promises; + })(); + + info("Creating database A"); + + // Create a database which will be used for stopping of the connection idle + // maintenance. + const databaseA = await (async function () { + const request = indexedDB.open(name + "-a", 1); + + { + const event = await expectingUpgrade(request); + + const database = event.target.result; + + database.createObjectStore(name); + } + + const event = await expectingSuccess(request); + + const database = event.target.result; + + return database; + })(); + + info("Creating database B"); + + // Create a database for checking of the connection idle maintenance. + { + const request = indexedDB.open(name + "-b", 1); + + const event = await expectingUpgrade(request); + + const database = event.target.result; + + const objectStore = database.createObjectStore(name); + + // Add lots of data... + for (let index = 0; index < 10000; index++) { + objectStore.add(abc, index); + } + + // And then clear it so that maintenance has some space to reclaim. + objectStore.clear(); + + await expectingSuccess(request); + } + + info("Getting database usage before maintenance"); + + const databaseUsageBeforeMaintenance = await new Promise(function (resolve) { + getCurrentUsage(function (request) { + resolve(request.result.databaseUsage); + }); + }); + + info("Waiting for maintenance to start"); + + // This time is a double of connectionIdleMaintenanceMS which should be + // pessimistic enough to work with randomly slowed down threads in the + // chaos mode. + await new Promise(function (resolve) { + do_timeout(2 * connectionIdleMaintenanceMS, resolve); + }); + + info("Activating database A"); + + // Activate an open database which should trigger stopping of the connection + // idle maintenance of the database which had a lot of data. + { + const transaction = databaseA.transaction(name); + + const objectStore = transaction.objectStore(name); + + const request = objectStore.get(42); + + await requestSucceeded(request); + } + + info("Waiting for maintenance to finish"); + + // This time is a double of connectionIdleMaintenanceMS which should be + // pessimistic enough to work with randomly slowed down threads in the + // chaos mode. + await new Promise(function (resolve) { + do_timeout(2 * connectionIdleMaintenanceMS, resolve); + }); + + info("Getting database usage after maintenance"); + + const databaseUsageAfterMaintenance = await new Promise(function (resolve) { + getCurrentUsage(function (request) { + resolve(request.result.databaseUsage); + }); + }); + + info( + "Database usage before: " + + databaseUsageBeforeMaintenance + + ". " + + "Database usage after: " + + databaseUsageAfterMaintenance + ); + + // Checkpointing done immediately after the maintenance can slightly decrease + // the usage even when the maintenance was stopped very early. + ok( + databaseUsageBeforeMaintenance - databaseUsageAfterMaintenance < + cosmologicalConstant, + "Maintenance did not significantly decrease database usage" + ); + + done = true; + + info("Waiting for transactions to complete"); + + await Promise.all(completePromises); +} diff --git a/dom/indexedDB/test/unit/test_cursor_cycle.js b/dom/indexedDB/test/unit/test_cursor_cycle.js index 09099387f3..3c60c24238 100644 --- a/dom/indexedDB/test/unit/test_cursor_cycle.js +++ b/dom/indexedDB/test/unit/test_cursor_cycle.js @@ -34,7 +34,7 @@ function* testSteps() { let cursor = event.target.result; if (cursor) { let objectStore = event.target.transaction.objectStore("foo"); - objectStore.delete(Bob.ss).onsuccess = function (event) { + objectStore.delete(Bob.ss).onsuccess = function () { cursor.continue(); }; } diff --git a/dom/indexedDB/test/unit/test_cursor_mutation.js b/dom/indexedDB/test/unit/test_cursor_mutation.js index 6af7df5c9b..c948b8d6c9 100644 --- a/dom/indexedDB/test/unit/test_cursor_mutation.js +++ b/dom/indexedDB/test/unit/test_cursor_mutation.js @@ -101,10 +101,10 @@ function* testSteps() { if (count == 1) { let objectStore = event.target.transaction.objectStore("foo"); - objectStore.delete(objectStoreData[0].ss).onsuccess = function (event) { + objectStore.delete(objectStoreData[0].ss).onsuccess = function () { objectStore.add( objectStoreData[objectStoreData.length - 1] - ).onsuccess = function (event) { + ).onsuccess = function () { cursor.continue(); }; }; diff --git a/dom/indexedDB/test/unit/test_cursors.js b/dom/indexedDB/test/unit/test_cursors.js index 15e3d94355..84d0f082a8 100644 --- a/dom/indexedDB/test/unit/test_cursors.js +++ b/dom/indexedDB/test/unit/test_cursors.js @@ -77,7 +77,7 @@ function* testSteps() { for (let i in keys) { request = objectStore.add("foo", keys[i]); request.onerror = errorHandler; - request.onsuccess = function (event) { + request.onsuccess = function () { if (++keyIndex == keys.length) { testGenerator.next(); } @@ -233,7 +233,7 @@ function* testSteps() { if (keyIndex == 4) { request = cursor.update("bar"); request.onerror = errorHandler; - request.onsuccess = function (event) { + request.onsuccess = function () { keyIndex++; cursor.continue(); }; diff --git a/dom/indexedDB/test/unit/test_database_onclose.js b/dom/indexedDB/test/unit/test_database_onclose.js index 0162ffc3ab..8d24ad620b 100644 --- a/dom/indexedDB/test/unit/test_database_onclose.js +++ b/dom/indexedDB/test/unit/test_database_onclose.js @@ -104,7 +104,7 @@ function* testSteps() { let objectId = 0; while (true) { let addRequest = objectStore.add({ foo: "foo" }, objectId); - addRequest.onerror = function (event) { + addRequest.onerror = function () { info("addRequest.onerror, objectId: " + objectId); txn.onerror = grabEventAndContinueHandler; testGenerator.next(true); @@ -200,7 +200,7 @@ function* testSteps() { let numberOfReadObjects = 0; let readRequest = objectStore.openCursor(); - readRequest.onerror = function (event) { + readRequest.onerror = function () { info("readRequest.onerror, numberOfReadObjects: " + numberOfReadObjects); testGenerator.next(true); }; diff --git a/dom/indexedDB/test/unit/test_getAll.js b/dom/indexedDB/test/unit/test_getAll.js index 6ada30d845..b8c3e6854a 100644 --- a/dom/indexedDB/test/unit/test_getAll.js +++ b/dom/indexedDB/test/unit/test_getAll.js @@ -33,7 +33,7 @@ function* testSteps() { for (let i in values) { request = objectStore.add(values[i]); request.onerror = errorHandler; - request.onsuccess = function (event) { + request.onsuccess = function () { if (++addedCount == values.length) { executeSoon(function () { testGenerator.next(); diff --git a/dom/indexedDB/test/unit/test_index_object_cursors.js b/dom/indexedDB/test/unit/test_index_object_cursors.js index 850e1c6007..992fe9e0e3 100644 --- a/dom/indexedDB/test/unit/test_index_object_cursors.js +++ b/dom/indexedDB/test/unit/test_index_object_cursors.js @@ -102,7 +102,7 @@ function* testSteps() { let obj = cursor.value; obj.updated = true; - cursor.update(obj).onsuccess = function (event) { + cursor.update(obj).onsuccess = function () { ok(true, "Object updated"); cursor.continue(); keyIndex++; @@ -110,7 +110,7 @@ function* testSteps() { return; } - cursor.delete().onsuccess = function (event) { + cursor.delete().onsuccess = function () { ok(true, "Object deleted"); cursor.continue(); keyIndex++; diff --git a/dom/indexedDB/test/unit/test_index_update_delete.js b/dom/indexedDB/test/unit/test_index_update_delete.js index da43feb3b9..df6d3d86f4 100644 --- a/dom/indexedDB/test/unit/test_index_update_delete.js +++ b/dom/indexedDB/test/unit/test_index_update_delete.js @@ -73,7 +73,7 @@ function* testSteps() { is(cursor.key, modifiedEntry, "Correct key"); cursor.value.index = unique ? 30 : 35; - cursor.update(cursor.value).onsuccess = function (event) { + cursor.update(cursor.value).onsuccess = function () { cursor.continue(); }; } else { @@ -106,7 +106,7 @@ function* testSteps() { is(cursor.key, modifiedEntry, "Correct key"); delete cursor.value.index; - cursor.update(cursor.value).onsuccess = function (event) { + cursor.update(cursor.value).onsuccess = function () { indexCount--; cursor.continue(); }; diff --git a/dom/indexedDB/test/unit/test_indexes_bad_values.js b/dom/indexedDB/test/unit/test_indexes_bad_values.js index c695490f74..d8426d60cc 100644 --- a/dom/indexedDB/test/unit/test_indexes_bad_values.js +++ b/dom/indexedDB/test/unit/test_indexes_bad_values.js @@ -74,7 +74,7 @@ function* testSteps() { badObjectStoreData[i].key ); request.onerror = errorHandler; - request.onsuccess = function (event) { + request.onsuccess = function () { if (++addedData == badObjectStoreData.length) { executeSoon(function () { testGenerator.next(); diff --git a/dom/indexedDB/test/unit/test_invalid_version.js b/dom/indexedDB/test/unit/test_invalid_version.js index 79d74ab2cc..ea5e2953d0 100644 --- a/dom/indexedDB/test/unit/test_invalid_version.js +++ b/dom/indexedDB/test/unit/test_invalid_version.js @@ -6,6 +6,7 @@ /* exported testGenerator */ var testGenerator = testSteps(); +// eslint-disable-next-line require-yield function* testSteps() { const name = this.window ? window.location.pathname : "Splendid Test"; diff --git a/dom/indexedDB/test/unit/test_quotaExceeded_recovery.js b/dom/indexedDB/test/unit/test_quotaExceeded_recovery.js index 20366be417..3f5ef96ba4 100644 --- a/dom/indexedDB/test/unit/test_quotaExceeded_recovery.js +++ b/dom/indexedDB/test/unit/test_quotaExceeded_recovery.js @@ -82,14 +82,14 @@ function* testSteps() { event.stopPropagation(); }; - trans.oncomplete = function (event) { + trans.oncomplete = function () { if (iter == 1) { i++; } j++; testGenerator.next(true); }; - trans.onabort = function (event) { + trans.onabort = function () { is(trans.error.name, "QuotaExceededError", "Reached quota limit"); testGenerator.next(false); }; diff --git a/dom/indexedDB/test/unit/test_remove_objectStore.js b/dom/indexedDB/test/unit/test_remove_objectStore.js index bdc16d9a6a..8d4cd17246 100644 --- a/dom/indexedDB/test/unit/test_remove_objectStore.js +++ b/dom/indexedDB/test/unit/test_remove_objectStore.js @@ -28,7 +28,7 @@ function* testSteps() { for (let i = 0; i < 100; i++) { request = objectStore.add({ foo: i }); request.onerror = errorHandler; - request.onsuccess = function (event) { + request.onsuccess = function () { if (++addedCount == 100) { executeSoon(function () { testGenerator.next(); diff --git a/dom/indexedDB/test/unit/test_setVersion_throw.js b/dom/indexedDB/test/unit/test_setVersion_throw.js index 2706c2c2a4..b0b5392ba2 100644 --- a/dom/indexedDB/test/unit/test_setVersion_throw.js +++ b/dom/indexedDB/test/unit/test_setVersion_throw.js @@ -17,7 +17,7 @@ function* testSteps() { let request = indexedDB.open(name, 1); request.onerror = errorHandler; request.onsuccess = grabEventAndContinueHandler; - request.onupgradeneeded = function (event) { + request.onupgradeneeded = function () { info("Got upgradeneeded event for db 1"); }; let event = yield undefined; @@ -36,7 +36,7 @@ function* testSteps() { request = indexedDB.open(name, 2); request.onerror = grabEventAndContinueHandler; request.onsuccess = unexpectedSuccessHandler; - request.onupgradeneeded = function (event) { + request.onupgradeneeded = function () { info("Got upgradeneeded event for db 2"); expectUncaughtException(true); // eslint-disable-next-line no-undef diff --git a/dom/indexedDB/test/unit/test_table_locks.js b/dom/indexedDB/test/unit/test_table_locks.js index e1f3b5e7d6..3363520775 100644 --- a/dom/indexedDB/test/unit/test_table_locks.js +++ b/dom/indexedDB/test/unit/test_table_locks.js @@ -81,7 +81,7 @@ function doReadOnlyTransaction(db, key, remaining) { let cursor = event.target.result; ok(cursor, "Got readonly cursor"); - objectStore.get(cursor.primaryKey).onsuccess = function (event) { + objectStore.get(cursor.primaryKey).onsuccess = function () { if (++key == objDataCount) { key = 0; } @@ -113,7 +113,7 @@ function doReadWriteTransaction(db, key, remaining) { let value = cursor.value; value[idxKeyPathProp]++; - cursor.update(value).onsuccess = function (event) { + cursor.update(value).onsuccess = function () { if (++key == objDataCount) { key = 0; } diff --git a/dom/indexedDB/test/unit/test_transaction_abort.js b/dom/indexedDB/test/unit/test_transaction_abort.js index 6829392842..48f3677e0d 100644 --- a/dom/indexedDB/test/unit/test_transaction_abort.js +++ b/dom/indexedDB/test/unit/test_transaction_abort.js @@ -150,7 +150,7 @@ function* testSteps() { request.onsuccess = grabEventAndContinueHandler; event = yield undefined; - event.target.transaction.onabort = function (event) { + event.target.transaction.onabort = function () { ok(false, "Shouldn't see an abort event!"); }; event.target.transaction.oncomplete = grabEventAndContinueHandler; @@ -168,7 +168,7 @@ function* testSteps() { key = event.target.result; event.target.transaction.onabort = grabEventAndContinueHandler; - event.target.transaction.oncomplete = function (event) { + event.target.transaction.oncomplete = function () { ok(false, "Shouldn't see a complete event here!"); }; @@ -303,7 +303,7 @@ function* testSteps() { r.onerror = abortErrorHandler; } makeNewRequest(); - transaction.objectStore("foo").get(1).onsuccess = function (event) { + transaction.objectStore("foo").get(1).onsuccess = function () { executeSoon(function () { transaction.abort(); expectedAbortEventCount++; @@ -315,7 +315,7 @@ function* testSteps() { // During COMMITTING transaction = db.transaction("foo", "readwrite"); transaction.objectStore("foo").put({ hello: "world" }, 1).onsuccess = - function (event) { + function () { continueToNextStep(); }; yield undefined; @@ -335,11 +335,10 @@ function* testSteps() { // Abort both failing and succeeding requests transaction = db.transaction("foo", "readwrite"); transaction.onabort = transaction.oncomplete = grabEventAndContinueHandler; - transaction.objectStore("foo").add({ indexKey: "key" }).onsuccess = function ( - event - ) { - transaction.abort(); - }; + transaction.objectStore("foo").add({ indexKey: "key" }).onsuccess = + function () { + transaction.abort(); + }; let request1 = transaction.objectStore("foo").add({ indexKey: "key" }); request1.onsuccess = grabEventAndContinueHandler; request1.onerror = grabEventAndContinueHandler; diff --git a/dom/indexedDB/test/unit/test_transaction_abort_hang.js b/dom/indexedDB/test/unit/test_transaction_abort_hang.js index 6a2c61128b..cb7e4f7133 100644 --- a/dom/indexedDB/test/unit/test_transaction_abort_hang.js +++ b/dom/indexedDB/test/unit/test_transaction_abort_hang.js @@ -47,7 +47,7 @@ function* testSteps() { // Last one, finish the test. transaction.oncomplete = grabEventAndContinueHandler; } else if (i == abortedTransactionIndex - 1) { - transaction.oncomplete = function (event) { + transaction.oncomplete = function () { ok( true, "Completed transaction " + @@ -84,7 +84,7 @@ function* testSteps() { transaction.abort(); }); } else { - transaction.oncomplete = function (event) { + transaction.oncomplete = function () { ok(true, "Completed transaction " + ++completedTransactionCount); }; } diff --git a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js index f297b72d25..f6bd2608ef 100644 --- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js +++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js @@ -28,7 +28,7 @@ function isnot(a, b, msg) { Assert.notEqual(a, b, msg); } -function todo(condition, name, diag) { +function todo(condition) { todo_check_true(condition); } @@ -122,7 +122,7 @@ function expectedErrorHandler(name) { }; } -function expectUncaughtException(expecting) { +function expectUncaughtException() { // This is dummy for xpcshell test. } @@ -196,19 +196,19 @@ function compareKeys(k1, k2) { return false; } -function addPermission(permission, url) { +function addPermission() { throw new Error("addPermission"); } -function removePermission(permission, url) { +function removePermission() { throw new Error("removePermission"); } -function allowIndexedDB(url) { +function allowIndexedDB() { throw new Error("allowIndexedDB"); } -function disallowIndexedDB(url) { +function disallowIndexedDB() { throw new Error("disallowIndexedDB"); } @@ -240,7 +240,7 @@ function scheduleGC() { function setTimeout(fun, timeout) { let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); var event = { - notify(timer) { + notify() { fun(); }, }; diff --git a/dom/indexedDB/test/unit/xpcshell-parent-process.toml b/dom/indexedDB/test/unit/xpcshell-parent-process.toml index d63e3d6bf2..01740cdd82 100644 --- a/dom/indexedDB/test/unit/xpcshell-parent-process.toml +++ b/dom/indexedDB/test/unit/xpcshell-parent-process.toml @@ -44,6 +44,10 @@ skip-if = ["true"] # Only used for recreating URLSearchParams_profile.zip requesttimeoutfactor = 2 skip-if = ["tsan"] +["test_connection_idle_maintenance.js"] + +["test_connection_idle_maintenance_stop.js"] + ["test_database_close_without_onclose.js"] ["test_database_onclose.js"] |