diff options
Diffstat (limited to 'Source/WebCore/Modules/indexeddb/IDBTransaction.h')
-rw-r--r-- | Source/WebCore/Modules/indexeddb/IDBTransaction.h | 375 |
1 files changed, 243 insertions, 132 deletions
diff --git a/Source/WebCore/Modules/indexeddb/IDBTransaction.h b/Source/WebCore/Modules/indexeddb/IDBTransaction.h index f6e4ad98c..af96c4cd9 100644 --- a/Source/WebCore/Modules/indexeddb/IDBTransaction.h +++ b/Source/WebCore/Modules/indexeddb/IDBTransaction.h @@ -1,174 +1,285 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef IDBTransaction_h -#define IDBTransaction_h +#pragma once #if ENABLE(INDEXED_DATABASE) -#include "ActiveDOMObject.h" -#include "DOMError.h" -#include "Event.h" -#include "EventListener.h" -#include "EventNames.h" #include "EventTarget.h" -#include "IDBDatabaseMetadata.h" +#include "IDBActiveDOMObject.h" +#include "IDBError.h" +#include "IDBGetAllRecordsData.h" +#include "IDBGetRecordData.h" +#include "IDBKeyRangeData.h" +#include "IDBOpenDBRequest.h" +#include "IDBTransactionInfo.h" +#include "IDBTransactionMode.h" #include "IndexedDB.h" -#include "ScriptWrappable.h" -#include <wtf/HashSet.h> -#include <wtf/RefCounted.h> +#include "Timer.h" +#include <wtf/Deque.h> +#include <wtf/HashMap.h> namespace WebCore { +class DOMError; +class DOMStringList; class IDBCursor; +class IDBCursorInfo; class IDBDatabase; -class IDBDatabaseBackend; -class IDBDatabaseError; +class IDBIndex; +class IDBIndexInfo; +class IDBKey; +class IDBKeyData; class IDBObjectStore; -class IDBOpenDBRequest; -struct IDBObjectStoreMetadata; +class IDBObjectStoreInfo; +class IDBResultData; +class SerializedScriptValue; -class IDBTransaction final : public ScriptWrappable, public RefCounted<IDBTransaction>, public EventTargetWithInlineData, public ActiveDOMObject { -public: - static PassRefPtr<IDBTransaction> create(ScriptExecutionContext*, int64_t, const Vector<String>& objectStoreNames, IndexedDB::TransactionMode, IDBDatabase*); - static PassRefPtr<IDBTransaction> create(ScriptExecutionContext*, int64_t, IDBDatabase*, IDBOpenDBRequest*, const IDBDatabaseMetadata& previousMetadata); - virtual ~IDBTransaction(); - - static const AtomicString& modeReadOnly(); - static const AtomicString& modeReadWrite(); - static const AtomicString& modeVersionChange(); - static const AtomicString& modeReadOnlyLegacy(); - static const AtomicString& modeReadWriteLegacy(); - - static IndexedDB::TransactionMode stringToMode(const String&, ExceptionCode&); - static const AtomicString& modeToString(IndexedDB::TransactionMode); - - IDBDatabaseBackend* backendDB() const; - - int64_t id() const { return m_id; } - bool isActive() const { return m_state == Active; } - bool isFinished() const { return m_state == Finished; } - bool isReadOnly() const { return m_mode == IndexedDB::TransactionMode::ReadOnly; } - bool isVersionChange() const { return m_mode == IndexedDB::TransactionMode::VersionChange; } - - // Implement the IDBTransaction IDL - const String& mode() const; - IDBDatabase* db() const { return m_database.get(); } - PassRefPtr<DOMError> error() const { return m_error; } - PassRefPtr<IDBObjectStore> objectStore(const String& name, ExceptionCode&); - void abort(ExceptionCode&); - - class OpenCursorNotifier { - public: - OpenCursorNotifier(PassRefPtr<IDBTransaction>, IDBCursor*); - ~OpenCursorNotifier(); - void cursorFinished(); - private: - RefPtr<IDBTransaction> m_transaction; - IDBCursor* m_cursor; - }; - - void registerRequest(IDBRequest*); - void unregisterRequest(IDBRequest*); - void objectStoreCreated(const String&, PassRefPtr<IDBObjectStore>); - void objectStoreDeleted(const String&); - void setActive(bool); - void setError(PassRefPtr<DOMError>, const String& errorMessage); - - DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); - DEFINE_ATTRIBUTE_EVENT_LISTENER(complete); - DEFINE_ATTRIBUTE_EVENT_LISTENER(error); - - void onAbort(PassRefPtr<IDBDatabaseError>); - void onComplete(); - - // EventTarget - virtual EventTargetInterface eventTargetInterface() const override { return IDBTransactionEventTargetInterfaceType; } - virtual ScriptExecutionContext* scriptExecutionContext() const override { return ActiveDOMObject::scriptExecutionContext(); } +struct IDBIterateCursorData; +struct IDBKeyRangeData; + +namespace IDBClient { +class IDBConnectionProxy; +class TransactionOperation; +} +class IDBTransaction : public ThreadSafeRefCounted<IDBTransaction>, public EventTargetWithInlineData, public IDBActiveDOMObject { +public: + static Ref<IDBTransaction> create(IDBDatabase&, const IDBTransactionInfo&); + static Ref<IDBTransaction> create(IDBDatabase&, const IDBTransactionInfo&, IDBOpenDBRequest&); + + ~IDBTransaction() final; + + // IDBTransaction IDL + Ref<DOMStringList> objectStoreNames() const; + IDBTransactionMode mode() const { return m_info.mode(); } + IDBDatabase* db(); + DOMError* error() const; + ExceptionOr<Ref<IDBObjectStore>> objectStore(const String& name); + ExceptionOr<void> abort(); + + EventTargetInterface eventTargetInterface() const final { return IDBTransactionEventTargetInterfaceType; } + ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); } + void refEventTarget() final { ThreadSafeRefCounted::ref(); } + void derefEventTarget() final { ThreadSafeRefCounted::deref(); } using EventTarget::dispatchEvent; - virtual bool dispatchEvent(PassRefPtr<Event>) override; + bool dispatchEvent(Event&) final; + + using ThreadSafeRefCounted<IDBTransaction>::ref; + using ThreadSafeRefCounted<IDBTransaction>::deref; + + const char* activeDOMObjectName() const final; + bool canSuspendForDocumentSuspension() const final; + bool hasPendingActivity() const final; + void stop() final; + + const IDBTransactionInfo& info() const { return m_info; } + IDBDatabase& database() { return m_database.get(); } + const IDBDatabase& database() const { return m_database.get(); } + IDBDatabaseInfo* originalDatabaseInfo() const { return m_info.originalDatabaseInfo(); } + + void didStart(const IDBError&); + void didAbort(const IDBError&); + void didCommit(const IDBError&); + + bool isVersionChange() const { return mode() == IDBTransactionMode::Versionchange; } + bool isReadOnly() const { return mode() == IDBTransactionMode::Readonly; } + bool isActive() const; + + Ref<IDBObjectStore> createObjectStore(const IDBObjectStoreInfo&); + void renameObjectStore(IDBObjectStore&, const String& newName); + std::unique_ptr<IDBIndex> createIndex(IDBObjectStore&, const IDBIndexInfo&); + void renameIndex(IDBIndex&, const String& newName); + + Ref<IDBRequest> requestPutOrAdd(JSC::ExecState&, IDBObjectStore&, IDBKey*, SerializedScriptValue&, IndexedDB::ObjectStoreOverwriteMode); + Ref<IDBRequest> requestGetRecord(JSC::ExecState&, IDBObjectStore&, const IDBGetRecordData&); + Ref<IDBRequest> requestGetAllObjectStoreRecords(JSC::ExecState&, IDBObjectStore&, const IDBKeyRangeData&, IndexedDB::GetAllType, std::optional<uint32_t> count); + Ref<IDBRequest> requestGetAllIndexRecords(JSC::ExecState&, IDBIndex&, const IDBKeyRangeData&, IndexedDB::GetAllType, std::optional<uint32_t> count); + Ref<IDBRequest> requestDeleteRecord(JSC::ExecState&, IDBObjectStore&, const IDBKeyRangeData&); + Ref<IDBRequest> requestClearObjectStore(JSC::ExecState&, IDBObjectStore&); + Ref<IDBRequest> requestCount(JSC::ExecState&, IDBObjectStore&, const IDBKeyRangeData&); + Ref<IDBRequest> requestCount(JSC::ExecState&, IDBIndex&, const IDBKeyRangeData&); + Ref<IDBRequest> requestGetValue(JSC::ExecState&, IDBIndex&, const IDBKeyRangeData&); + Ref<IDBRequest> requestGetKey(JSC::ExecState&, IDBIndex&, const IDBKeyRangeData&); + Ref<IDBRequest> requestOpenCursor(JSC::ExecState&, IDBObjectStore&, const IDBCursorInfo&); + Ref<IDBRequest> requestOpenCursor(JSC::ExecState&, IDBIndex&, const IDBCursorInfo&); + void iterateCursor(IDBCursor&, const IDBIterateCursorData&); + + void deleteObjectStore(const String& objectStoreName); + void deleteIndex(uint64_t objectStoreIdentifier, const String& indexName); - // ActiveDOMObject - virtual bool hasPendingActivity() const override; + void addRequest(IDBRequest&); + void removeRequest(IDBRequest&); - using RefCounted<IDBTransaction>::ref; - using RefCounted<IDBTransaction>::deref; + void abortDueToFailedRequest(DOMError&); + + void activate(); + void deactivate(); + + void operationCompletedOnServer(const IDBResultData&, IDBClient::TransactionOperation&); + void operationCompletedOnClient(IDBClient::TransactionOperation&); + + void finishedDispatchEventForRequest(IDBRequest&); + + bool isFinishedOrFinishing() const; + bool isFinished() const { return m_state == IndexedDB::TransactionState::Finished; } + + IDBClient::IDBConnectionProxy& connectionProxy(); + + void connectionClosedFromServer(const IDBError&); + + void visitReferencedObjectStores(JSC::SlotVisitor&) const; private: - IDBTransaction(ScriptExecutionContext*, int64_t, const Vector<String>&, IndexedDB::TransactionMode, IDBDatabase*, IDBOpenDBRequest*, const IDBDatabaseMetadata&); + IDBTransaction(IDBDatabase&, const IDBTransactionInfo&, IDBOpenDBRequest*); + + void commit(); + + void internalAbort(); + void notifyDidAbort(const IDBError&); + void finishAbortOrCommit(); + void abortInProgressOperations(const IDBError&); + + void scheduleOperation(RefPtr<IDBClient::TransactionOperation>&&); + void pendingOperationTimerFired(); + void completedOperationTimerFired(); + + void fireOnComplete(); + void fireOnAbort(); + void enqueueEvent(Ref<Event>&&); + + Ref<IDBRequest> requestIndexRecord(JSC::ExecState&, IDBIndex&, IndexedDB::IndexRecordType, const IDBKeyRangeData&); - void enqueueEvent(PassRefPtr<Event>); - void closeOpenCursors(); + void commitOnServer(IDBClient::TransactionOperation&); + void abortOnServerAndCancelRequests(IDBClient::TransactionOperation&); - void registerOpenCursor(IDBCursor*); - void unregisterOpenCursor(IDBCursor*); + void createObjectStoreOnServer(IDBClient::TransactionOperation&, const IDBObjectStoreInfo&); + void didCreateObjectStoreOnServer(const IDBResultData&); - // ActiveDOMObject - virtual bool canSuspend() const override; - virtual void stop() override; + void renameObjectStoreOnServer(IDBClient::TransactionOperation&, const uint64_t& objectStoreIdentifier, const String& newName); + void didRenameObjectStoreOnServer(const IDBResultData&); - // EventTarget - virtual void refEventTarget() override { ref(); } - virtual void derefEventTarget() override { deref(); } + void createIndexOnServer(IDBClient::TransactionOperation&, const IDBIndexInfo&); + void didCreateIndexOnServer(const IDBResultData&); - enum State { - Inactive, // Created or started, but not in an event callback - Active, // Created or started, in creation scope or an event callback - Finishing, // In the process of aborting or completing. - Finished, // No more events will fire and no new requests may be filed. - }; + void renameIndexOnServer(IDBClient::TransactionOperation&, const uint64_t& objectStoreIdentifier, const uint64_t& indexIdentifier, const String& newName); + void didRenameIndexOnServer(const IDBResultData&); - int64_t m_id; - RefPtr<IDBDatabase> m_database; - const Vector<String> m_objectStoreNames; - IDBOpenDBRequest* m_openDBRequest; - const IndexedDB::TransactionMode m_mode; - State m_state; - bool m_hasPendingActivity; - bool m_contextStopped; - RefPtr<DOMError> m_error; - String m_errorMessage; + void clearObjectStoreOnServer(IDBClient::TransactionOperation&, const uint64_t& objectStoreIdentifier); + void didClearObjectStoreOnServer(IDBRequest&, const IDBResultData&); - ListHashSet<RefPtr<IDBRequest>> m_requestList; + void putOrAddOnServer(IDBClient::TransactionOperation&, RefPtr<IDBKey>, RefPtr<SerializedScriptValue>, const IndexedDB::ObjectStoreOverwriteMode&); + void didPutOrAddOnServer(IDBRequest&, const IDBResultData&); - typedef HashMap<String, RefPtr<IDBObjectStore>> IDBObjectStoreMap; - IDBObjectStoreMap m_objectStoreMap; + void getRecordOnServer(IDBClient::TransactionOperation&, const IDBGetRecordData&); + void didGetRecordOnServer(IDBRequest&, const IDBResultData&); - typedef HashSet<RefPtr<IDBObjectStore>> IDBObjectStoreSet; - IDBObjectStoreSet m_deletedObjectStores; + void getAllRecordsOnServer(IDBClient::TransactionOperation&, const IDBGetAllRecordsData&); + void didGetAllRecordsOnServer(IDBRequest&, const IDBResultData&); - typedef HashMap<RefPtr<IDBObjectStore>, IDBObjectStoreMetadata> IDBObjectStoreMetadataMap; - IDBObjectStoreMetadataMap m_objectStoreCleanupMap; - IDBDatabaseMetadata m_previousMetadata; + void getCountOnServer(IDBClient::TransactionOperation&, const IDBKeyRangeData&); + void didGetCountOnServer(IDBRequest&, const IDBResultData&); - HashSet<IDBCursor*> m_openCursors; + void deleteRecordOnServer(IDBClient::TransactionOperation&, const IDBKeyRangeData&); + void didDeleteRecordOnServer(IDBRequest&, const IDBResultData&); + + void deleteObjectStoreOnServer(IDBClient::TransactionOperation&, const String& objectStoreName); + void didDeleteObjectStoreOnServer(const IDBResultData&); + + void deleteIndexOnServer(IDBClient::TransactionOperation&, const uint64_t& objectStoreIdentifier, const String& indexName); + void didDeleteIndexOnServer(const IDBResultData&); + + Ref<IDBRequest> doRequestOpenCursor(JSC::ExecState&, Ref<IDBCursor>&&); + void openCursorOnServer(IDBClient::TransactionOperation&, const IDBCursorInfo&); + void didOpenCursorOnServer(IDBRequest&, const IDBResultData&); + + void iterateCursorOnServer(IDBClient::TransactionOperation&, const IDBIterateCursorData&); + void didIterateCursorOnServer(IDBRequest&, const IDBResultData&); + + void transitionedToFinishing(IndexedDB::TransactionState); + + void establishOnServer(); + + void completeNoncursorRequest(IDBRequest&, const IDBResultData&); + void completeCursorRequest(IDBRequest&, const IDBResultData&); + + void schedulePendingOperationTimer(); + void scheduleCompletedOperationTimer(); + + Ref<IDBDatabase> m_database; + IDBTransactionInfo m_info; + + IndexedDB::TransactionState m_state { IndexedDB::TransactionState::Inactive }; + bool m_startedOnServer { false }; + + IDBError m_idbError; + RefPtr<DOMError> m_domError; + + Timer m_pendingOperationTimer; + Timer m_completedOperationTimer; + std::unique_ptr<Timer> m_activationTimer; + + RefPtr<IDBOpenDBRequest> m_openDBRequest; + + Deque<RefPtr<IDBClient::TransactionOperation>> m_pendingTransactionOperationQueue; + Deque<IDBClient::TransactionOperation*> m_transactionOperationsInProgressQueue; + Deque<std::pair<RefPtr<IDBClient::TransactionOperation>, IDBResultData>> m_completedOnServerQueue; + Deque<RefPtr<IDBClient::TransactionOperation>> m_abortQueue; + + HashMap<IDBResourceIdentifier, RefPtr<IDBClient::TransactionOperation>> m_transactionOperationMap; + + mutable Lock m_referencedObjectStoreLock; + HashMap<String, std::unique_ptr<IDBObjectStore>> m_referencedObjectStores; + HashMap<uint64_t, std::unique_ptr<IDBObjectStore>> m_deletedObjectStores; + + HashSet<RefPtr<IDBRequest>> m_openRequests; + RefPtr<IDBRequest> m_currentlyCompletingRequest; + + bool m_contextStopped { false }; +}; + +class TransactionActivator { + WTF_MAKE_NONCOPYABLE(TransactionActivator); +public: + TransactionActivator(IDBTransaction* transaction) + : m_transaction(transaction) + { + if (m_transaction) + m_transaction->activate(); + } + + ~TransactionActivator() + { + if (m_transaction) + m_transaction->deactivate(); + } + +private: + IDBTransaction* m_transaction; }; } // namespace WebCore #endif // ENABLE(INDEXED_DATABASE) - -#endif // IDBTransaction_h |