michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #include "IndexedDBParent.h" michael@0: michael@0: #include "nsIDOMEvent.h" michael@0: #include "nsIDOMFile.h" michael@0: #include "nsIXPConnect.h" michael@0: michael@0: #include "mozilla/AppProcessChecker.h" michael@0: #include "mozilla/Assertions.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/dom/ContentParent.h" michael@0: #include "mozilla/dom/IDBDatabaseBinding.h" michael@0: #include "mozilla/dom/ipc/Blob.h" michael@0: #include "mozilla/dom/TabParent.h" michael@0: #include "mozilla/unused.h" michael@0: #include "nsCxPusher.h" michael@0: michael@0: #include "AsyncConnectionHelper.h" michael@0: #include "DatabaseInfo.h" michael@0: #include "IDBDatabase.h" michael@0: #include "IDBEvents.h" michael@0: #include "IDBFactory.h" michael@0: #include "IDBIndex.h" michael@0: #include "IDBKeyRange.h" michael@0: #include "IDBObjectStore.h" michael@0: #include "IDBTransaction.h" michael@0: michael@0: #define CHROME_ORIGIN "chrome" michael@0: #define PERMISSION_PREFIX "indexedDB-chrome-" michael@0: #define PERMISSION_SUFFIX_READ "-read" michael@0: #define PERMISSION_SUFFIX_WRITE "-write" michael@0: michael@0: USING_INDEXEDDB_NAMESPACE michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::dom; michael@0: michael@0: /******************************************************************************* michael@0: * AutoSetCurrentTransaction michael@0: ******************************************************************************/ michael@0: michael@0: AutoSetCurrentTransaction::AutoSetCurrentTransaction( michael@0: IDBTransaction* aTransaction) michael@0: { michael@0: MOZ_ASSERT(aTransaction); michael@0: AsyncConnectionHelper::SetCurrentTransaction(aTransaction); michael@0: } michael@0: michael@0: AutoSetCurrentTransaction::~AutoSetCurrentTransaction() michael@0: { michael@0: AsyncConnectionHelper::SetCurrentTransaction(nullptr); michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBParent::IndexedDBParent(ContentParent* aContentParent) michael@0: : mManagerContent(aContentParent), mManagerTab(nullptr), mDisconnected(false) michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBParent); michael@0: MOZ_ASSERT(aContentParent); michael@0: } michael@0: michael@0: IndexedDBParent::IndexedDBParent(TabParent* aTabParent) michael@0: : mManagerContent(nullptr), mManagerTab(aTabParent), mDisconnected(false) michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBParent); michael@0: MOZ_ASSERT(aTabParent); michael@0: } michael@0: michael@0: IndexedDBParent::~IndexedDBParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBParent); michael@0: } michael@0: michael@0: void michael@0: IndexedDBParent::Disconnect() michael@0: { michael@0: if (mDisconnected) { michael@0: return; michael@0: } michael@0: michael@0: mDisconnected = true; michael@0: michael@0: const InfallibleTArray& databases = michael@0: ManagedPIndexedDBDatabaseParent(); michael@0: for (uint32_t i = 0; i < databases.Length(); ++i) { michael@0: static_cast(databases[i])->Disconnect(); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: IndexedDBParent::CheckReadPermission(const nsAString& aDatabaseName) michael@0: { michael@0: NS_NAMED_LITERAL_CSTRING(permission, PERMISSION_SUFFIX_READ); michael@0: return CheckPermissionInternal(aDatabaseName, permission); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBParent::CheckWritePermission(const nsAString& aDatabaseName) michael@0: { michael@0: // Write permission assumes read permission is granted as well. michael@0: MOZ_ASSERT(CheckReadPermission(aDatabaseName)); michael@0: michael@0: NS_NAMED_LITERAL_CSTRING(permission, PERMISSION_SUFFIX_WRITE); michael@0: return CheckPermissionInternal(aDatabaseName, permission); michael@0: } michael@0: michael@0: mozilla::ipc::IProtocol* michael@0: IndexedDBParent::CloneProtocol(Channel* aChannel, michael@0: mozilla::ipc::ProtocolCloneContext* aCtx) michael@0: { michael@0: MOZ_ASSERT(mManagerContent != nullptr); michael@0: MOZ_ASSERT(mManagerTab == nullptr); michael@0: MOZ_ASSERT(!mDisconnected); michael@0: MOZ_ASSERT(IndexedDatabaseManager::Get()); michael@0: MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess()); michael@0: michael@0: ContentParent* contentParent = aCtx->GetContentParent(); michael@0: nsAutoPtr actor(contentParent->AllocPIndexedDBParent()); michael@0: if (!actor || !contentParent->RecvPIndexedDBConstructor(actor)) { michael@0: return nullptr; michael@0: } michael@0: return actor.forget(); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBParent::CheckPermissionInternal(const nsAString& aDatabaseName, michael@0: const nsACString& aPermission) michael@0: { michael@0: MOZ_ASSERT(!mASCIIOrigin.IsEmpty()); michael@0: MOZ_ASSERT(mManagerContent || mManagerTab); michael@0: michael@0: if (mASCIIOrigin.EqualsLiteral(CHROME_ORIGIN)) { michael@0: nsAutoCString fullPermission = michael@0: NS_LITERAL_CSTRING(PERMISSION_PREFIX) + michael@0: NS_ConvertUTF16toUTF8(aDatabaseName) + michael@0: aPermission; michael@0: michael@0: if ((mManagerContent && michael@0: !AssertAppProcessPermission(mManagerContent, fullPermission.get())) || michael@0: (mManagerTab && michael@0: !AssertAppProcessPermission(mManagerTab, fullPermission.get()))) { michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: IndexedDBParent::ActorDestroy(ActorDestroyReason aWhy) michael@0: { michael@0: // Nothing really needs to be done here... michael@0: } michael@0: michael@0: bool michael@0: IndexedDBParent::RecvPIndexedDBDatabaseConstructor( michael@0: PIndexedDBDatabaseParent* aActor, michael@0: const nsString& aName, michael@0: const uint64_t& aVersion, michael@0: const PersistenceType& aPersistenceType) michael@0: { michael@0: if (!CheckReadPermission(aName)) { michael@0: return false; michael@0: } michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mFactory) { michael@0: return true; michael@0: } michael@0: michael@0: nsRefPtr request; michael@0: nsresult rv = mFactory->OpenInternal(aName, aVersion, aPersistenceType, false, michael@0: getter_AddRefs(request)); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: michael@0: IndexedDBDatabaseParent* actor = michael@0: static_cast(aActor); michael@0: michael@0: rv = actor->SetOpenRequest(request); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBParent::RecvPIndexedDBDeleteDatabaseRequestConstructor( michael@0: PIndexedDBDeleteDatabaseRequestParent* aActor, michael@0: const nsString& aName, michael@0: const PersistenceType& aPersistenceType) michael@0: { michael@0: if (!CheckWritePermission(aName)) { michael@0: return false; michael@0: } michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mFactory) { michael@0: return true; michael@0: } michael@0: michael@0: IndexedDBDeleteDatabaseRequestParent* actor = michael@0: static_cast(aActor); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: nsresult rv = mFactory->OpenInternal(aName, 0, aPersistenceType, true, michael@0: getter_AddRefs(request)); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: michael@0: rv = actor->SetOpenRequest(request); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: PIndexedDBDatabaseParent* michael@0: IndexedDBParent::AllocPIndexedDBDatabaseParent( michael@0: const nsString& aName, michael@0: const uint64_t& aVersion, michael@0: const PersistenceType& aPersistenceType) michael@0: { michael@0: return new IndexedDBDatabaseParent(); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBParent::DeallocPIndexedDBDatabaseParent(PIndexedDBDatabaseParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: PIndexedDBDeleteDatabaseRequestParent* michael@0: IndexedDBParent::AllocPIndexedDBDeleteDatabaseRequestParent( michael@0: const nsString& aName, michael@0: const PersistenceType& aPersistenceType) michael@0: { michael@0: return new IndexedDBDeleteDatabaseRequestParent(mFactory); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBParent::DeallocPIndexedDBDeleteDatabaseRequestParent( michael@0: PIndexedDBDeleteDatabaseRequestParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBDatabaseParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBDatabaseParent::IndexedDBDatabaseParent() michael@0: : mEventListener(MOZ_THIS_IN_INITIALIZER_LIST()) michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBDatabaseParent); michael@0: } michael@0: michael@0: IndexedDBDatabaseParent::~IndexedDBDatabaseParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBDatabaseParent); michael@0: } michael@0: michael@0: nsresult michael@0: IndexedDBDatabaseParent::SetOpenRequest(IDBOpenDBRequest* aRequest) michael@0: { michael@0: MOZ_ASSERT(aRequest); michael@0: MOZ_ASSERT(!mOpenRequest); michael@0: michael@0: nsresult rv = aRequest->EventTarget::AddEventListener(NS_LITERAL_STRING(SUCCESS_EVT_STR), michael@0: mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = aRequest->EventTarget::AddEventListener(NS_LITERAL_STRING(ERROR_EVT_STR), michael@0: mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = aRequest->EventTarget::AddEventListener(NS_LITERAL_STRING(BLOCKED_EVT_STR), michael@0: mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = aRequest->EventTarget::AddEventListener(NS_LITERAL_STRING(UPGRADENEEDED_EVT_STR), michael@0: mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: mOpenRequest = aRequest; michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: IndexedDBDatabaseParent::HandleEvent(nsIDOMEvent* aEvent) michael@0: { michael@0: MOZ_ASSERT(aEvent); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this event. michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsString type; michael@0: nsresult rv = aEvent->GetType(type); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr target = aEvent->InternalDOMEvent()->GetTarget(); michael@0: michael@0: if (mDatabase && michael@0: SameCOMIdentity(target, NS_ISUPPORTS_CAST(EventTarget*, michael@0: mDatabase))) { michael@0: rv = HandleDatabaseEvent(aEvent, type); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (mOpenRequest && michael@0: SameCOMIdentity(target, NS_ISUPPORTS_CAST(EventTarget*, michael@0: mOpenRequest))) { michael@0: rv = HandleRequestEvent(aEvent, type); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: MOZ_CRASH("Unexpected message!"); michael@0: } michael@0: michael@0: void michael@0: IndexedDBDatabaseParent::Disconnect() michael@0: { michael@0: if (mDatabase) { michael@0: mDatabase->DisconnectFromActorParent(); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: IndexedDBDatabaseParent::CheckWritePermission(const nsAString& aDatabaseName) michael@0: { michael@0: IndexedDBParent* manager = static_cast(Manager()); michael@0: MOZ_ASSERT(manager); michael@0: michael@0: return manager->CheckWritePermission(aDatabaseName); michael@0: } michael@0: michael@0: void michael@0: IndexedDBDatabaseParent::Invalidate() michael@0: { michael@0: MOZ_ASSERT(mDatabase); michael@0: michael@0: if (!IsDisconnected()) { michael@0: mozilla::unused << SendInvalidate(); michael@0: } michael@0: } michael@0: michael@0: nsresult michael@0: IndexedDBDatabaseParent::HandleRequestEvent(nsIDOMEvent* aEvent, michael@0: const nsAString& aType) michael@0: { michael@0: MOZ_ASSERT(mOpenRequest); michael@0: MOZ_ASSERT(!IsDisconnected()); michael@0: michael@0: nsresult rv; michael@0: michael@0: if (aType.EqualsLiteral(ERROR_EVT_STR)) { michael@0: nsRefPtr request; michael@0: mOpenRequest.swap(request); michael@0: michael@0: rv = request->GetErrorCode(); michael@0: MOZ_ASSERT(NS_FAILED(rv)); michael@0: michael@0: if (!SendError(rv)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: rv = aEvent->PreventDefault(); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (aType.EqualsLiteral(BLOCKED_EVT_STR)) { michael@0: MOZ_ASSERT(!mDatabase); michael@0: michael@0: nsCOMPtr changeEvent = do_QueryInterface(aEvent); michael@0: NS_ENSURE_TRUE(changeEvent, NS_ERROR_FAILURE); michael@0: michael@0: uint64_t oldVersion = changeEvent->OldVersion(); michael@0: michael@0: if (!SendBlocked(oldVersion)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: AutoSafeJSContext cx; michael@0: michael@0: ErrorResult error; michael@0: JS::Rooted result(cx); michael@0: mOpenRequest->GetResult(cx, &result, error); michael@0: ENSURE_SUCCESS(error, error.ErrorCode()); michael@0: michael@0: MOZ_ASSERT(!JSVAL_IS_PRIMITIVE(result)); michael@0: michael@0: IDBDatabase *database; michael@0: rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database); michael@0: if (NS_FAILED(rv)) { michael@0: NS_WARNING("Didn't get the object we expected!"); michael@0: return rv; michael@0: } michael@0: michael@0: DatabaseInfo* dbInfo = database->Info(); michael@0: MOZ_ASSERT(dbInfo); michael@0: michael@0: nsAutoTArray objectStoreNames; michael@0: if (!dbInfo->GetObjectStoreNames(objectStoreNames)) { michael@0: MOZ_CRASH("This should never fail!"); michael@0: } michael@0: michael@0: InfallibleTArray objectStoreInfos; michael@0: if (!objectStoreNames.IsEmpty()) { michael@0: uint32_t length = objectStoreNames.Length(); michael@0: michael@0: objectStoreInfos.SetCapacity(length); michael@0: michael@0: for (uint32_t i = 0; i < length; i++) { michael@0: ObjectStoreInfo* osInfo = dbInfo->GetObjectStore(objectStoreNames[i]); michael@0: MOZ_ASSERT(osInfo); michael@0: michael@0: objectStoreInfos.AppendElement(*osInfo); michael@0: } michael@0: } michael@0: michael@0: if (aType.EqualsLiteral(SUCCESS_EVT_STR)) { michael@0: nsRefPtr request; michael@0: mOpenRequest.swap(request); michael@0: michael@0: EventTarget* target = static_cast(database); michael@0: michael@0: #ifdef DEBUG michael@0: { michael@0: nsresult rvDEBUG = michael@0: target->AddEventListener(NS_LITERAL_STRING(ERROR_EVT_STR), michael@0: mEventListener, false); michael@0: NS_WARN_IF_FALSE(NS_SUCCEEDED(rvDEBUG), "Failed to add error listener!"); michael@0: } michael@0: #endif michael@0: michael@0: NS_NAMED_LITERAL_STRING(versionChange, VERSIONCHANGE_EVT_STR); michael@0: rv = target->AddEventListener(versionChange, mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: if (!SendSuccess(*dbInfo, objectStoreInfos)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: MOZ_ASSERT(!mDatabase || mDatabase == database); michael@0: michael@0: if (!mDatabase) { michael@0: database->SetActor(this); michael@0: mDatabase = database; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (aType.EqualsLiteral(UPGRADENEEDED_EVT_STR)) { michael@0: MOZ_ASSERT(!mDatabase); michael@0: michael@0: IDBTransaction* transaction = michael@0: AsyncConnectionHelper::GetCurrentTransaction(); michael@0: MOZ_ASSERT(transaction); michael@0: michael@0: if (!CheckWritePermission(database->Name())) { michael@0: // If we get here then the child process is either dead or in the process michael@0: // of being killed. Abort the transaction now to prevent any changes to michael@0: // the database. michael@0: ErrorResult rv; michael@0: transaction->Abort(rv); michael@0: if (rv.Failed()) { michael@0: NS_WARNING("Failed to abort transaction!"); michael@0: } michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: nsCOMPtr changeEvent = do_QueryInterface(aEvent); michael@0: NS_ENSURE_TRUE(changeEvent, NS_ERROR_FAILURE); michael@0: michael@0: uint64_t oldVersion = changeEvent->OldVersion(); michael@0: michael@0: nsAutoPtr actor( michael@0: new IndexedDBVersionChangeTransactionParent()); michael@0: michael@0: rv = actor->SetTransaction(transaction); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: VersionChangeTransactionParams versionChangeParams; michael@0: versionChangeParams.dbInfo() = *dbInfo; michael@0: versionChangeParams.osInfo() = objectStoreInfos; michael@0: versionChangeParams.oldVersion() = oldVersion; michael@0: michael@0: if (!SendPIndexedDBTransactionConstructor(actor.forget(), michael@0: versionChangeParams)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: database->SetActor(this); michael@0: mDatabase = database; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: MOZ_CRASH("Unexpected message type!"); michael@0: } michael@0: michael@0: nsresult michael@0: IndexedDBDatabaseParent::HandleDatabaseEvent(nsIDOMEvent* aEvent, michael@0: const nsAString& aType) michael@0: { michael@0: MOZ_ASSERT(mDatabase); michael@0: MOZ_ASSERT(!aType.EqualsLiteral(ERROR_EVT_STR), michael@0: "Should never get error events in the parent process!"); michael@0: MOZ_ASSERT(!IsDisconnected()); michael@0: michael@0: if (aType.EqualsLiteral(VERSIONCHANGE_EVT_STR)) { michael@0: AutoSafeJSContext cx; michael@0: NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE); michael@0: michael@0: nsCOMPtr changeEvent = do_QueryInterface(aEvent); michael@0: NS_ENSURE_TRUE(changeEvent, NS_ERROR_FAILURE); michael@0: michael@0: uint64_t oldVersion = changeEvent->OldVersion(); michael@0: michael@0: Nullable newVersionVal = changeEvent->GetNewVersion(); michael@0: michael@0: uint64_t newVersion; michael@0: if (newVersionVal.IsNull()) { michael@0: newVersion = 0; michael@0: } michael@0: else { michael@0: newVersion = newVersionVal.Value(); michael@0: } michael@0: michael@0: if (!SendVersionChange(oldVersion, newVersion)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: MOZ_CRASH("Unexpected message type!"); michael@0: } michael@0: michael@0: void michael@0: IndexedDBDatabaseParent::ActorDestroy(ActorDestroyReason aWhy) michael@0: { michael@0: if (mDatabase) { michael@0: mDatabase->SetActor(static_cast(nullptr)); michael@0: mDatabase->InvalidateInternal(/* aIsDead */ true); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: IndexedDBDatabaseParent::RecvClose(const bool& aUnlinked) michael@0: { michael@0: MOZ_ASSERT(mDatabase); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: mDatabase->CloseInternal(aUnlinked); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBDatabaseParent::RecvPIndexedDBTransactionConstructor( michael@0: PIndexedDBTransactionParent* aActor, michael@0: const TransactionParams& aParams) michael@0: { michael@0: MOZ_ASSERT(aParams.type() == michael@0: TransactionParams::TNormalTransactionParams); michael@0: MOZ_ASSERT(!mOpenRequest); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mDatabase) { michael@0: return true; michael@0: } michael@0: michael@0: IndexedDBTransactionParent* actor = michael@0: static_cast(aActor); michael@0: michael@0: const NormalTransactionParams& params = aParams.get_NormalTransactionParams(); michael@0: michael@0: if (params.mode() != IDBTransaction::READ_ONLY && michael@0: !CheckWritePermission(mDatabase->Name())) { michael@0: return false; michael@0: } michael@0: michael@0: if (mDatabase->IsClosed()) { michael@0: // If the window was navigated then we won't be able to do anything here. michael@0: return true; michael@0: } michael@0: michael@0: Sequence storesToOpen; michael@0: storesToOpen.AppendElements(params.names()); michael@0: michael@0: nsRefPtr transaction = michael@0: IDBTransaction::Create(mDatabase, storesToOpen, params.mode(), false); michael@0: NS_ENSURE_TRUE(transaction, false); michael@0: michael@0: nsresult rv = actor->SetTransaction(transaction); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: PIndexedDBTransactionParent* michael@0: IndexedDBDatabaseParent::AllocPIndexedDBTransactionParent( michael@0: const TransactionParams& aParams) michael@0: { michael@0: MOZ_ASSERT(aParams.type() == michael@0: TransactionParams::TNormalTransactionParams); michael@0: return new IndexedDBTransactionParent(); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBDatabaseParent::DeallocPIndexedDBTransactionParent( michael@0: PIndexedDBTransactionParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBTransactionParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBTransactionParent::IndexedDBTransactionParent() michael@0: : mEventListener(MOZ_THIS_IN_INITIALIZER_LIST()), michael@0: mArtificialRequestCount(false) michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBTransactionParent); michael@0: } michael@0: michael@0: IndexedDBTransactionParent::~IndexedDBTransactionParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBTransactionParent); michael@0: } michael@0: michael@0: nsresult michael@0: IndexedDBTransactionParent::SetTransaction(IDBTransaction* aTransaction) michael@0: { michael@0: MOZ_ASSERT(aTransaction); michael@0: MOZ_ASSERT(!mTransaction); michael@0: michael@0: EventTarget* target = static_cast(aTransaction); michael@0: michael@0: NS_NAMED_LITERAL_STRING(complete, COMPLETE_EVT_STR); michael@0: nsresult rv = target->AddEventListener(complete, mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = target->AddEventListener(NS_LITERAL_STRING(ABORT_EVT_STR), michael@0: mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: aTransaction->OnNewRequest(); michael@0: mArtificialRequestCount = true; michael@0: michael@0: aTransaction->SetActor(this); michael@0: michael@0: mTransaction = aTransaction; michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: IndexedDBTransactionParent::HandleEvent(nsIDOMEvent* aEvent) michael@0: { michael@0: MOZ_ASSERT(aEvent); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this event. michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsString type; michael@0: nsresult rv = aEvent->GetType(type); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: CompleteParams params; michael@0: michael@0: if (type.EqualsLiteral(COMPLETE_EVT_STR)) { michael@0: params = CompleteResult(); michael@0: } michael@0: else if (type.EqualsLiteral(ABORT_EVT_STR)) { michael@0: #ifdef DEBUG michael@0: { michael@0: nsCOMPtr target = aEvent->InternalDOMEvent()->GetTarget(); michael@0: MOZ_ASSERT(SameCOMIdentity(target, NS_ISUPPORTS_CAST(EventTarget*, michael@0: mTransaction))); michael@0: } michael@0: #endif michael@0: params = AbortResult(mTransaction->GetAbortCode()); michael@0: } michael@0: else { michael@0: NS_WARNING("Unknown message type!"); michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: if (!SendComplete(params)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: IndexedDBTransactionParent::ActorDestroy(ActorDestroyReason aWhy) michael@0: { michael@0: if (mTransaction) { michael@0: if (mArtificialRequestCount) { michael@0: // The transaction never completed and now the child side is dead. Abort michael@0: // here to be safe. michael@0: ErrorResult rv; michael@0: mTransaction->Abort(rv); michael@0: michael@0: mTransaction->OnRequestFinished(); michael@0: #ifdef DEBUG michael@0: mArtificialRequestCount = false; michael@0: #endif michael@0: } michael@0: mTransaction->SetActor(static_cast(nullptr)); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: IndexedDBTransactionParent::RecvAbort(const nsresult& aAbortCode) michael@0: { michael@0: MOZ_ASSERT(mTransaction); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: mTransaction->Abort(aAbortCode); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBTransactionParent::RecvAllRequestsFinished() michael@0: { michael@0: MOZ_ASSERT(mTransaction); michael@0: MOZ_ASSERT(mArtificialRequestCount); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: mTransaction->OnRequestFinished(); michael@0: mArtificialRequestCount = false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBTransactionParent::RecvDeleteObjectStore(const nsString& aName) michael@0: { michael@0: MOZ_CRASH("Should be overridden, don't call me!"); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBTransactionParent::RecvPIndexedDBObjectStoreConstructor( michael@0: PIndexedDBObjectStoreParent* aActor, michael@0: const ObjectStoreConstructorParams& aParams) michael@0: { michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mTransaction) { michael@0: return true; michael@0: } michael@0: michael@0: IndexedDBObjectStoreParent* actor = michael@0: static_cast(aActor); michael@0: michael@0: if (aParams.type() == michael@0: ObjectStoreConstructorParams::TGetObjectStoreParams) { michael@0: const GetObjectStoreParams& params = aParams.get_GetObjectStoreParams(); michael@0: const nsString& name = params.name(); michael@0: michael@0: nsRefPtr objectStore; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mTransaction); michael@0: michael@0: ErrorResult rv; michael@0: objectStore = mTransaction->ObjectStore(name, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: michael@0: actor->SetObjectStore(objectStore); michael@0: } michael@0: michael@0: objectStore->SetActor(actor); michael@0: return true; michael@0: } michael@0: michael@0: if (aParams.type() == michael@0: ObjectStoreConstructorParams::TCreateObjectStoreParams) { michael@0: MOZ_CRASH("Should be overridden, don't call me!"); michael@0: } michael@0: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: PIndexedDBObjectStoreParent* michael@0: IndexedDBTransactionParent::AllocPIndexedDBObjectStoreParent( michael@0: const ObjectStoreConstructorParams& aParams) michael@0: { michael@0: return new IndexedDBObjectStoreParent(); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBTransactionParent::DeallocPIndexedDBObjectStoreParent( michael@0: PIndexedDBObjectStoreParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBVersionChangeTransactionParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBVersionChangeTransactionParent:: michael@0: IndexedDBVersionChangeTransactionParent() michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBVersionChangeTransactionParent); michael@0: } michael@0: michael@0: IndexedDBVersionChangeTransactionParent:: michael@0: ~IndexedDBVersionChangeTransactionParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBVersionChangeTransactionParent); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBVersionChangeTransactionParent::RecvDeleteObjectStore( michael@0: const nsString& aName) michael@0: { michael@0: MOZ_ASSERT(!mTransaction || michael@0: mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mTransaction) { michael@0: return true; michael@0: } michael@0: michael@0: if (mTransaction->Database()->IsInvalidated()) { michael@0: // If we've invalidated this database in the parent then we should bail out michael@0: // now to avoid logic problems that could force-kill the child. michael@0: return true; michael@0: } michael@0: michael@0: IDBDatabase* db = mTransaction->Database(); michael@0: MOZ_ASSERT(db); michael@0: michael@0: ErrorResult rv; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mTransaction); michael@0: db->DeleteObjectStore(aName, rv); michael@0: } michael@0: michael@0: ENSURE_SUCCESS(rv, false); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBVersionChangeTransactionParent::RecvPIndexedDBObjectStoreConstructor( michael@0: PIndexedDBObjectStoreParent* aActor, michael@0: const ObjectStoreConstructorParams& aParams) michael@0: { michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mTransaction) { michael@0: return true; michael@0: } michael@0: michael@0: if (mTransaction->Database()->IsInvalidated()) { michael@0: // If we've invalidated this database in the parent then we should bail out michael@0: // now to avoid logic problems that could force-kill the child. michael@0: return true; michael@0: } michael@0: michael@0: IndexedDBObjectStoreParent* actor = michael@0: static_cast(aActor); michael@0: michael@0: if (aParams.type() == michael@0: ObjectStoreConstructorParams::TCreateObjectStoreParams) { michael@0: MOZ_ASSERT(mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE); michael@0: michael@0: const CreateObjectStoreParams& params = michael@0: aParams.get_CreateObjectStoreParams(); michael@0: michael@0: const ObjectStoreInfoGuts& info = params.info(); michael@0: michael@0: IDBDatabase* db = mTransaction->Database(); michael@0: MOZ_ASSERT(db); michael@0: michael@0: nsRefPtr objectStore; michael@0: michael@0: ErrorResult rv; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mTransaction); michael@0: michael@0: objectStore = db->CreateObjectStoreInternal(mTransaction, info, rv); michael@0: } michael@0: michael@0: ENSURE_SUCCESS(rv, false); michael@0: michael@0: actor->SetObjectStore(objectStore); michael@0: objectStore->SetActor(actor); michael@0: return true; michael@0: } michael@0: michael@0: return michael@0: IndexedDBTransactionParent::RecvPIndexedDBObjectStoreConstructor(aActor, michael@0: aParams); michael@0: } michael@0: michael@0: PIndexedDBObjectStoreParent* michael@0: IndexedDBVersionChangeTransactionParent::AllocPIndexedDBObjectStoreParent( michael@0: const ObjectStoreConstructorParams& aParams) michael@0: { michael@0: if (aParams.type() == michael@0: ObjectStoreConstructorParams::TCreateObjectStoreParams || michael@0: mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE) { michael@0: return new IndexedDBVersionChangeObjectStoreParent(); michael@0: } michael@0: michael@0: return IndexedDBTransactionParent::AllocPIndexedDBObjectStoreParent(aParams); michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBCursorParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBCursorParent::IndexedDBCursorParent(IDBCursor* aCursor) michael@0: : mCursor(aCursor) michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBCursorParent); michael@0: MOZ_ASSERT(aCursor); michael@0: aCursor->SetActor(this); michael@0: } michael@0: michael@0: IndexedDBCursorParent::~IndexedDBCursorParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBCursorParent); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBCursorParent::IsDisconnected() const michael@0: { michael@0: MOZ_ASSERT(mCursor); michael@0: return mCursor->Transaction()->GetActorParent()->IsDisconnected(); michael@0: } michael@0: michael@0: void michael@0: IndexedDBCursorParent::ActorDestroy(ActorDestroyReason aWhy) michael@0: { michael@0: MOZ_ASSERT(mCursor); michael@0: mCursor->SetActor(static_cast(nullptr)); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBCursorParent::RecvPIndexedDBRequestConstructor( michael@0: PIndexedDBRequestParent* aActor, michael@0: const CursorRequestParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mCursor); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: IndexedDBCursorRequestParent* actor = michael@0: static_cast(aActor); michael@0: michael@0: if (mCursor->Transaction()->Database()->IsInvalidated()) { michael@0: // If we've invalidated this database in the parent then we should bail out michael@0: // now to avoid logic problems that could force-kill the child. michael@0: return actor->Send__delete__(actor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); michael@0: } michael@0: michael@0: switch (aParams.type()) { michael@0: case CursorRequestParams::TContinueParams: michael@0: return actor->Continue(aParams.get_ContinueParams()); michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown type!"); michael@0: } michael@0: michael@0: MOZ_CRASH("Should never get here!"); michael@0: } michael@0: michael@0: PIndexedDBRequestParent* michael@0: IndexedDBCursorParent::AllocPIndexedDBRequestParent( michael@0: const CursorRequestParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mCursor); michael@0: return new IndexedDBCursorRequestParent(mCursor, aParams.type()); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBCursorParent::DeallocPIndexedDBRequestParent(PIndexedDBRequestParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBObjectStoreParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBObjectStoreParent::IndexedDBObjectStoreParent() michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBObjectStoreParent); michael@0: } michael@0: michael@0: IndexedDBObjectStoreParent::~IndexedDBObjectStoreParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBObjectStoreParent); michael@0: } michael@0: michael@0: void michael@0: IndexedDBObjectStoreParent::SetObjectStore(IDBObjectStore* aObjectStore) michael@0: { michael@0: // Sadly can't assert aObjectStore here... michael@0: MOZ_ASSERT(!mObjectStore); michael@0: michael@0: mObjectStore = aObjectStore; michael@0: } michael@0: michael@0: void michael@0: IndexedDBObjectStoreParent::ActorDestroy(ActorDestroyReason aWhy) michael@0: { michael@0: if (mObjectStore) { michael@0: mObjectStore->SetActor(static_cast(nullptr)); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreParent::RecvDeleteIndex(const nsString& aName) michael@0: { michael@0: MOZ_CRASH("Should be overridden, don't call me!"); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreParent::RecvPIndexedDBRequestConstructor( michael@0: PIndexedDBRequestParent* aActor, michael@0: const ObjectStoreRequestParams& aParams) michael@0: { michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mObjectStore) { michael@0: return true; michael@0: } michael@0: michael@0: IndexedDBObjectStoreRequestParent* actor = michael@0: static_cast(aActor); michael@0: michael@0: if (mObjectStore->Transaction()->Database()->IsInvalidated()) { michael@0: // If we've invalidated this database in the parent then we should bail out michael@0: // now to avoid logic problems that could force-kill the child. michael@0: return actor->Send__delete__(actor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); michael@0: } michael@0: michael@0: switch (aParams.type()) { michael@0: case ObjectStoreRequestParams::TGetParams: michael@0: return actor->Get(aParams.get_GetParams()); michael@0: michael@0: case ObjectStoreRequestParams::TGetAllParams: michael@0: return actor->GetAll(aParams.get_GetAllParams()); michael@0: michael@0: case ObjectStoreRequestParams::TGetAllKeysParams: michael@0: return actor->GetAllKeys(aParams.get_GetAllKeysParams()); michael@0: michael@0: case ObjectStoreRequestParams::TAddParams: michael@0: return actor->Add(aParams.get_AddParams()); michael@0: michael@0: case ObjectStoreRequestParams::TPutParams: michael@0: return actor->Put(aParams.get_PutParams()); michael@0: michael@0: case ObjectStoreRequestParams::TDeleteParams: michael@0: return actor->Delete(aParams.get_DeleteParams()); michael@0: michael@0: case ObjectStoreRequestParams::TClearParams: michael@0: return actor->Clear(aParams.get_ClearParams()); michael@0: michael@0: case ObjectStoreRequestParams::TCountParams: michael@0: return actor->Count(aParams.get_CountParams()); michael@0: michael@0: case ObjectStoreRequestParams::TOpenCursorParams: michael@0: return actor->OpenCursor(aParams.get_OpenCursorParams()); michael@0: michael@0: case ObjectStoreRequestParams::TOpenKeyCursorParams: michael@0: return actor->OpenKeyCursor(aParams.get_OpenKeyCursorParams()); michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown type!"); michael@0: } michael@0: michael@0: MOZ_CRASH("Should never get here!"); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreParent::RecvPIndexedDBIndexConstructor( michael@0: PIndexedDBIndexParent* aActor, michael@0: const IndexConstructorParams& aParams) michael@0: { michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mObjectStore) { michael@0: return true; michael@0: } michael@0: michael@0: IndexedDBIndexParent* actor = static_cast(aActor); michael@0: michael@0: if (aParams.type() == IndexConstructorParams::TGetIndexParams) { michael@0: const GetIndexParams& params = aParams.get_GetIndexParams(); michael@0: const nsString& name = params.name(); michael@0: michael@0: nsRefPtr index; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: index = mObjectStore->Index(name, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: michael@0: actor->SetIndex(index); michael@0: } michael@0: michael@0: index->SetActor(actor); michael@0: return true; michael@0: } michael@0: michael@0: if (aParams.type() == IndexConstructorParams::TCreateIndexParams) { michael@0: MOZ_CRASH("Should be overridden, don't call me!"); michael@0: } michael@0: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: PIndexedDBRequestParent* michael@0: IndexedDBObjectStoreParent::AllocPIndexedDBRequestParent( michael@0: const ObjectStoreRequestParams& aParams) michael@0: { michael@0: return new IndexedDBObjectStoreRequestParent(mObjectStore, aParams.type()); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreParent::DeallocPIndexedDBRequestParent( michael@0: PIndexedDBRequestParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: PIndexedDBIndexParent* michael@0: IndexedDBObjectStoreParent::AllocPIndexedDBIndexParent( michael@0: const IndexConstructorParams& aParams) michael@0: { michael@0: return new IndexedDBIndexParent(); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreParent::DeallocPIndexedDBIndexParent( michael@0: PIndexedDBIndexParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: PIndexedDBCursorParent* michael@0: IndexedDBObjectStoreParent::AllocPIndexedDBCursorParent( michael@0: const ObjectStoreCursorConstructorParams& aParams) michael@0: { michael@0: MOZ_CRASH("Caller is supposed to manually construct a cursor!"); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreParent::DeallocPIndexedDBCursorParent( michael@0: PIndexedDBCursorParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBVersionChangeObjectStoreParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBVersionChangeObjectStoreParent:: michael@0: IndexedDBVersionChangeObjectStoreParent() michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBVersionChangeObjectStoreParent); michael@0: } michael@0: michael@0: IndexedDBVersionChangeObjectStoreParent:: michael@0: ~IndexedDBVersionChangeObjectStoreParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBVersionChangeObjectStoreParent); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBVersionChangeObjectStoreParent::RecvDeleteIndex(const nsString& aName) michael@0: { michael@0: MOZ_ASSERT(!mObjectStore || michael@0: mObjectStore->Transaction()->GetMode() == michael@0: IDBTransaction::VERSION_CHANGE); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mObjectStore) { michael@0: return true; michael@0: } michael@0: michael@0: if (mObjectStore->Transaction()->Database()->IsInvalidated()) { michael@0: // If we've invalidated this database in the parent then we should bail out michael@0: // now to avoid logic problems that could force-kill the child. michael@0: return true; michael@0: } michael@0: michael@0: ErrorResult rv; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: mObjectStore->DeleteIndex(aName, rv); michael@0: } michael@0: michael@0: ENSURE_SUCCESS(rv, false); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBVersionChangeObjectStoreParent::RecvPIndexedDBIndexConstructor( michael@0: PIndexedDBIndexParent* aActor, michael@0: const IndexConstructorParams& aParams) michael@0: { michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mObjectStore) { michael@0: return true; michael@0: } michael@0: michael@0: if (mObjectStore->Transaction()->Database()->IsInvalidated()) { michael@0: // If we've invalidated this database in the parent then we should bail out michael@0: // now to avoid logic problems that could force-kill the child. michael@0: return true; michael@0: } michael@0: michael@0: IndexedDBIndexParent* actor = static_cast(aActor); michael@0: michael@0: if (aParams.type() == IndexConstructorParams::TCreateIndexParams) { michael@0: MOZ_ASSERT(mObjectStore->Transaction()->GetMode() == michael@0: IDBTransaction::VERSION_CHANGE); michael@0: michael@0: const CreateIndexParams& params = aParams.get_CreateIndexParams(); michael@0: const IndexInfo& info = params.info(); michael@0: michael@0: nsRefPtr index; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: index = mObjectStore->CreateIndexInternal(info, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: actor->SetIndex(index); michael@0: index->SetActor(actor); michael@0: return true; michael@0: } michael@0: michael@0: return IndexedDBObjectStoreParent::RecvPIndexedDBIndexConstructor(aActor, michael@0: aParams); michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBIndexParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBIndexParent::IndexedDBIndexParent() michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBIndexParent); michael@0: } michael@0: michael@0: IndexedDBIndexParent::~IndexedDBIndexParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBIndexParent); michael@0: } michael@0: michael@0: void michael@0: IndexedDBIndexParent::SetIndex(IDBIndex* aIndex) michael@0: { michael@0: MOZ_ASSERT(aIndex); michael@0: MOZ_ASSERT(!mIndex); michael@0: michael@0: mIndex = aIndex; michael@0: } michael@0: michael@0: void michael@0: IndexedDBIndexParent::ActorDestroy(ActorDestroyReason aWhy) michael@0: { michael@0: if (mIndex) { michael@0: mIndex->SetActor(static_cast(nullptr)); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexParent::RecvPIndexedDBRequestConstructor( michael@0: PIndexedDBRequestParent* aActor, michael@0: const IndexRequestParams& aParams) michael@0: { michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this request. michael@0: return true; michael@0: } michael@0: michael@0: if (!mIndex) { michael@0: return true; michael@0: } michael@0: michael@0: IndexedDBIndexRequestParent* actor = michael@0: static_cast(aActor); michael@0: michael@0: if (mIndex->ObjectStore()->Transaction()->Database()->IsInvalidated()) { michael@0: // If we've invalidated this database in the parent then we should bail out michael@0: // now to avoid logic problems that could force-kill the child. michael@0: return actor->Send__delete__(actor, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); michael@0: } michael@0: michael@0: switch (aParams.type()) { michael@0: case IndexRequestParams::TGetParams: michael@0: return actor->Get(aParams.get_GetParams()); michael@0: michael@0: case IndexRequestParams::TGetKeyParams: michael@0: return actor->GetKey(aParams.get_GetKeyParams()); michael@0: michael@0: case IndexRequestParams::TGetAllParams: michael@0: return actor->GetAll(aParams.get_GetAllParams()); michael@0: michael@0: case IndexRequestParams::TGetAllKeysParams: michael@0: return actor->GetAllKeys(aParams.get_GetAllKeysParams()); michael@0: michael@0: case IndexRequestParams::TCountParams: michael@0: return actor->Count(aParams.get_CountParams()); michael@0: michael@0: case IndexRequestParams::TOpenCursorParams: michael@0: return actor->OpenCursor(aParams.get_OpenCursorParams()); michael@0: michael@0: case IndexRequestParams::TOpenKeyCursorParams: michael@0: return actor->OpenKeyCursor(aParams.get_OpenKeyCursorParams()); michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown type!"); michael@0: } michael@0: michael@0: MOZ_CRASH("Should never get here!"); michael@0: } michael@0: michael@0: PIndexedDBRequestParent* michael@0: IndexedDBIndexParent::AllocPIndexedDBRequestParent(const IndexRequestParams& aParams) michael@0: { michael@0: return new IndexedDBIndexRequestParent(mIndex, aParams.type()); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexParent::DeallocPIndexedDBRequestParent(PIndexedDBRequestParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: PIndexedDBCursorParent* michael@0: IndexedDBIndexParent::AllocPIndexedDBCursorParent( michael@0: const IndexCursorConstructorParams& aParams) michael@0: { michael@0: MOZ_CRASH("Caller is supposed to manually construct a cursor!"); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexParent::DeallocPIndexedDBCursorParent(PIndexedDBCursorParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBRequestParentBase michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBRequestParentBase::IndexedDBRequestParentBase() michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBRequestParentBase); michael@0: } michael@0: michael@0: IndexedDBRequestParentBase::~IndexedDBRequestParentBase() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBRequestParentBase); michael@0: } michael@0: michael@0: void michael@0: IndexedDBRequestParentBase::ActorDestroy(ActorDestroyReason aWhy) michael@0: { michael@0: if (mRequest) { michael@0: mRequest->SetActor(nullptr); michael@0: } michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBObjectStoreRequestParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBObjectStoreRequestParent::IndexedDBObjectStoreRequestParent( michael@0: IDBObjectStore* aObjectStore, michael@0: RequestType aRequestType) michael@0: : mObjectStore(aObjectStore), mRequestType(aRequestType) michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBObjectStoreRequestParent); michael@0: // Sadly can't assert aObjectStore here... michael@0: MOZ_ASSERT(aRequestType > ParamsUnionType::T__None && michael@0: aRequestType <= ParamsUnionType::T__Last); michael@0: } michael@0: michael@0: IndexedDBObjectStoreRequestParent::~IndexedDBObjectStoreRequestParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBObjectStoreRequestParent); michael@0: } michael@0: michael@0: void michael@0: IndexedDBObjectStoreRequestParent::ConvertBlobActors( michael@0: const InfallibleTArray& aActors, michael@0: nsTArray >& aBlobs) michael@0: { michael@0: MOZ_ASSERT(aBlobs.IsEmpty()); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: if (!aActors.IsEmpty()) { michael@0: // Walk the chain to get to ContentParent. michael@0: MOZ_ASSERT(mObjectStore->Transaction()->Database()->GetContentParent()); michael@0: michael@0: uint32_t length = aActors.Length(); michael@0: aBlobs.SetCapacity(length); michael@0: michael@0: for (uint32_t index = 0; index < length; index++) { michael@0: BlobParent* actor = static_cast(aActors[index]); michael@0: nsCOMPtr blob = actor->GetBlob(); michael@0: aBlobs.AppendElement(blob); michael@0: } michael@0: } michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::IsDisconnected() michael@0: { michael@0: MOZ_ASSERT(mObjectStore); michael@0: MOZ_ASSERT(mObjectStore->GetActorParent()); michael@0: return mObjectStore->GetActorParent()->IsDisconnected(); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::Get(const GetParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TGetParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: nsRefPtr keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(aParams.keyRange()); michael@0: MOZ_ASSERT(keyRange); michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mObjectStore->GetInternal(keyRange, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::GetAll(const GetAllParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TGetAllParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mObjectStore->GetAllInternal(keyRange, aParams.limit(), rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::GetAllKeys(const GetAllKeysParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TGetAllKeysParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mObjectStore->GetAllKeysInternal(keyRange, aParams.limit(), rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::Add(const AddParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TAddParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: ipc::AddPutParams params = aParams.commonParams(); michael@0: michael@0: nsTArray > blobs; michael@0: ConvertBlobActors(params.blobsParent(), blobs); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: nsresult rv = michael@0: mObjectStore->AddOrPutInternal(params.cloneInfo(), params.key(), michael@0: params.indexUpdateInfos(), blobs, false, michael@0: getter_AddRefs(request)); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::Put(const PutParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TPutParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: ipc::AddPutParams params = aParams.commonParams(); michael@0: michael@0: nsTArray > blobs; michael@0: ConvertBlobActors(params.blobsParent(), blobs); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: nsresult rv = michael@0: mObjectStore->AddOrPutInternal(params.cloneInfo(), params.key(), michael@0: params.indexUpdateInfos(), blobs, true, michael@0: getter_AddRefs(request)); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::Delete(const DeleteParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TDeleteParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: nsRefPtr keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(aParams.keyRange()); michael@0: MOZ_ASSERT(keyRange); michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mObjectStore->DeleteInternal(keyRange, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::Clear(const ClearParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TClearParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mObjectStore->Clear(rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::Count(const CountParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TCountParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: nsRefPtr request; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mObjectStore->CountInternal(keyRange, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::OpenCursor(const OpenCursorParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TOpenCursorParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: size_t direction = static_cast(aParams.direction()); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mObjectStore->OpenCursorInternal(keyRange, direction, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBObjectStoreRequestParent::OpenKeyCursor( michael@0: const OpenKeyCursorParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TOpenKeyCursorParams); michael@0: MOZ_ASSERT(mObjectStore); michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: size_t direction = static_cast(aParams.direction()); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mObjectStore->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mObjectStore->OpenKeyCursorInternal(keyRange, direction, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBIndexRequestParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBIndexRequestParent::IndexedDBIndexRequestParent( michael@0: IDBIndex* aIndex, michael@0: RequestType aRequestType) michael@0: : mIndex(aIndex), mRequestType(aRequestType) michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBIndexRequestParent); michael@0: // Sadly can't assert aIndex here... michael@0: MOZ_ASSERT(aRequestType > ParamsUnionType::T__None && michael@0: aRequestType <= ParamsUnionType::T__Last); michael@0: } michael@0: michael@0: IndexedDBIndexRequestParent::~IndexedDBIndexRequestParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBIndexRequestParent); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexRequestParent::IsDisconnected() michael@0: { michael@0: MOZ_ASSERT(mIndex); michael@0: MOZ_ASSERT(mIndex->GetActorParent()); michael@0: return mIndex->GetActorParent()->IsDisconnected(); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexRequestParent::Get(const GetParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TGetParams); michael@0: MOZ_ASSERT(mIndex); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: nsRefPtr keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(aParams.keyRange()); michael@0: MOZ_ASSERT(keyRange); michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mIndex->GetInternal(keyRange, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexRequestParent::GetKey(const GetKeyParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TGetKeyParams); michael@0: MOZ_ASSERT(mIndex); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: nsRefPtr keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(aParams.keyRange()); michael@0: MOZ_ASSERT(keyRange); michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mIndex->GetKeyInternal(keyRange, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexRequestParent::GetAll(const GetAllParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TGetAllParams); michael@0: MOZ_ASSERT(mIndex); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mIndex->GetAllInternal(keyRange, aParams.limit(), rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexRequestParent::GetAllKeys(const GetAllKeysParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TGetAllKeysParams); michael@0: MOZ_ASSERT(mIndex); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mIndex->GetAllKeysInternal(keyRange, aParams.limit(), rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexRequestParent::Count(const CountParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TCountParams); michael@0: MOZ_ASSERT(mIndex); michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: nsRefPtr request; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mIndex->CountInternal(keyRange, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexRequestParent::OpenCursor(const OpenCursorParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TOpenCursorParams); michael@0: MOZ_ASSERT(mIndex); michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: size_t direction = static_cast(aParams.direction()); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction()); michael@0: michael@0: nsresult rv = michael@0: mIndex->OpenCursorInternal(keyRange, direction, getter_AddRefs(request)); michael@0: NS_ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: IndexedDBIndexRequestParent::OpenKeyCursor(const OpenKeyCursorParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TOpenKeyCursorParams); michael@0: MOZ_ASSERT(mIndex); michael@0: michael@0: const ipc::OptionalKeyRange keyRangeUnion = aParams.optionalKeyRange(); michael@0: michael@0: nsRefPtr keyRange; michael@0: michael@0: switch (keyRangeUnion.type()) { michael@0: case ipc::OptionalKeyRange::TKeyRange: michael@0: keyRange = michael@0: IDBKeyRange::FromSerializedKeyRange(keyRangeUnion.get_KeyRange()); michael@0: break; michael@0: michael@0: case ipc::OptionalKeyRange::Tvoid_t: michael@0: break; michael@0: michael@0: default: michael@0: MOZ_CRASH("Unknown param type!"); michael@0: } michael@0: michael@0: size_t direction = static_cast(aParams.direction()); michael@0: michael@0: nsRefPtr request; michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: request = mIndex->OpenKeyCursorInternal(keyRange, direction, rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: request->SetActor(this); michael@0: mRequest.swap(request); michael@0: return true; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBCursorRequestParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBCursorRequestParent::IndexedDBCursorRequestParent( michael@0: IDBCursor* aCursor, michael@0: RequestType aRequestType) michael@0: : mCursor(aCursor), mRequestType(aRequestType) michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBCursorRequestParent); michael@0: MOZ_ASSERT(aCursor); michael@0: MOZ_ASSERT(aRequestType > ParamsUnionType::T__None && michael@0: aRequestType <= ParamsUnionType::T__Last); michael@0: } michael@0: michael@0: IndexedDBCursorRequestParent::~IndexedDBCursorRequestParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBCursorRequestParent); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBCursorRequestParent::IsDisconnected() michael@0: { michael@0: MOZ_ASSERT(mCursor); michael@0: MOZ_ASSERT(mCursor->GetActorParent()); michael@0: return mCursor->GetActorParent()->IsDisconnected(); michael@0: } michael@0: michael@0: bool michael@0: IndexedDBCursorRequestParent::Continue(const ContinueParams& aParams) michael@0: { michael@0: MOZ_ASSERT(mCursor); michael@0: MOZ_ASSERT(mRequestType == ParamsUnionType::TContinueParams); michael@0: michael@0: { michael@0: AutoSetCurrentTransaction asct(mCursor->Transaction()); michael@0: michael@0: ErrorResult rv; michael@0: mCursor->ContinueInternal(aParams.key(), aParams.count(), rv); michael@0: ENSURE_SUCCESS(rv, false); michael@0: } michael@0: michael@0: mRequest = mCursor->Request(); michael@0: MOZ_ASSERT(mRequest); michael@0: michael@0: mRequest->SetActor(this); michael@0: return true; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * IndexedDBDeleteDatabaseRequestParent michael@0: ******************************************************************************/ michael@0: michael@0: IndexedDBDeleteDatabaseRequestParent::IndexedDBDeleteDatabaseRequestParent( michael@0: IDBFactory* aFactory) michael@0: : mEventListener(MOZ_THIS_IN_INITIALIZER_LIST()), mFactory(aFactory) michael@0: { michael@0: MOZ_COUNT_CTOR(IndexedDBDeleteDatabaseRequestParent); michael@0: MOZ_ASSERT(aFactory); michael@0: } michael@0: michael@0: IndexedDBDeleteDatabaseRequestParent::~IndexedDBDeleteDatabaseRequestParent() michael@0: { michael@0: MOZ_COUNT_DTOR(IndexedDBDeleteDatabaseRequestParent); michael@0: } michael@0: michael@0: nsresult michael@0: IndexedDBDeleteDatabaseRequestParent::HandleEvent(nsIDOMEvent* aEvent) michael@0: { michael@0: MOZ_ASSERT(aEvent); michael@0: michael@0: if (IsDisconnected()) { michael@0: // We're shutting down, ignore this event. michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsString type; michael@0: nsresult rv = aEvent->GetType(type); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: if (type.EqualsASCII(BLOCKED_EVT_STR)) { michael@0: nsCOMPtr event = do_QueryInterface(aEvent); michael@0: MOZ_ASSERT(event); michael@0: michael@0: uint64_t currentVersion = event->OldVersion(); michael@0: michael@0: if (!SendBlocked(currentVersion)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: if (type.EqualsASCII(SUCCESS_EVT_STR)) { michael@0: MOZ_ASSERT(NS_SUCCEEDED(mOpenRequest->GetErrorCode())); michael@0: } michael@0: else { michael@0: MOZ_ASSERT(type.EqualsASCII(ERROR_EVT_STR)); michael@0: MOZ_ASSERT(NS_FAILED(mOpenRequest->GetErrorCode())); michael@0: } michael@0: #endif michael@0: michael@0: if (!Send__delete__(this, mOpenRequest->GetErrorCode())) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: IndexedDBDeleteDatabaseRequestParent::SetOpenRequest( michael@0: IDBOpenDBRequest* aOpenRequest) michael@0: { michael@0: MOZ_ASSERT(aOpenRequest); michael@0: MOZ_ASSERT(!mOpenRequest); michael@0: michael@0: EventTarget* target = static_cast(aOpenRequest); michael@0: michael@0: nsresult rv = target->AddEventListener(NS_LITERAL_STRING(SUCCESS_EVT_STR), michael@0: mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = target->AddEventListener(NS_LITERAL_STRING(ERROR_EVT_STR), michael@0: mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = target->AddEventListener(NS_LITERAL_STRING(BLOCKED_EVT_STR), michael@0: mEventListener, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: mOpenRequest = aOpenRequest; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * WeakEventListener michael@0: ******************************************************************************/ michael@0: michael@0: NS_IMPL_ISUPPORTS(WeakEventListenerBase, nsIDOMEventListener) michael@0: michael@0: NS_IMETHODIMP michael@0: WeakEventListenerBase::HandleEvent(nsIDOMEvent* aEvent) michael@0: { michael@0: MOZ_CRASH("This must be overridden!"); michael@0: }