2010-06-23 23:46:08 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2015-05-03 22:32:37 +03:00
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2010-06-28 20:46:49 +04:00
|
|
|
#include "IDBDatabase.h"
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "FileInfo.h"
|
2010-06-23 23:46:08 +04:00
|
|
|
#include "IDBEvents.h"
|
2012-08-30 04:50:28 +04:00
|
|
|
#include "IDBFactory.h"
|
2010-10-19 21:58:52 +04:00
|
|
|
#include "IDBIndex.h"
|
2014-06-12 07:35:29 +04:00
|
|
|
#include "IDBMutableFile.h"
|
2010-06-28 22:51:06 +04:00
|
|
|
#include "IDBObjectStore.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "IDBRequest.h"
|
2010-06-28 20:46:21 +04:00
|
|
|
#include "IDBTransaction.h"
|
2010-06-28 20:44:30 +04:00
|
|
|
#include "IDBFactory.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "IndexedDatabaseManager.h"
|
|
|
|
#include "mozilla/ErrorResult.h"
|
|
|
|
#include "mozilla/EventDispatcher.h"
|
|
|
|
#include "MainThreadUtils.h"
|
|
|
|
#include "mozilla/Services.h"
|
|
|
|
#include "mozilla/storage.h"
|
|
|
|
#include "mozilla/dom/BindingDeclarations.h"
|
|
|
|
#include "mozilla/dom/DOMStringListBinding.h"
|
2015-01-26 09:30:09 +03:00
|
|
|
#include "mozilla/dom/Exceptions.h"
|
2014-10-08 20:15:23 +04:00
|
|
|
#include "mozilla/dom/File.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/dom/IDBDatabaseBinding.h"
|
|
|
|
#include "mozilla/dom/IDBObjectStoreBinding.h"
|
|
|
|
#include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseFileChild.h"
|
|
|
|
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
|
2017-05-23 08:50:33 +03:00
|
|
|
#include "mozilla/dom/IPCBlobUtils.h"
|
|
|
|
#include "mozilla/dom/quota/QuotaManager.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/ipc/BackgroundChild.h"
|
|
|
|
#include "mozilla/ipc/BackgroundUtils.h"
|
|
|
|
#include "mozilla/ipc/FileDescriptor.h"
|
|
|
|
#include "mozilla/ipc/InputStreamParams.h"
|
|
|
|
#include "mozilla/ipc/InputStreamUtils.h"
|
2016-06-07 23:10:18 +03:00
|
|
|
#include "nsAutoPtr.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "nsCOMPtr.h"
|
2019-01-02 16:05:23 +03:00
|
|
|
#include "mozilla/dom/Document.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "nsIObserver.h"
|
|
|
|
#include "nsIObserverService.h"
|
2014-11-14 05:20:38 +03:00
|
|
|
#include "nsIScriptError.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "nsISupportsPrimitives.h"
|
|
|
|
#include "nsThreadUtils.h"
|
2018-10-31 23:39:03 +03:00
|
|
|
#include "nsIWeakReferenceUtils.h"
|
2013-03-16 10:58:50 +04:00
|
|
|
#include "ProfilerHelpers.h"
|
2014-01-28 04:37:05 +04:00
|
|
|
#include "ReportInternalError.h"
|
2016-03-16 10:12:17 +03:00
|
|
|
#include "ScriptErrorHelper.h"
|
2015-04-15 19:47:03 +03:00
|
|
|
#include "nsQueryObject.h"
|
2012-06-01 21:21:12 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// Include this last to avoid path problems on Windows.
|
|
|
|
#include "ActorsChild.h"
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
2013-05-18 05:48:25 +04:00
|
|
|
|
2017-06-07 13:36:20 +03:00
|
|
|
using namespace mozilla::dom::indexedDB;
|
2014-09-27 03:21:57 +04:00
|
|
|
using namespace mozilla::dom::quota;
|
|
|
|
using namespace mozilla::ipc;
|
|
|
|
using namespace mozilla::services;
|
2010-06-23 23:46:08 +04:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const char kCycleCollectionObserverTopic[] = "cycle-collector-end";
|
|
|
|
const char kMemoryPressureObserverTopic[] = "memory-pressure";
|
|
|
|
const char kWindowObserverTopic[] = "inner-window-destroyed";
|
2012-06-01 21:21:12 +04:00
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
class CancelableRunnableWrapper final : public CancelableRunnable {
|
2014-12-17 09:26:15 +03:00
|
|
|
nsCOMPtr<nsIRunnable> mRunnable;
|
|
|
|
|
|
|
|
public:
|
2017-06-12 22:34:10 +03:00
|
|
|
explicit CancelableRunnableWrapper(nsIRunnable* aRunnable)
|
|
|
|
: CancelableRunnable("dom::CancelableRunnableWrapper"),
|
|
|
|
mRunnable(aRunnable) {
|
2014-12-17 09:26:15 +03:00
|
|
|
MOZ_ASSERT(aRunnable);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2019-11-08 16:22:28 +03:00
|
|
|
~CancelableRunnableWrapper() = default;
|
2014-12-17 09:26:15 +03:00
|
|
|
|
|
|
|
NS_DECL_NSIRUNNABLE
|
2016-04-11 21:40:06 +03:00
|
|
|
nsresult Cancel() override;
|
2014-12-17 09:26:15 +03:00
|
|
|
};
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
class DatabaseFile final : public PBackgroundIDBDatabaseFileChild {
|
|
|
|
IDBDatabase* mDatabase;
|
2010-10-19 21:58:52 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
public:
|
|
|
|
explicit DatabaseFile(IDBDatabase* aDatabase) : mDatabase(aDatabase) {
|
|
|
|
MOZ_ASSERT(aDatabase);
|
|
|
|
aDatabase->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
MOZ_COUNT_CTOR(DatabaseFile);
|
2010-10-19 21:58:52 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
private:
|
|
|
|
~DatabaseFile() {
|
|
|
|
MOZ_ASSERT(!mDatabase);
|
|
|
|
|
|
|
|
MOZ_COUNT_DTOR(DatabaseFile);
|
2014-09-13 20:12:19 +04:00
|
|
|
}
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
virtual void ActorDestroy(ActorDestroyReason aWhy) override {
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(mDatabase);
|
|
|
|
mDatabase->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (aWhy != Deletion) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IDBDatabase> database = mDatabase;
|
2014-09-27 03:21:57 +04:00
|
|
|
database->NoteFinishedFileActor(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
mDatabase = nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
2010-10-19 21:58:52 +04:00
|
|
|
};
|
|
|
|
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
class IDBDatabase::Observer final : public nsIObserver {
|
2014-09-27 03:21:57 +04:00
|
|
|
IDBDatabase* mWeakDatabase;
|
|
|
|
const uint64_t mWindowId;
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
public:
|
|
|
|
Observer(IDBDatabase* aDatabase, uint64_t aWindowId)
|
|
|
|
: mWeakDatabase(aDatabase), mWindowId(aWindowId) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(aDatabase);
|
|
|
|
}
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void Revoke() {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2010-09-10 23:12:11 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mWeakDatabase = nullptr;
|
|
|
|
}
|
2013-03-26 15:13:17 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_DECL_ISUPPORTS
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
private:
|
|
|
|
~Observer() {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(!mWeakDatabase);
|
2010-09-10 23:12:11 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
};
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
IDBDatabase::IDBDatabase(IDBOpenDBRequest* aRequest, IDBFactory* aFactory,
|
2014-09-27 03:21:57 +04:00
|
|
|
BackgroundDatabaseChild* aActor, DatabaseSpec* aSpec)
|
2019-03-29 21:05:11 +03:00
|
|
|
: DOMEventTargetHelper(aRequest),
|
2014-09-27 03:21:57 +04:00
|
|
|
mFactory(aFactory),
|
|
|
|
mSpec(aSpec),
|
|
|
|
mBackgroundActor(aActor),
|
2015-09-09 14:15:05 +03:00
|
|
|
mFileHandleDisabled(aRequest->IsFileHandleDisabled()),
|
2014-09-27 03:21:57 +04:00
|
|
|
mClosed(false),
|
|
|
|
mInvalidated(false),
|
2016-04-21 07:53:30 +03:00
|
|
|
mQuotaExceeded(false),
|
2017-06-16 14:06:36 +03:00
|
|
|
mIncreasedActiveDatabaseCount(false) {
|
2015-09-09 14:15:05 +03:00
|
|
|
MOZ_ASSERT(aRequest);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aFactory);
|
|
|
|
aFactory->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
MOZ_ASSERT(aSpec);
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
|
|
|
|
2010-06-28 20:46:49 +04:00
|
|
|
IDBDatabase::~IDBDatabase() {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(!mBackgroundActor);
|
2017-06-16 14:06:36 +03:00
|
|
|
MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
|
2013-07-09 21:30:58 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// static
|
|
|
|
already_AddRefed<IDBDatabase> IDBDatabase::Create(
|
2015-09-09 14:15:05 +03:00
|
|
|
IDBOpenDBRequest* aRequest, IDBFactory* aFactory,
|
2014-09-27 03:21:57 +04:00
|
|
|
BackgroundDatabaseChild* aActor, DatabaseSpec* aSpec) {
|
2015-09-09 14:15:05 +03:00
|
|
|
MOZ_ASSERT(aRequest);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aFactory);
|
|
|
|
aFactory->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
MOZ_ASSERT(aSpec);
|
2010-09-10 23:12:11 +04:00
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
RefPtr<IDBDatabase> db = new IDBDatabase(aRequest, aFactory, aActor, aSpec);
|
2012-06-01 21:21:12 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (NS_IsMainThread()) {
|
2019-03-29 21:05:11 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window =
|
|
|
|
do_QueryInterface(aFactory->GetParentObject());
|
|
|
|
if (window) {
|
2014-09-27 03:21:57 +04:00
|
|
|
uint64_t windowId = window->WindowID();
|
2012-06-20 05:50:39 +04:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Observer> observer = new Observer(db, windowId);
|
2010-10-19 21:58:52 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIObserverService> obsSvc = GetObserverService();
|
|
|
|
MOZ_ASSERT(obsSvc);
|
2010-09-10 23:12:11 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// This topic must be successfully registered.
|
2017-06-16 14:06:36 +03:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(
|
|
|
|
obsSvc->AddObserver(observer, kWindowObserverTopic, false));
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// These topics are not crucial.
|
|
|
|
if (NS_FAILED(obsSvc->AddObserver(observer, kCycleCollectionObserverTopic,
|
|
|
|
false)) ||
|
|
|
|
NS_FAILED(obsSvc->AddObserver(observer, kMemoryPressureObserverTopic,
|
|
|
|
false))) {
|
|
|
|
NS_WARNING("Failed to add additional memory observers!");
|
|
|
|
}
|
2012-10-23 20:31:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
db->mObserver.swap(observer);
|
|
|
|
}
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
2012-10-05 23:09:33 +04:00
|
|
|
|
2017-06-16 14:06:36 +03:00
|
|
|
db->IncreaseActiveDatabaseCount();
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return db.forget();
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
void IDBDatabase::AssertIsOnOwningThread() const {
|
|
|
|
MOZ_ASSERT(mFactory);
|
|
|
|
mFactory->AssertIsOnOwningThread();
|
2014-09-18 03:36:01 +04:00
|
|
|
}
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
#endif // DEBUG
|
|
|
|
|
2017-01-13 11:40:58 +03:00
|
|
|
nsIEventTarget* IDBDatabase::EventTarget() const {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
return Factory()->EventTarget();
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::CloseInternal() {
|
|
|
|
AssertIsOnOwningThread();
|
2010-10-19 21:58:52 +04:00
|
|
|
|
|
|
|
if (!mClosed) {
|
2012-08-10 05:06:21 +04:00
|
|
|
mClosed = true;
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
ExpireFileActors(/* aExpireAll */ true);
|
|
|
|
|
|
|
|
if (mObserver) {
|
|
|
|
mObserver->Revoke();
|
2011-11-08 04:15:45 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsCOMPtr<nsIObserverService> obsSvc = GetObserverService();
|
|
|
|
if (obsSvc) {
|
|
|
|
// These might not have been registered.
|
|
|
|
obsSvc->RemoveObserver(mObserver, kCycleCollectionObserverTopic);
|
|
|
|
obsSvc->RemoveObserver(mObserver, kMemoryPressureObserverTopic);
|
|
|
|
|
2016-03-28 20:28:15 +03:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(
|
|
|
|
obsSvc->RemoveObserver(mObserver, kWindowObserverTopic));
|
2011-11-08 04:15:45 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mObserver = nullptr;
|
2010-10-19 21:58:52 +04:00
|
|
|
}
|
2012-06-01 21:21:12 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mBackgroundActor && !mInvalidated) {
|
|
|
|
mBackgroundActor->SendClose();
|
2012-06-01 21:21:12 +04:00
|
|
|
}
|
2017-06-16 14:06:36 +03:00
|
|
|
|
|
|
|
// Decrease the number of active databases right after the database is
|
|
|
|
// closed.
|
|
|
|
MaybeDecreaseActiveDatabaseCount();
|
2010-10-19 21:58:52 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::InvalidateInternal() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
InvalidateMutableFiles();
|
2014-11-14 05:20:38 +03:00
|
|
|
AbortTransactions(/* aShouldWarn */ true);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
CloseInternal();
|
2010-10-19 21:58:52 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::EnterSetVersionTransaction(uint64_t aNewVersion) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aNewVersion);
|
|
|
|
MOZ_ASSERT(!RunningVersionChangeTransaction());
|
|
|
|
MOZ_ASSERT(mSpec);
|
|
|
|
MOZ_ASSERT(!mPreviousSpec);
|
2012-06-29 20:48:34 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mPreviousSpec = new DatabaseSpec(*mSpec);
|
2012-06-29 20:48:34 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mSpec->metadata().version() = aNewVersion;
|
2011-10-25 16:49:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void IDBDatabase::ExitSetVersionTransaction() {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mPreviousSpec) {
|
|
|
|
mPreviousSpec = nullptr;
|
|
|
|
}
|
2011-10-25 16:49:31 +04:00
|
|
|
}
|
|
|
|
|
2012-06-29 20:48:34 +04:00
|
|
|
void IDBDatabase::RevertToPreviousState() {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(RunningVersionChangeTransaction());
|
|
|
|
MOZ_ASSERT(mPreviousSpec);
|
2012-06-29 20:48:34 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// Hold the current spec alive until RefreshTransactionsSpecEnumerator has
|
|
|
|
// finished!
|
2019-12-13 15:18:21 +03:00
|
|
|
auto currentSpec = std::move(mSpec);
|
2010-10-19 21:58:52 +04:00
|
|
|
|
2019-12-13 15:18:21 +03:00
|
|
|
mSpec = std::move(mPreviousSpec);
|
2014-09-18 03:36:01 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
RefreshSpec(/* aMayDelete */ true);
|
2010-10-19 21:58:52 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::RefreshSpec(bool aMayDelete) {
|
|
|
|
AssertIsOnOwningThread();
|
2012-06-01 21:21:12 +04:00
|
|
|
|
2015-07-21 04:48:54 +03:00
|
|
|
for (auto iter = mTransactions.Iter(); !iter.Done(); iter.Next()) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IDBTransaction> transaction = iter.Get()->GetKey();
|
2015-07-21 04:48:54 +03:00
|
|
|
MOZ_ASSERT(transaction);
|
|
|
|
transaction->AssertIsOnOwningThread();
|
|
|
|
transaction->RefreshSpec(aMayDelete);
|
|
|
|
}
|
2014-09-13 20:12:19 +04:00
|
|
|
}
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const nsString& IDBDatabase::Name() const {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mSpec);
|
|
|
|
|
|
|
|
return mSpec->metadata().name();
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
|
|
|
|
2013-07-31 19:48:46 +04:00
|
|
|
uint64_t IDBDatabase::Version() const {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mSpec);
|
|
|
|
|
|
|
|
return mSpec->metadata().version();
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
already_AddRefed<DOMStringList> IDBDatabase::ObjectStoreNames() const {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mSpec);
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2019-11-28 23:24:33 +03:00
|
|
|
return CreateSortedDOMStringList(
|
|
|
|
mSpec->objectStores(),
|
|
|
|
[](const auto& objectStore) { return objectStore.metadata().name(); });
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
already_AddRefed<Document> IDBDatabase::GetOwnerDocument() const {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsPIDOMWindowInner* window = GetOwner()) {
|
2019-01-02 16:05:23 +03:00
|
|
|
nsCOMPtr<Document> doc = window->GetExtantDoc();
|
2014-09-27 03:21:57 +04:00
|
|
|
return doc.forget();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2013-07-31 19:48:46 +04:00
|
|
|
already_AddRefed<IDBObjectStore> IDBDatabase::CreateObjectStore(
|
|
|
|
const nsAString& aName, const IDBObjectStoreParameters& aOptionalParameters,
|
|
|
|
ErrorResult& aRv) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
IDBTransaction* transaction = IDBTransaction::GetCurrent();
|
2015-02-07 02:25:33 +03:00
|
|
|
if (!transaction || transaction->Database() != this ||
|
2019-11-27 13:54:57 +03:00
|
|
|
transaction->GetMode() != IDBTransaction::Mode::VersionChange) {
|
2013-07-31 19:48:46 +04:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
|
|
|
|
return nullptr;
|
2010-11-11 02:25:44 +03:00
|
|
|
}
|
|
|
|
|
2019-11-28 19:00:29 +03:00
|
|
|
if (!transaction->CanAcceptRequests()) {
|
2015-06-20 19:09:27 +03:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2013-05-18 05:48:25 +04:00
|
|
|
KeyPath keyPath(0);
|
2014-12-11 21:07:44 +03:00
|
|
|
if (NS_FAILED(KeyPath::Parse(aOptionalParameters.mKeyPath, &keyPath))) {
|
2013-07-31 19:48:46 +04:00
|
|
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
|
|
|
return nullptr;
|
2010-12-21 19:02:01 +03:00
|
|
|
}
|
|
|
|
|
2019-11-20 18:18:33 +03:00
|
|
|
auto& objectStores = mSpec->objectStores();
|
|
|
|
const auto end = objectStores.cend();
|
|
|
|
const auto foundIt = std::find_if(
|
|
|
|
objectStores.cbegin(), end, [&aName](const auto& objectStore) {
|
|
|
|
return aName == objectStore.metadata().name();
|
|
|
|
});
|
|
|
|
if (foundIt != end) {
|
|
|
|
aRv.ThrowDOMException(
|
|
|
|
NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR,
|
|
|
|
nsPrintfCString("Object store named '%s' already exists at index '%zu'",
|
|
|
|
NS_ConvertUTF16toUTF8(aName).get(),
|
|
|
|
foundIt.GetIndex()));
|
|
|
|
return nullptr;
|
2011-12-04 21:39:01 +04:00
|
|
|
}
|
|
|
|
|
2013-07-31 19:48:46 +04:00
|
|
|
if (!keyPath.IsAllowedForObjectStore(aOptionalParameters.mAutoIncrement)) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
|
|
|
return nullptr;
|
2011-11-21 18:56:24 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const ObjectStoreSpec* oldSpecElements =
|
|
|
|
objectStores.IsEmpty() ? nullptr : objectStores.Elements();
|
|
|
|
|
|
|
|
ObjectStoreSpec* newSpec = objectStores.AppendElement();
|
|
|
|
newSpec->metadata() =
|
|
|
|
ObjectStoreMetadata(transaction->NextObjectStoreId(), nsString(aName),
|
|
|
|
keyPath, aOptionalParameters.mAutoIncrement);
|
2010-10-19 21:58:52 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (oldSpecElements && oldSpecElements != objectStores.Elements()) {
|
|
|
|
MOZ_ASSERT(objectStores.Length() > 1);
|
|
|
|
|
|
|
|
// Array got moved, update the spec pointers for all live objectStores and
|
|
|
|
// indexes.
|
|
|
|
RefreshSpec(/* aMayDelete */ false);
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<IDBObjectStore> objectStore = transaction->CreateObjectStore(*newSpec);
|
|
|
|
MOZ_ASSERT(objectStore);
|
|
|
|
|
2014-10-16 08:56:52 +04:00
|
|
|
// Don't do this in the macro because we always need to increment the serial
|
|
|
|
// number to keep in sync with the parent.
|
|
|
|
const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
|
|
|
|
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
2014-10-16 08:56:52 +04:00
|
|
|
"database(%s).transaction(%s).createObjectStore(%s)",
|
2019-09-27 13:11:45 +03:00
|
|
|
"IDBDatabase.createObjectStore()", transaction->LoggingSerialNumber(),
|
2014-10-16 08:56:52 +04:00
|
|
|
requestSerialNumber, IDB_LOG_STRINGIFY(this),
|
|
|
|
IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(objectStore));
|
2010-10-19 21:58:52 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return objectStore.forget();
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
|
|
|
|
2013-07-31 19:48:46 +04:00
|
|
|
void IDBDatabase::DeleteObjectStore(const nsAString& aName, ErrorResult& aRv) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
IDBTransaction* transaction = IDBTransaction::GetCurrent();
|
2015-02-07 02:25:33 +03:00
|
|
|
if (!transaction || transaction->Database() != this ||
|
2019-11-27 13:54:57 +03:00
|
|
|
transaction->GetMode() != IDBTransaction::Mode::VersionChange) {
|
2013-07-31 19:48:46 +04:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
|
|
|
|
return;
|
2010-11-11 02:25:44 +03:00
|
|
|
}
|
|
|
|
|
2019-11-28 19:00:29 +03:00
|
|
|
if (!transaction->CanAcceptRequests()) {
|
2015-06-20 19:09:27 +03:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2019-11-21 14:01:55 +03:00
|
|
|
auto& specArray = mSpec->objectStores();
|
|
|
|
const auto end = specArray.end();
|
|
|
|
const auto foundIt =
|
|
|
|
std::find_if(specArray.begin(), end, [&aName](const auto& objectStore) {
|
|
|
|
const ObjectStoreMetadata& metadata = objectStore.metadata();
|
|
|
|
MOZ_ASSERT(metadata.id());
|
|
|
|
|
|
|
|
return aName == metadata.name();
|
|
|
|
});
|
2012-06-01 21:21:12 +04:00
|
|
|
|
2019-11-21 14:01:55 +03:00
|
|
|
if (foundIt == end) {
|
2014-09-27 03:21:57 +04:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR);
|
|
|
|
return;
|
2012-06-01 21:21:12 +04:00
|
|
|
}
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2019-11-21 14:01:55 +03:00
|
|
|
// Must do this before altering the metadata array!
|
|
|
|
transaction->DeleteObjectStore(foundIt->metadata().id());
|
|
|
|
|
|
|
|
specArray.RemoveElementAt(foundIt);
|
|
|
|
RefreshSpec(/* aMayDelete */ false);
|
|
|
|
|
2014-10-16 08:56:52 +04:00
|
|
|
// Don't do this in the macro because we always need to increment the serial
|
|
|
|
// number to keep in sync with the parent.
|
|
|
|
const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
|
|
|
|
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
|
2014-10-16 08:56:52 +04:00
|
|
|
"database(%s).transaction(%s).deleteObjectStore(\"%s\")",
|
2019-09-27 13:11:45 +03:00
|
|
|
"IDBDatabase.deleteObjectStore()", transaction->LoggingSerialNumber(),
|
2014-10-16 08:56:52 +04:00
|
|
|
requestSerialNumber, IDB_LOG_STRINGIFY(this),
|
|
|
|
IDB_LOG_STRINGIFY(transaction), NS_ConvertUTF16toUTF8(aName).get());
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
already_AddRefed<IDBTransaction> IDBDatabase::Transaction(
|
2016-03-23 18:02:57 +03:00
|
|
|
JSContext* aCx, const StringOrStringSequence& aStoreNames,
|
2014-09-27 03:21:57 +04:00
|
|
|
IDBTransactionMode aMode, ErrorResult& aRv) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2016-03-15 09:00:37 +03:00
|
|
|
if ((aMode == IDBTransactionMode::Readwriteflush ||
|
|
|
|
aMode == IDBTransactionMode::Cleanup) &&
|
2015-01-26 09:30:09 +03:00
|
|
|
!IndexedDatabaseManager::ExperimentalFeaturesEnabled()) {
|
|
|
|
// Pretend that this mode doesn't exist. We don't have a way to annotate
|
|
|
|
// certain enum values as depending on preferences so we just duplicate the
|
|
|
|
// normal exception generation here.
|
2016-03-23 18:02:57 +03:00
|
|
|
aRv.ThrowTypeError<MSG_INVALID_ENUM_VALUE>(
|
|
|
|
NS_LITERAL_STRING("Argument 2 of IDBDatabase.transaction"),
|
|
|
|
NS_LITERAL_STRING("readwriteflush"),
|
|
|
|
NS_LITERAL_STRING("IDBTransactionMode"));
|
2015-01-26 09:30:09 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IDBTransaction> transaction;
|
2016-03-23 18:02:57 +03:00
|
|
|
aRv = Transaction(aCx, aStoreNames, aMode, getter_AddRefs(transaction));
|
2015-01-26 09:30:09 +03:00
|
|
|
if (NS_WARN_IF(aRv.Failed())) {
|
2014-09-27 03:21:57 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-01-26 09:30:09 +03:00
|
|
|
return transaction.forget();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2016-03-23 18:02:57 +03:00
|
|
|
nsresult IDBDatabase::Transaction(JSContext* aCx,
|
|
|
|
const StringOrStringSequence& aStoreNames,
|
2014-09-27 03:21:57 +04:00
|
|
|
IDBTransactionMode aMode,
|
2015-01-26 09:30:09 +03:00
|
|
|
IDBTransaction** aTransaction) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2016-03-15 09:00:37 +03:00
|
|
|
if (NS_WARN_IF((aMode == IDBTransactionMode::Readwriteflush ||
|
|
|
|
aMode == IDBTransactionMode::Cleanup) &&
|
2015-01-26 09:30:09 +03:00
|
|
|
!IndexedDatabaseManager::ExperimentalFeaturesEnabled())) {
|
2015-01-26 09:30:09 +03:00
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
2015-01-26 09:30:09 +03:00
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
|
|
|
|
2015-01-26 09:30:09 +03:00
|
|
|
if (QuotaManager::IsShuttingDown()) {
|
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
2015-03-29 22:55:11 +03:00
|
|
|
}
|
2011-11-03 05:03:15 +04:00
|
|
|
|
2015-01-26 09:30:09 +03:00
|
|
|
if (mClosed || RunningVersionChangeTransaction()) {
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
2015-03-31 05:45:56 +03:00
|
|
|
}
|
2011-11-03 19:57:30 +04:00
|
|
|
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<nsString, 1> stackSequence;
|
2015-01-26 09:30:09 +03:00
|
|
|
|
2015-01-26 09:30:09 +03:00
|
|
|
if (aStoreNames.IsString()) {
|
|
|
|
stackSequence.AppendElement(aStoreNames.GetAsString());
|
|
|
|
} else {
|
|
|
|
MOZ_ASSERT(aStoreNames.IsStringSequence());
|
|
|
|
if (aStoreNames.GetAsStringSequence().IsEmpty()) {
|
|
|
|
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
|
|
|
|
}
|
2015-03-31 05:45:56 +03:00
|
|
|
}
|
2015-01-26 09:30:09 +03:00
|
|
|
|
2015-01-26 09:30:09 +03:00
|
|
|
const nsTArray<nsString>& storeNames =
|
|
|
|
aStoreNames.IsString() ? stackSequence
|
|
|
|
: static_cast<const nsTArray<nsString>&>(
|
|
|
|
aStoreNames.GetAsStringSequence());
|
|
|
|
MOZ_ASSERT(!storeNames.IsEmpty());
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
const nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores();
|
2015-01-26 09:30:09 +03:00
|
|
|
const uint32_t nameCount = storeNames.Length();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
nsTArray<nsString> sortedStoreNames;
|
|
|
|
sortedStoreNames.SetCapacity(nameCount);
|
|
|
|
|
2019-11-21 15:38:12 +03:00
|
|
|
// While collecting object store names, check if the corresponding object
|
|
|
|
// stores actually exist.
|
|
|
|
const auto begin = objectStores.cbegin();
|
|
|
|
const auto end = objectStores.cend();
|
|
|
|
for (const auto& name : storeNames) {
|
|
|
|
const auto foundIt =
|
|
|
|
std::find_if(begin, end, [&name](const auto& objectStore) {
|
|
|
|
return objectStore.metadata().name() == name;
|
|
|
|
});
|
|
|
|
if (foundIt == end) {
|
2015-01-26 09:30:09 +03:00
|
|
|
return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
|
2011-11-03 19:57:30 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2019-11-21 15:38:12 +03:00
|
|
|
sortedStoreNames.EmplaceBack(name);
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
2019-11-21 15:38:12 +03:00
|
|
|
sortedStoreNames.Sort();
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// Remove any duplicates.
|
2019-11-21 15:38:12 +03:00
|
|
|
sortedStoreNames.SetLength(
|
|
|
|
std::unique(sortedStoreNames.begin(), sortedStoreNames.end()).GetIndex());
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2015-01-26 09:30:09 +03:00
|
|
|
IDBTransaction::Mode mode;
|
|
|
|
switch (aMode) {
|
|
|
|
case IDBTransactionMode::Readonly:
|
2019-11-27 13:54:57 +03:00
|
|
|
mode = IDBTransaction::Mode::ReadOnly;
|
2015-01-26 09:30:09 +03:00
|
|
|
break;
|
|
|
|
case IDBTransactionMode::Readwrite:
|
2016-04-21 07:53:30 +03:00
|
|
|
if (mQuotaExceeded) {
|
2019-11-27 13:54:57 +03:00
|
|
|
mode = IDBTransaction::Mode::Cleanup;
|
2016-04-21 07:53:30 +03:00
|
|
|
mQuotaExceeded = false;
|
|
|
|
} else {
|
2019-11-27 13:54:57 +03:00
|
|
|
mode = IDBTransaction::Mode::ReadWrite;
|
2016-04-21 07:53:30 +03:00
|
|
|
}
|
2015-01-26 09:30:09 +03:00
|
|
|
break;
|
|
|
|
case IDBTransactionMode::Readwriteflush:
|
2019-11-27 13:54:57 +03:00
|
|
|
mode = IDBTransaction::Mode::ReadWriteFlush;
|
2015-01-26 09:30:09 +03:00
|
|
|
break;
|
2016-03-15 09:00:37 +03:00
|
|
|
case IDBTransactionMode::Cleanup:
|
2019-11-27 13:54:57 +03:00
|
|
|
mode = IDBTransaction::Mode::Cleanup;
|
2016-04-21 07:53:30 +03:00
|
|
|
mQuotaExceeded = false;
|
2016-03-15 09:00:37 +03:00
|
|
|
break;
|
2015-01-26 09:30:09 +03:00
|
|
|
case IDBTransactionMode::Versionchange:
|
2016-04-28 12:38:21 +03:00
|
|
|
return NS_ERROR_DOM_TYPE_ERR;
|
2015-01-26 09:30:09 +03:00
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Unknown mode!");
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IDBTransaction> transaction =
|
2016-03-23 18:02:57 +03:00
|
|
|
IDBTransaction::Create(aCx, this, sortedStoreNames, mode);
|
2017-09-20 11:53:14 +03:00
|
|
|
if (NS_WARN_IF(!transaction)) {
|
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
|
|
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
BackgroundTransactionChild* actor =
|
|
|
|
new BackgroundTransactionChild(transaction);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_MARK_CHILD_TRANSACTION(
|
|
|
|
"database(%s).transaction(%s)", "IDBDatabase.transaction()",
|
2014-10-16 08:56:52 +04:00
|
|
|
transaction->LoggingSerialNumber(), IDB_LOG_STRINGIFY(this),
|
|
|
|
IDB_LOG_STRINGIFY(transaction));
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ALWAYS_TRUE(mBackgroundActor->SendPBackgroundIDBTransactionConstructor(
|
|
|
|
actor, sortedStoreNames, mode));
|
2017-02-10 10:13:45 +03:00
|
|
|
MOZ_ASSERT(actor->GetActorEventTarget(),
|
|
|
|
"The event target shall be inherited from it manager actor.");
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
transaction->SetBackgroundActor(actor);
|
|
|
|
|
2019-11-27 13:54:57 +03:00
|
|
|
if (mode == IDBTransaction::Mode::Cleanup) {
|
2016-03-15 09:00:37 +03:00
|
|
|
ExpireFileActors(/* aExpireAll */ true);
|
|
|
|
}
|
|
|
|
|
2015-01-26 09:30:09 +03:00
|
|
|
transaction.forget(aTransaction);
|
|
|
|
return NS_OK;
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
StorageType IDBDatabase::Storage() const {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mSpec);
|
|
|
|
|
|
|
|
return PersistenceTypeToStorage(mSpec->metadata().persistenceType());
|
|
|
|
}
|
|
|
|
|
2016-03-23 18:02:57 +03:00
|
|
|
already_AddRefed<IDBRequest> IDBDatabase::CreateMutableFile(
|
2014-06-12 07:35:29 +04:00
|
|
|
JSContext* aCx, const nsAString& aName, const Optional<nsAString>& aType,
|
|
|
|
ErrorResult& aRv) {
|
2015-09-09 14:15:05 +03:00
|
|
|
AssertIsOnOwningThread();
|
2012-11-09 01:41:23 +04:00
|
|
|
|
2019-03-22 17:01:31 +03:00
|
|
|
if (aName.IsEmpty()) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2013-03-26 15:13:17 +04:00
|
|
|
if (QuotaManager::IsShuttingDown()) {
|
2014-01-28 04:37:05 +04:00
|
|
|
IDB_REPORT_INTERNAL_ERR();
|
2013-07-31 19:48:46 +04:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
|
|
return nullptr;
|
2012-06-03 20:33:52 +04:00
|
|
|
}
|
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
if (mClosed || mFileHandleDisabled) {
|
2013-07-31 19:48:46 +04:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
|
|
|
|
return nullptr;
|
2012-06-03 20:33:52 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsString type;
|
|
|
|
if (aType.WasPassed()) {
|
|
|
|
type = aType.Value();
|
|
|
|
}
|
2012-06-03 20:33:52 +04:00
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
CreateFileParams params(nsString(aName), type);
|
2014-10-16 08:56:52 +04:00
|
|
|
|
2016-03-23 18:02:57 +03:00
|
|
|
RefPtr<IDBRequest> request = IDBRequest::Create(aCx, this, nullptr);
|
2015-09-09 14:15:05 +03:00
|
|
|
MOZ_ASSERT(request);
|
|
|
|
|
|
|
|
BackgroundDatabaseRequestChild* actor =
|
|
|
|
new BackgroundDatabaseRequestChild(this, request);
|
|
|
|
|
2019-09-27 13:11:45 +03:00
|
|
|
IDB_LOG_MARK_CHILD_REQUEST(
|
|
|
|
"database(%s).createMutableFile(%s)", "IDBDatabase.createMutableFile()",
|
|
|
|
request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(this),
|
|
|
|
NS_ConvertUTF16toUTF8(aName).get());
|
2015-09-09 14:15:05 +03:00
|
|
|
|
|
|
|
mBackgroundActor->SendPBackgroundIDBDatabaseRequestConstructor(actor, params);
|
2012-06-03 20:33:52 +04:00
|
|
|
|
2017-02-10 10:13:45 +03:00
|
|
|
MOZ_ASSERT(actor->GetActorEventTarget(),
|
|
|
|
"The event target shall be inherited from its manager actor.");
|
|
|
|
|
2013-07-31 19:48:46 +04:00
|
|
|
return request.forget();
|
2012-06-03 20:33:52 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::RegisterTransaction(IDBTransaction* aTransaction) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aTransaction);
|
|
|
|
aTransaction->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(!mTransactions.Contains(aTransaction));
|
2010-10-19 21:58:52 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mTransactions.PutEntry(aTransaction);
|
|
|
|
}
|
2010-10-19 21:58:52 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::UnregisterTransaction(IDBTransaction* aTransaction) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aTransaction);
|
|
|
|
aTransaction->AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mTransactions.Contains(aTransaction));
|
2013-07-31 19:48:46 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
mTransactions.RemoveEntry(aTransaction);
|
|
|
|
}
|
|
|
|
|
2014-11-14 05:20:38 +03:00
|
|
|
void IDBDatabase::AbortTransactions(bool aShouldWarn) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
class MOZ_STACK_CLASS Helper final {
|
2016-02-02 18:36:30 +03:00
|
|
|
typedef AutoTArray<RefPtr<IDBTransaction>, 20> StrongTransactionArray;
|
|
|
|
typedef AutoTArray<IDBTransaction*, 20> WeakTransactionArray;
|
2015-06-26 01:22:59 +03:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
public:
|
2015-06-26 01:22:59 +03:00
|
|
|
static void AbortTransactions(IDBDatabase* aDatabase,
|
|
|
|
const bool aShouldWarn) {
|
|
|
|
MOZ_ASSERT(aDatabase);
|
|
|
|
aDatabase->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
nsTHashtable<nsPtrHashKey<IDBTransaction>>& transactionTable =
|
|
|
|
aDatabase->mTransactions;
|
|
|
|
|
|
|
|
if (!transactionTable.Count()) {
|
2019-11-11 11:25:20 +03:00
|
|
|
// Return early as an optimization, the remainder is a no-op in this
|
|
|
|
// case.
|
2014-09-27 03:21:57 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-26 01:22:59 +03:00
|
|
|
StrongTransactionArray transactionsToAbort;
|
|
|
|
transactionsToAbort.SetCapacity(transactionTable.Count());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-07-21 04:48:54 +03:00
|
|
|
for (auto iter = transactionTable.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
IDBTransaction* transaction = iter.Get()->GetKey();
|
|
|
|
MOZ_ASSERT(transaction);
|
|
|
|
|
|
|
|
transaction->AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
// Transactions that are already done can simply be ignored. Otherwise
|
|
|
|
// there is a race here and it's possible that the transaction has not
|
|
|
|
// been successfully committed yet so we will warn the user.
|
2019-11-28 19:00:29 +03:00
|
|
|
if (!transaction->IsFinished()) {
|
2015-07-21 04:48:54 +03:00
|
|
|
transactionsToAbort.AppendElement(transaction);
|
|
|
|
}
|
|
|
|
}
|
2015-06-26 01:22:59 +03:00
|
|
|
MOZ_ASSERT(transactionsToAbort.Length() <= transactionTable.Count());
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-06-26 01:22:59 +03:00
|
|
|
if (transactionsToAbort.IsEmpty()) {
|
2019-11-11 11:25:20 +03:00
|
|
|
// Return early as an optimization, the remainder is a no-op in this
|
|
|
|
// case.
|
2015-06-26 01:22:59 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We want to abort transactions as soon as possible so we iterate the
|
|
|
|
// transactions once and abort them all first, collecting the transactions
|
|
|
|
// that need to have a warning issued along the way. Those that need a
|
|
|
|
// warning will be a subset of those that are aborted, so we don't need
|
|
|
|
// additional strong references here.
|
|
|
|
WeakTransactionArray transactionsThatNeedWarning;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
for (RefPtr<IDBTransaction>& transaction : transactionsToAbort) {
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(transaction);
|
2019-11-28 19:00:29 +03:00
|
|
|
MOZ_ASSERT(!transaction->IsFinished());
|
2015-06-26 01:22:59 +03:00
|
|
|
|
2019-11-11 11:25:13 +03:00
|
|
|
// We warn for any transactions that could have written data, but
|
|
|
|
// ignore read-only transactions.
|
|
|
|
if (aShouldWarn && transaction->IsWriteAllowed()) {
|
|
|
|
transactionsThatNeedWarning.AppendElement(transaction);
|
2015-06-26 01:22:59 +03:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2016-05-31 13:08:20 +03:00
|
|
|
transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
2015-06-26 01:22:59 +03:00
|
|
|
}
|
2014-11-14 05:20:38 +03:00
|
|
|
|
2015-06-26 01:22:59 +03:00
|
|
|
static const char kWarningMessage[] =
|
|
|
|
"IndexedDBTransactionAbortNavigation";
|
|
|
|
|
|
|
|
for (IDBTransaction* transaction : transactionsThatNeedWarning) {
|
|
|
|
MOZ_ASSERT(transaction);
|
|
|
|
|
|
|
|
nsString filename;
|
2015-09-02 04:01:02 +03:00
|
|
|
uint32_t lineNo, column;
|
|
|
|
transaction->GetCallerLocation(filename, &lineNo, &column);
|
2015-06-26 01:22:59 +03:00
|
|
|
|
2015-09-02 04:01:02 +03:00
|
|
|
aDatabase->LogWarning(kWarningMessage, filename, lineNo, column);
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-26 01:22:59 +03:00
|
|
|
Helper::AbortTransactions(this, aShouldWarn);
|
2010-10-19 21:58:52 +04:00
|
|
|
}
|
|
|
|
|
2015-05-12 15:09:51 +03:00
|
|
|
PBackgroundIDBDatabaseFileChild* IDBDatabase::GetOrCreateFileActorForBlob(
|
|
|
|
Blob* aBlob) {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aBlob);
|
|
|
|
MOZ_ASSERT(mBackgroundActor);
|
|
|
|
|
2014-10-08 20:15:23 +04:00
|
|
|
// We use the File's nsIWeakReference as the key to the table because
|
2014-09-27 03:21:57 +04:00
|
|
|
// a) it is unique per blob, b) it is reference-counted so that we can
|
2014-10-08 20:15:23 +04:00
|
|
|
// guarantee that it stays alive, and c) it doesn't hold the actual File
|
2014-09-27 03:21:57 +04:00
|
|
|
// alive.
|
2018-10-31 23:39:03 +03:00
|
|
|
nsWeakPtr weakRef = do_GetWeakReference(aBlob);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(weakRef);
|
|
|
|
|
|
|
|
PBackgroundIDBDatabaseFileChild* actor = nullptr;
|
|
|
|
|
|
|
|
if (!mFileActors.Get(weakRef, &actor)) {
|
2015-05-12 15:11:03 +03:00
|
|
|
BlobImpl* blobImpl = aBlob->Impl();
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(blobImpl);
|
|
|
|
|
2017-05-23 08:50:33 +03:00
|
|
|
PBackgroundChild* backgroundManager =
|
|
|
|
mBackgroundActor->Manager()->Manager();
|
|
|
|
MOZ_ASSERT(backgroundManager);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2017-05-23 08:50:33 +03:00
|
|
|
IPCBlob ipcBlob;
|
|
|
|
nsresult rv = IPCBlobUtils::Serialize(blobImpl, backgroundManager, ipcBlob);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-02-10 10:13:45 +03:00
|
|
|
|
2017-05-23 08:50:33 +03:00
|
|
|
auto* dbFile = new DatabaseFile(this);
|
2017-02-10 10:13:45 +03:00
|
|
|
|
2017-05-23 08:50:33 +03:00
|
|
|
actor = mBackgroundActor->SendPBackgroundIDBDatabaseFileConstructor(
|
|
|
|
dbFile, ipcBlob);
|
|
|
|
if (NS_WARN_IF(!actor)) {
|
|
|
|
return nullptr;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2017-05-23 08:50:33 +03:00
|
|
|
MOZ_ASSERT(actor->GetActorEventTarget(),
|
|
|
|
"The event target shall be inherited from its manager actor.");
|
2014-09-27 03:21:57 +04:00
|
|
|
mFileActors.Put(weakRef, actor);
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(actor);
|
|
|
|
|
|
|
|
return actor;
|
2012-12-17 23:25:10 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::NoteFinishedFileActor(
|
|
|
|
PBackgroundIDBDatabaseFileChild* aFileActor) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aFileActor);
|
|
|
|
|
2015-11-25 03:54:27 +03:00
|
|
|
for (auto iter = mFileActors.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
MOZ_ASSERT(iter.Key());
|
|
|
|
PBackgroundIDBDatabaseFileChild* actor = iter.Data();
|
|
|
|
MOZ_ASSERT(actor);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-11-25 03:54:27 +03:00
|
|
|
if (actor == aFileActor) {
|
|
|
|
iter.Remove();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
2015-11-25 03:54:27 +03:00
|
|
|
}
|
2013-03-26 15:13:17 +04:00
|
|
|
}
|
|
|
|
|
2017-06-16 14:06:36 +03:00
|
|
|
void IDBDatabase::NoteActiveTransaction() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mFactory);
|
|
|
|
|
|
|
|
// Increase the number of active transactions.
|
|
|
|
mFactory->UpdateActiveTransactionCount(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IDBDatabase::NoteInactiveTransaction() {
|
2014-09-27 03:21:57 +04:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (!mBackgroundActor || !mFileActors.Count()) {
|
2017-06-16 14:06:36 +03:00
|
|
|
MOZ_ASSERT(mFactory);
|
|
|
|
mFactory->UpdateActiveTransactionCount(-1);
|
2014-09-27 03:21:57 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-13 11:40:58 +03:00
|
|
|
RefPtr<Runnable> runnable =
|
2017-06-16 14:06:36 +03:00
|
|
|
NewRunnableMethod("IDBDatabase::NoteInactiveTransactionDelayed", this,
|
|
|
|
&IDBDatabase::NoteInactiveTransactionDelayed);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(runnable);
|
|
|
|
|
2014-12-17 09:26:15 +03:00
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
// Wrap as a nsICancelableRunnable to make workers happy.
|
2017-01-13 11:40:58 +03:00
|
|
|
RefPtr<Runnable> cancelable = new CancelableRunnableWrapper(runnable);
|
2014-12-17 09:26:15 +03:00
|
|
|
cancelable.swap(runnable);
|
|
|
|
}
|
|
|
|
|
2017-01-13 11:40:58 +03:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(
|
|
|
|
EventTarget()->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL));
|
2013-03-26 15:13:17 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsresult IDBDatabase::GetQuotaInfo(nsACString& aOrigin,
|
|
|
|
PersistenceType* aPersistenceType) {
|
|
|
|
using mozilla::dom::quota::QuotaManager;
|
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread(), "This can't work off the main thread!");
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
if (aPersistenceType) {
|
2014-11-28 11:44:12 +03:00
|
|
|
*aPersistenceType = mSpec->metadata().persistenceType();
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(*aPersistenceType != PERSISTENCE_TYPE_INVALID);
|
|
|
|
}
|
|
|
|
|
|
|
|
PrincipalInfo* principalInfo = mFactory->GetPrincipalInfo();
|
|
|
|
MOZ_ASSERT(principalInfo);
|
|
|
|
|
|
|
|
switch (principalInfo->type()) {
|
|
|
|
case PrincipalInfo::TNullPrincipalInfo:
|
|
|
|
MOZ_CRASH("Is this needed?!");
|
|
|
|
|
|
|
|
case PrincipalInfo::TSystemPrincipalInfo:
|
2017-03-06 20:38:42 +03:00
|
|
|
QuotaManager::GetInfoForChrome(nullptr, nullptr, &aOrigin);
|
2014-09-27 03:21:57 +04:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
case PrincipalInfo::TContentPrincipalInfo: {
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
|
|
PrincipalInfoToPrincipal(*principalInfo, &rv);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = QuotaManager::GetInfoFromPrincipal(principal, nullptr, nullptr,
|
2017-03-06 20:38:42 +03:00
|
|
|
&aOrigin);
|
2014-09-27 03:21:57 +04:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Unknown PrincipalInfo type!");
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_CRASH("Should never get here!");
|
2010-11-11 02:26:03 +03:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::ExpireFileActors(bool aExpireAll) {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
2015-11-25 03:54:27 +03:00
|
|
|
if (mBackgroundActor && mFileActors.Count()) {
|
|
|
|
for (auto iter = mFileActors.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
nsISupports* key = iter.Key();
|
|
|
|
PBackgroundIDBDatabaseFileChild* actor = iter.Data();
|
|
|
|
MOZ_ASSERT(key);
|
|
|
|
MOZ_ASSERT(actor);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-11-25 03:54:27 +03:00
|
|
|
bool shouldExpire = aExpireAll;
|
2014-09-27 03:21:57 +04:00
|
|
|
if (!shouldExpire) {
|
2018-10-31 23:39:03 +03:00
|
|
|
nsWeakPtr weakRef = do_QueryInterface(key);
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(weakRef);
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> referent = do_QueryReferent(weakRef);
|
|
|
|
shouldExpire = !referent;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shouldExpire) {
|
2015-11-25 03:54:27 +03:00
|
|
|
PBackgroundIDBDatabaseFileChild::Send__delete__(actor);
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-11-25 03:54:27 +03:00
|
|
|
if (!aExpireAll) {
|
|
|
|
iter.Remove();
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (aExpireAll) {
|
|
|
|
mFileActors.Clear();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
MOZ_ASSERT(!mFileActors.Count());
|
|
|
|
}
|
2012-06-01 21:21:12 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::NoteLiveMutableFile(IDBMutableFile* aMutableFile) {
|
2015-09-09 14:15:05 +03:00
|
|
|
AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aMutableFile);
|
2015-09-09 14:15:05 +03:00
|
|
|
aMutableFile->AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(!mLiveMutableFiles.Contains(aMutableFile));
|
|
|
|
|
|
|
|
mLiveMutableFiles.AppendElement(aMutableFile);
|
2012-06-01 21:21:12 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::NoteFinishedMutableFile(IDBMutableFile* aMutableFile) {
|
2015-09-09 14:15:05 +03:00
|
|
|
AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(aMutableFile);
|
2015-09-09 14:15:05 +03:00
|
|
|
aMutableFile->AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
// It's ok if this is called after we cleared the array, so don't assert that
|
|
|
|
// aMutableFile is in the list.
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
mLiveMutableFiles.RemoveElement(aMutableFile);
|
2012-06-01 21:21:12 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::InvalidateMutableFiles() {
|
2015-09-09 14:15:05 +03:00
|
|
|
AssertIsOnOwningThread();
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2015-09-09 14:15:05 +03:00
|
|
|
if (!mLiveMutableFiles.IsEmpty()) {
|
2014-09-27 03:21:57 +04:00
|
|
|
for (uint32_t count = mLiveMutableFiles.Length(), index = 0; index < count;
|
|
|
|
index++) {
|
|
|
|
mLiveMutableFiles[index]->Invalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
mLiveMutableFiles.Clear();
|
|
|
|
}
|
2012-06-01 21:21:12 +04:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::Invalidate() {
|
|
|
|
AssertIsOnOwningThread();
|
2013-03-16 10:58:50 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (!mInvalidated) {
|
|
|
|
mInvalidated = true;
|
2013-03-16 10:58:50 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
InvalidateInternal();
|
2013-05-11 01:22:01 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
|
|
|
|
2017-06-16 14:06:36 +03:00
|
|
|
void IDBDatabase::NoteInactiveTransactionDelayed() {
|
|
|
|
ExpireFileActors(/* aExpireAll */ false);
|
|
|
|
|
|
|
|
MOZ_ASSERT(mFactory);
|
|
|
|
mFactory->UpdateActiveTransactionCount(-1);
|
|
|
|
}
|
|
|
|
|
2014-11-14 05:20:38 +03:00
|
|
|
void IDBDatabase::LogWarning(const char* aMessageName,
|
|
|
|
const nsAString& aFilename, uint32_t aLineNumber,
|
2015-09-02 04:01:02 +03:00
|
|
|
uint32_t aColumnNumber) {
|
2014-11-14 05:20:38 +03:00
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(aMessageName);
|
|
|
|
|
2016-03-16 10:12:17 +03:00
|
|
|
ScriptErrorHelper::DumpLocalizedMessage(
|
|
|
|
nsDependentCString(aMessageName), aFilename, aLineNumber, aColumnNumber,
|
|
|
|
nsIScriptError::warningFlag, mFactory->IsChrome(),
|
|
|
|
mFactory->InnerWindowID());
|
2014-11-14 05:20:38 +03:00
|
|
|
}
|
|
|
|
|
2019-03-29 21:05:11 +03:00
|
|
|
NS_IMPL_ADDREF_INHERITED(IDBDatabase, DOMEventTargetHelper)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(IDBDatabase, DOMEventTargetHelper)
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2017-08-30 02:02:48 +03:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBDatabase)
|
2019-03-29 21:05:11 +03:00
|
|
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBDatabase)
|
2013-05-11 01:22:01 +04:00
|
|
|
|
2019-03-29 21:05:11 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase,
|
|
|
|
DOMEventTargetHelper)
|
2014-09-27 03:21:57 +04:00
|
|
|
tmp->AssertIsOnOwningThread();
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFactory)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
2010-10-19 21:58:52 +04:00
|
|
|
|
2019-03-29 21:05:11 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase,
|
|
|
|
DOMEventTargetHelper)
|
2014-09-27 03:21:57 +04:00
|
|
|
tmp->AssertIsOnOwningThread();
|
2010-10-19 21:58:52 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// Don't unlink mFactory!
|
2010-06-23 23:46:08 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
// We've been unlinked, at the very least we should be able to prevent further
|
|
|
|
// transactions from starting and unblock any other SetVersion callers.
|
|
|
|
tmp->CloseInternal();
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2018-04-04 03:10:17 +03:00
|
|
|
void IDBDatabase::DisconnectFromOwner() {
|
|
|
|
InvalidateInternal();
|
2019-03-29 21:05:11 +03:00
|
|
|
DOMEventTargetHelper::DisconnectFromOwner();
|
2018-04-04 03:10:17 +03:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
void IDBDatabase::LastRelease() {
|
|
|
|
AssertIsOnOwningThread();
|
2014-09-13 20:12:19 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
CloseInternal();
|
|
|
|
|
2019-10-09 06:21:22 +03:00
|
|
|
ExpireFileActors(/* aExpireAll */ true);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (mBackgroundActor) {
|
|
|
|
mBackgroundActor->SendDeleteMeInternal();
|
|
|
|
MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
|
2011-12-20 14:59:07 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
2011-12-20 14:59:07 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
nsresult IDBDatabase::PostHandleEvent(EventChainPostVisitor& aVisitor) {
|
2014-12-17 09:26:15 +03:00
|
|
|
nsresult rv =
|
2015-03-20 07:42:37 +03:00
|
|
|
IndexedDatabaseManager::CommonPostHandleEvent(aVisitor, mFactory);
|
2014-12-17 09:26:15 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2014-09-27 03:21:57 +04:00
|
|
|
}
|
2010-06-23 23:46:08 +04:00
|
|
|
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
JSObject* IDBDatabase::WrapObject(JSContext* aCx,
|
|
|
|
JS::Handle<JSObject*> aGivenProto) {
|
2018-06-26 00:20:54 +03:00
|
|
|
return IDBDatabase_Binding::Wrap(aCx, this, aGivenProto);
|
2010-06-23 23:46:08 +04:00
|
|
|
}
|
|
|
|
|
2014-12-17 09:26:15 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
CancelableRunnableWrapper::Run() {
|
|
|
|
nsCOMPtr<nsIRunnable> runnable;
|
|
|
|
mRunnable.swap(runnable);
|
|
|
|
|
|
|
|
if (runnable) {
|
|
|
|
return runnable->Run();
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult CancelableRunnableWrapper::Cancel() {
|
|
|
|
if (mRunnable) {
|
|
|
|
mRunnable = nullptr;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
NS_IMPL_ISUPPORTS(IDBDatabase::Observer, nsIObserver)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
IDBDatabase::Observer::Observe(nsISupports* aSubject, const char* aTopic,
|
|
|
|
const char16_t* aData) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(aTopic);
|
2012-06-03 20:33:52 +04:00
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
if (!strcmp(aTopic, kWindowObserverTopic)) {
|
|
|
|
if (mWeakDatabase) {
|
|
|
|
nsCOMPtr<nsISupportsPRUint64> supportsInt = do_QueryInterface(aSubject);
|
|
|
|
MOZ_ASSERT(supportsInt);
|
|
|
|
|
|
|
|
uint64_t windowId;
|
2016-03-28 20:28:15 +03:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(supportsInt->GetData(&windowId));
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
if (windowId == mWindowId) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IDBDatabase> database = mWeakDatabase;
|
2014-09-27 03:21:57 +04:00
|
|
|
mWeakDatabase = nullptr;
|
|
|
|
|
|
|
|
database->InvalidateInternal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(aTopic, kCycleCollectionObserverTopic) ||
|
|
|
|
!strcmp(aTopic, kMemoryPressureObserverTopic)) {
|
|
|
|
if (mWeakDatabase) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IDBDatabase> database = mWeakDatabase;
|
2014-09-27 03:21:57 +04:00
|
|
|
|
|
|
|
database->ExpireFileActors(/* aExpireAll */ false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_WARNING("Unknown observer topic!");
|
|
|
|
return NS_OK;
|
2012-06-03 20:33:52 +04:00
|
|
|
}
|
2014-09-27 03:21:57 +04:00
|
|
|
|
2016-03-30 06:04:56 +03:00
|
|
|
nsresult IDBDatabase::RenameObjectStore(int64_t aObjectStoreId,
|
|
|
|
const nsAString& aName) {
|
|
|
|
MOZ_ASSERT(mSpec);
|
|
|
|
|
|
|
|
nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores();
|
|
|
|
ObjectStoreSpec* foundObjectStoreSpec = nullptr;
|
2019-11-21 14:54:40 +03:00
|
|
|
|
2016-03-30 06:04:56 +03:00
|
|
|
// Find the matched object store spec and check if 'aName' is already used by
|
|
|
|
// another object store.
|
2019-11-21 14:54:40 +03:00
|
|
|
|
|
|
|
for (const auto& objSpec : objectStores) {
|
|
|
|
const bool idIsCurrent = objSpec.metadata().id() == aObjectStoreId;
|
|
|
|
|
|
|
|
if (idIsCurrent) {
|
2016-03-30 06:04:56 +03:00
|
|
|
MOZ_ASSERT(!foundObjectStoreSpec);
|
2019-11-21 14:54:40 +03:00
|
|
|
foundObjectStoreSpec = const_cast<ObjectStoreSpec*>(&objSpec);
|
2016-03-30 06:04:56 +03:00
|
|
|
}
|
2019-11-21 14:54:40 +03:00
|
|
|
|
|
|
|
if (objSpec.metadata().name() == aName) {
|
|
|
|
if (idIsCurrent) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2018-10-11 14:06:11 +03:00
|
|
|
return NS_ERROR_DOM_INDEXEDDB_RENAME_OBJECT_STORE_ERR;
|
2016-03-30 06:04:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(foundObjectStoreSpec);
|
|
|
|
|
|
|
|
// Update the name of the matched object store.
|
2019-11-21 14:54:40 +03:00
|
|
|
foundObjectStoreSpec->metadata().name().Assign(aName);
|
2016-03-30 06:04:56 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult IDBDatabase::RenameIndex(int64_t aObjectStoreId, int64_t aIndexId,
|
|
|
|
const nsAString& aName) {
|
|
|
|
MOZ_ASSERT(mSpec);
|
|
|
|
|
|
|
|
nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores();
|
|
|
|
|
|
|
|
ObjectStoreSpec* foundObjectStoreSpec = nullptr;
|
|
|
|
// Find the matched index metadata and check if 'aName' is already used by
|
|
|
|
// another index.
|
|
|
|
for (uint32_t objCount = objectStores.Length(), objIndex = 0;
|
|
|
|
objIndex < objCount; objIndex++) {
|
|
|
|
const ObjectStoreSpec& objSpec = objectStores[objIndex];
|
|
|
|
if (objSpec.metadata().id() == aObjectStoreId) {
|
|
|
|
foundObjectStoreSpec = &objectStores[objIndex];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(foundObjectStoreSpec);
|
|
|
|
|
|
|
|
nsTArray<IndexMetadata>& indexes = foundObjectStoreSpec->indexes();
|
|
|
|
IndexMetadata* foundIndexMetadata = nullptr;
|
|
|
|
for (uint32_t idxCount = indexes.Length(), idxIndex = 0; idxIndex < idxCount;
|
|
|
|
idxIndex++) {
|
|
|
|
const IndexMetadata& metadata = indexes[idxIndex];
|
|
|
|
if (metadata.id() == aIndexId) {
|
|
|
|
MOZ_ASSERT(!foundIndexMetadata);
|
|
|
|
foundIndexMetadata = &indexes[idxIndex];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (aName == metadata.name()) {
|
2018-10-11 14:06:11 +03:00
|
|
|
return NS_ERROR_DOM_INDEXEDDB_RENAME_INDEX_ERR;
|
2016-03-30 06:04:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(foundIndexMetadata);
|
|
|
|
|
|
|
|
// Update the name of the matched object store.
|
|
|
|
foundIndexMetadata->name() = nsString(aName);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-06-16 14:06:36 +03:00
|
|
|
void IDBDatabase::IncreaseActiveDatabaseCount() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
MOZ_ASSERT(mFactory);
|
|
|
|
MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
|
|
|
|
|
|
|
|
mFactory->UpdateActiveDatabaseCount(1);
|
|
|
|
mIncreasedActiveDatabaseCount = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IDBDatabase::MaybeDecreaseActiveDatabaseCount() {
|
|
|
|
AssertIsOnOwningThread();
|
|
|
|
|
|
|
|
if (mIncreasedActiveDatabaseCount) {
|
|
|
|
// Decrease the number of active databases.
|
|
|
|
MOZ_ASSERT(mFactory);
|
|
|
|
mFactory->UpdateActiveDatabaseCount(-1);
|
|
|
|
mIncreasedActiveDatabaseCount = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|