summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/indexeddb/IDBTransaction.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/Modules/indexeddb/IDBTransaction.h')
-rw-r--r--Source/WebCore/Modules/indexeddb/IDBTransaction.h375
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