| Index: third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
|
| diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
|
| index 71ccf3d4f7fa6e7cf935eddf98135f78e28983c8..1775c2106a2be37c6b02fd6a49ca52ff2a79f208 100644
|
| --- a/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
|
| +++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp
|
| @@ -46,17 +46,19 @@ using blink::WebIDBDatabase;
|
|
|
| namespace blink {
|
|
|
| -IDBTransaction* IDBTransaction::create(ScriptState* scriptState, int64_t id, const HashSet<String>& objectStoreNames, WebIDBTransactionMode mode, IDBDatabase* db)
|
| +IDBTransaction* IDBTransaction::createNonVersionChange(ScriptState* scriptState, int64_t id, const HashSet<String>& scope, WebIDBTransactionMode mode, IDBDatabase* db)
|
| {
|
| + DCHECK_NE(mode, WebIDBTransactionModeVersionChange);
|
| + DCHECK(!scope.isEmpty()) << "Non-version transactions should operate on a well-defined set of stores";
|
| IDBOpenDBRequest* openDBRequest = nullptr;
|
| - IDBTransaction* transaction = new IDBTransaction(scriptState, id, objectStoreNames, mode, db, openDBRequest, IDBDatabaseMetadata());
|
| + IDBTransaction* transaction = new IDBTransaction(scriptState, id, scope, mode, db, openDBRequest, IDBDatabaseMetadata());
|
| transaction->suspendIfNeeded();
|
| return transaction;
|
| }
|
|
|
| -IDBTransaction* IDBTransaction::create(ScriptState* scriptState, int64_t id, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& previousMetadata)
|
| +IDBTransaction* IDBTransaction::createVersionChange(ScriptState* scriptState, int64_t id, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& oldMetadata)
|
| {
|
| - IDBTransaction* transaction = new IDBTransaction(scriptState, id, HashSet<String>(), WebIDBTransactionModeVersionChange, db, openDBRequest, previousMetadata);
|
| + IDBTransaction* transaction = new IDBTransaction(scriptState, id, HashSet<String>(), WebIDBTransactionModeVersionChange, db, openDBRequest, oldMetadata);
|
| transaction->suspendIfNeeded();
|
| return transaction;
|
| }
|
| @@ -85,19 +87,26 @@ private:
|
|
|
| } // namespace
|
|
|
| -IDBTransaction::IDBTransaction(ScriptState* scriptState, int64_t id, const HashSet<String>& objectStoreNames, WebIDBTransactionMode mode, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& previousMetadata)
|
| +IDBTransaction::IDBTransaction(ScriptState* scriptState, int64_t id, const HashSet<String>& scope, WebIDBTransactionMode mode, IDBDatabase* db, IDBOpenDBRequest* openDBRequest, const IDBDatabaseMetadata& oldMetadata)
|
| : ActiveScriptWrappable(this)
|
| , ActiveDOMObject(scriptState->getExecutionContext())
|
| , m_id(id)
|
| , m_database(db)
|
| - , m_objectStoreNames(objectStoreNames)
|
| , m_openDBRequest(openDBRequest)
|
| , m_mode(mode)
|
| - , m_previousMetadata(previousMetadata)
|
| + , m_scope(scope)
|
| + , m_oldDatabaseMetadata(oldMetadata)
|
| {
|
| - if (mode == WebIDBTransactionModeVersionChange) {
|
| + DCHECK(m_database);
|
| +
|
| + if (isVersionChange()) {
|
| + DCHECK(scope.isEmpty());
|
| +
|
| // Not active until the callback.
|
| m_state = Inactive;
|
| + } else {
|
| + DCHECK(!scope.isEmpty()) << "Non-versionchange transactions must operate on a well-defined set of stores";
|
| + DCHECK(m_mode == WebIDBTransactionModeReadOnly || m_mode == WebIDBTransactionModeReadWrite) << "Invalid transaction mode";
|
| }
|
|
|
| if (m_state == Active)
|
| @@ -107,8 +116,8 @@ IDBTransaction::IDBTransaction(ScriptState* scriptState, int64_t id, const HashS
|
|
|
| IDBTransaction::~IDBTransaction()
|
| {
|
| - ASSERT(m_state == Finished || m_contextStopped);
|
| - ASSERT(m_requestList.isEmpty() || m_contextStopped);
|
| + DCHECK(m_state == Finished || m_contextStopped);
|
| + DCHECK(m_requestList.isEmpty() || m_contextStopped);
|
| }
|
|
|
| DEFINE_TRACE(IDBTransaction)
|
| @@ -127,8 +136,8 @@ DEFINE_TRACE(IDBTransaction)
|
|
|
| void IDBTransaction::setError(DOMException* error)
|
| {
|
| - ASSERT(m_state != Finished);
|
| - ASSERT(error);
|
| + DCHECK_NE(m_state, Finished);
|
| + DCHECK(error);
|
|
|
| // The first error to be set is the true cause of the
|
| // transaction abort.
|
| @@ -139,7 +148,7 @@ void IDBTransaction::setError(DOMException* error)
|
|
|
| IDBObjectStore* IDBTransaction::objectStore(const String& name, ExceptionState& exceptionState)
|
| {
|
| - if (m_state == Finished) {
|
| + if (isFinished()) {
|
| exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transactionFinishedErrorMessage);
|
| return nullptr;
|
| }
|
| @@ -148,21 +157,23 @@ IDBObjectStore* IDBTransaction::objectStore(const String& name, ExceptionState&
|
| if (it != m_objectStoreMap.end())
|
| return it->value;
|
|
|
| - if (!isVersionChange() && !m_objectStoreNames.contains(name)) {
|
| + if (!isVersionChange() && !m_scope.contains(name)) {
|
| exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjectStoreErrorMessage);
|
| return nullptr;
|
| }
|
|
|
| int64_t objectStoreId = m_database->findObjectStoreId(name);
|
| if (objectStoreId == IDBObjectStoreMetadata::InvalidId) {
|
| - ASSERT(isVersionChange());
|
| + DCHECK(isVersionChange());
|
| exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjectStoreErrorMessage);
|
| return nullptr;
|
| }
|
|
|
| - const IDBDatabaseMetadata& metadata = m_database->metadata();
|
| + DCHECK(m_database->metadata().objectStores.contains(objectStoreId));
|
| + const IDBObjectStoreMetadata& objectStoreMetadata = m_database->metadata().objectStores.get(objectStoreId);
|
|
|
| - IDBObjectStore* objectStore = IDBObjectStore::create(metadata.objectStores.get(objectStoreId), this);
|
| + IDBObjectStore* objectStore = IDBObjectStore::create(objectStoreMetadata, this);
|
| + DCHECK(!m_objectStoreMap.contains(name));
|
| m_objectStoreMap.set(name, objectStore);
|
| m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
|
| return objectStore;
|
| @@ -170,8 +181,9 @@ IDBObjectStore* IDBTransaction::objectStore(const String& name, ExceptionState&
|
|
|
| void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* objectStore)
|
| {
|
| - ASSERT(m_state != Finished);
|
| - ASSERT(isVersionChange());
|
| + DCHECK_NE(m_state, Finished) << "A finished transaction created an object store";
|
| + DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchange transaction created an object store";
|
| + DCHECK(!m_objectStoreMap.contains(name)) << "An object store was created with the name of an existing store";
|
| m_objectStoreMap.set(name, objectStore);
|
| m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
|
| m_createdObjectStores.add(objectStore);
|
| @@ -179,8 +191,8 @@ void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* obje
|
|
|
| void IDBTransaction::objectStoreDeleted(const String& name)
|
| {
|
| - ASSERT(m_state != Finished);
|
| - ASSERT(isVersionChange());
|
| + DCHECK_NE(m_state, Finished) << "A finished transaction deleted an object store";
|
| + DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchange transaction deleted an object store";
|
| IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name);
|
| if (it != m_objectStoreMap.end()) {
|
| IDBObjectStore* objectStore = it->value;
|
| @@ -193,15 +205,12 @@ void IDBTransaction::objectStoreDeleted(const String& name)
|
|
|
| void IDBTransaction::objectStoreRenamed(const String& oldName, const String& newName)
|
| {
|
| - DCHECK(m_state != Finished);
|
| - DCHECK(isVersionChange());
|
| + DCHECK_NE(m_state, Finished) << "A finished transaction renamed an object store";
|
| + DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchange transaction renamed an object store";
|
|
|
| DCHECK(!m_objectStoreMap.contains(newName));
|
| DCHECK(m_objectStoreMap.contains(oldName)) << "The object store had to be accessed in order to be renamed.";
|
| -
|
| - IDBObjectStoreMap::iterator it = m_objectStoreMap.find(oldName);
|
| - m_objectStoreMap.set(newName, it->value);
|
| - m_objectStoreMap.remove(oldName);
|
| + m_objectStoreMap.set(newName, m_objectStoreMap.take(oldName));
|
| }
|
|
|
| void IDBTransaction::setActive(bool active)
|
| @@ -209,7 +218,7 @@ void IDBTransaction::setActive(bool active)
|
| DCHECK_NE(m_state, Finished) << "A finished transaction tried to setActive(" << (active ? "true" : "false") << ")";
|
| if (m_state == Finishing)
|
| return;
|
| - ASSERT(active != (m_state == Active));
|
| + DCHECK_NE(active, (m_state == Active));
|
| m_state = active ? Active : Inactive;
|
|
|
| if (!active && m_requestList.isEmpty() && backendDB())
|
| @@ -228,14 +237,8 @@ void IDBTransaction::abort(ExceptionState& exceptionState)
|
| if (m_contextStopped)
|
| return;
|
|
|
| - for (IDBRequest* request : m_requestList)
|
| - request->abort();
|
| - m_requestList.clear();
|
| -
|
| - for (IDBObjectStore* store : m_createdObjectStores) {
|
| - store->abort();
|
| - store->markDeleted();
|
| - }
|
| + abortOutstandingRequests();
|
| + revertDatabaseMetadata();
|
|
|
| if (backendDB())
|
| backendDB()->abort(m_id);
|
| @@ -243,14 +246,14 @@ void IDBTransaction::abort(ExceptionState& exceptionState)
|
|
|
| void IDBTransaction::registerRequest(IDBRequest* request)
|
| {
|
| - ASSERT(request);
|
| - ASSERT(m_state == Active);
|
| + DCHECK(request);
|
| + DCHECK_EQ(m_state, Active);
|
| m_requestList.add(request);
|
| }
|
|
|
| void IDBTransaction::unregisterRequest(IDBRequest* request)
|
| {
|
| - ASSERT(request);
|
| + DCHECK(request);
|
| // If we aborted the request, it will already have been removed.
|
| m_requestList.remove(request);
|
| }
|
| @@ -259,62 +262,44 @@ void IDBTransaction::onAbort(DOMException* error)
|
| {
|
| IDB_TRACE("IDBTransaction::onAbort");
|
| if (m_contextStopped) {
|
| - m_database->transactionFinished(this);
|
| + finished();
|
| return;
|
| }
|
|
|
| - ASSERT(m_state != Finished);
|
| + DCHECK_NE(m_state, Finished);
|
| if (m_state != Finishing) {
|
| // Abort was not triggered by front-end.
|
| - ASSERT(error);
|
| + DCHECK(error);
|
| setError(error);
|
|
|
| - // Outstanding requests must be aborted.
|
| - for (IDBRequest* request : m_requestList)
|
| - request->abort();
|
| - m_requestList.clear();
|
| -
|
| - // Newly created stores must be marked as deleted.
|
| - for (IDBObjectStore* store : m_createdObjectStores)
|
| - store->markDeleted();
|
| -
|
| - // Used stores may need to mark indexes as deleted.
|
| - for (auto& it : m_objectStoreCleanupMap)
|
| - it.key->abort();
|
| + abortOutstandingRequests();
|
| + revertDatabaseMetadata();
|
|
|
| m_state = Finishing;
|
| }
|
|
|
| - if (isVersionChange()) {
|
| - for (auto& it : m_objectStoreCleanupMap)
|
| - it.key->setMetadata(it.value);
|
| - m_database->setMetadata(m_previousMetadata);
|
| + if (isVersionChange())
|
| m_database->close();
|
| - }
|
| - m_objectStoreCleanupMap.clear();
|
|
|
| // Enqueue events before notifying database, as database may close which enqueues more events and order matters.
|
| enqueueEvent(Event::createBubble(EventTypeNames::abort));
|
| -
|
| - m_database->transactionFinished(this);
|
| + finished();
|
| }
|
|
|
| void IDBTransaction::onComplete()
|
| {
|
| IDB_TRACE("IDBTransaction::onComplete");
|
| if (m_contextStopped) {
|
| - m_database->transactionFinished(this);
|
| + finished();
|
| return;
|
| }
|
|
|
| - ASSERT(m_state != Finished);
|
| + DCHECK_NE(m_state, Finished);
|
| m_state = Finishing;
|
| - m_objectStoreCleanupMap.clear();
|
|
|
| // Enqueue events before notifying database, as database may close which enqueues more events and order matters.
|
| enqueueEvent(Event::create(EventTypeNames::complete));
|
| -
|
| - m_database->transactionFinished(this);
|
| + finished();
|
| }
|
|
|
| bool IDBTransaction::hasPendingActivity() const
|
| @@ -333,7 +318,7 @@ WebIDBTransactionMode IDBTransaction::stringToMode(const String& modeString)
|
| return WebIDBTransactionModeReadWrite;
|
| if (modeString == IndexedDBNames::versionchange)
|
| return WebIDBTransactionModeVersionChange;
|
| - ASSERT_NOT_REACHED();
|
| + NOTREACHED();
|
| return WebIDBTransactionModeReadOnly;
|
| }
|
|
|
| @@ -350,18 +335,23 @@ const String& IDBTransaction::mode() const
|
| return IndexedDBNames::versionchange;
|
| }
|
|
|
| - ASSERT_NOT_REACHED();
|
| + NOTREACHED();
|
| return IndexedDBNames::readonly;
|
| }
|
|
|
| +WebIDBDatabase* IDBTransaction::backendDB() const
|
| +{
|
| + return m_database->backend();
|
| +}
|
| +
|
| DOMStringList* IDBTransaction::objectStoreNames() const
|
| {
|
| - if (m_mode == WebIDBTransactionModeVersionChange)
|
| + if (isVersionChange())
|
| return m_database->objectStoreNames();
|
|
|
| DOMStringList* objectStoreNames = DOMStringList::create(DOMStringList::IndexedDB);
|
| - for (const String& name : m_objectStoreNames)
|
| - objectStoreNames->append(name);
|
| + for (const String& objectStoreName : m_scope)
|
| + objectStoreNames->append(objectStoreName);
|
| objectStoreNames->sort();
|
| return objectStoreNames;
|
| }
|
| @@ -383,33 +373,23 @@ DispatchEventResult IDBTransaction::dispatchEventInternal(Event* event)
|
| m_state = Finished;
|
| return DispatchEventResult::CanceledBeforeDispatch;
|
| }
|
| - ASSERT(m_state != Finished);
|
| - ASSERT(m_hasPendingActivity);
|
| - ASSERT(getExecutionContext());
|
| - ASSERT(event->target() == this);
|
| + DCHECK_NE(m_state, Finished);
|
| + DCHECK(m_hasPendingActivity);
|
| + DCHECK(getExecutionContext());
|
| + DCHECK_EQ(event->target(), this);
|
| m_state = Finished;
|
|
|
| - // Break reference cycles.
|
| - // TODO(jsbell): This can be removed c/o Oilpan.
|
| - for (auto& it : m_objectStoreMap)
|
| - it.value->transactionFinished();
|
| - m_objectStoreMap.clear();
|
| - for (auto& it : m_deletedObjectStores)
|
| - it->transactionFinished();
|
| - m_createdObjectStores.clear();
|
| - m_deletedObjectStores.clear();
|
| -
|
| HeapVector<Member<EventTarget>> targets;
|
| targets.append(this);
|
| targets.append(db());
|
|
|
| // FIXME: When we allow custom event dispatching, this will probably need to change.
|
| - ASSERT(event->type() == EventTypeNames::complete || event->type() == EventTypeNames::abort);
|
| + DCHECK(event->type() == EventTypeNames::complete || event->type() == EventTypeNames::abort);
|
| DispatchEventResult dispatchResult = IDBEventDispatcher::dispatch(event, targets);
|
| // FIXME: Try to construct a test where |this| outlives openDBRequest and we
|
| // get a crash.
|
| if (m_openDBRequest) {
|
| - ASSERT(isVersionChange());
|
| + DCHECK(isVersionChange());
|
| m_openDBRequest->transactionDidFinishAndDispatch();
|
| }
|
| m_hasPendingActivity = false;
|
| @@ -437,9 +417,54 @@ void IDBTransaction::enqueueEvent(Event* event)
|
| eventQueue->enqueueEvent(event);
|
| }
|
|
|
| -WebIDBDatabase* IDBTransaction::backendDB() const
|
| +void IDBTransaction::abortOutstandingRequests()
|
| {
|
| - return m_database->backend();
|
| + for (IDBRequest* request : m_requestList)
|
| + request->abort();
|
| + m_requestList.clear();
|
| +}
|
| +
|
| +void IDBTransaction::revertDatabaseMetadata()
|
| +{
|
| + DCHECK_NE(m_state, Active);
|
| + if (!isVersionChange())
|
| + return;
|
| +
|
| + // Newly created stores must be marked as deleted.
|
| + for (IDBObjectStore* store : m_createdObjectStores) {
|
| + store->abort();
|
| + store->markDeleted();
|
| + }
|
| +
|
| + // Used stores may need to mark indexes as deleted.
|
| + for (auto& it : m_objectStoreCleanupMap) {
|
| + it.key->abort();
|
| + it.key->setMetadata(it.value);
|
| + }
|
| +
|
| + m_database->setMetadata(m_oldDatabaseMetadata);
|
| +}
|
| +
|
| +void IDBTransaction::finished()
|
| +{
|
| +#if DCHECK_IS_ON()
|
| + DCHECK(!m_finishCalled);
|
| + m_finishCalled = true;
|
| +#endif // DCHECK_IS_ON()
|
| +
|
| + m_database->transactionFinished(this);
|
| +
|
| + // Break reference cycles.
|
| + // TODO(jsbell): This can be removed c/o Oilpan.
|
| + for (auto& it : m_objectStoreMap)
|
| + it.value->transactionFinished();
|
| + m_objectStoreMap.clear();
|
| + for (auto& it : m_deletedObjectStores)
|
| + it->transactionFinished();
|
| + m_createdObjectStores.clear();
|
| + m_deletedObjectStores.clear();
|
| +
|
| + m_objectStoreCleanupMap.clear();
|
| }
|
|
|
| } // namespace blink
|
|
|