2 * Copyright (C) 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "IDBTransactionImpl.h"
29 #if ENABLE(INDEXED_DATABASE)
32 #include "EventQueue.h"
33 #include "IDBCursorWithValueImpl.h"
34 #include "IDBDatabaseImpl.h"
36 #include "IDBEventDispatcher.h"
37 #include "IDBKeyData.h"
38 #include "IDBKeyRangeData.h"
39 #include "IDBObjectStore.h"
40 #include "IDBOpenDBRequestImpl.h"
41 #include "IDBRequestImpl.h"
42 #include "IDBResultData.h"
43 #include "JSDOMWindowBase.h"
45 #include "ScriptExecutionContext.h"
46 #include "TransactionOperation.h"
51 Ref<IDBTransaction> IDBTransaction::create(IDBDatabase& database, const IDBTransactionInfo& info)
53 return adoptRef(*new IDBTransaction(database, info, nullptr));
56 Ref<IDBTransaction> IDBTransaction::create(IDBDatabase& database, const IDBTransactionInfo& info, IDBOpenDBRequest& request)
58 return adoptRef(*new IDBTransaction(database, info, &request));
61 IDBTransaction::IDBTransaction(IDBDatabase& database, const IDBTransactionInfo& info, IDBOpenDBRequest* request)
62 : WebCore::IDBTransaction(database.scriptExecutionContext())
63 , m_database(database)
65 , m_operationTimer(*this, &IDBTransaction::operationTimerFired)
66 , m_openDBRequest(request)
69 relaxAdoptionRequirement();
71 if (m_info.mode() == IndexedDB::TransactionMode::VersionChange) {
72 ASSERT(m_openDBRequest);
73 m_originalDatabaseInfo = std::make_unique<IDBDatabaseInfo>(m_database->info());
74 m_startedOnServer = true;
78 RefPtr<IDBTransaction> self;
79 JSC::VM& vm = JSDOMWindowBase::commonVM();
80 vm.whenIdle([self, this]() {
90 IDBTransaction::~IDBTransaction()
94 const String& IDBTransaction::mode() const
96 switch (m_info.mode()) {
97 case IndexedDB::TransactionMode::ReadOnly:
98 return IDBTransaction::modeReadOnly();
99 case IndexedDB::TransactionMode::ReadWrite:
100 return IDBTransaction::modeReadWrite();
101 case IndexedDB::TransactionMode::VersionChange:
102 return IDBTransaction::modeVersionChange();
105 RELEASE_ASSERT_NOT_REACHED();
108 WebCore::IDBDatabase* IDBTransaction::db()
110 return &m_database.get();
113 IDBConnectionToServer& IDBTransaction::serverConnection()
115 return m_database->serverConnection();
118 RefPtr<DOMError> IDBTransaction::error() const
120 ASSERT_NOT_REACHED();
124 RefPtr<WebCore::IDBObjectStore> IDBTransaction::objectStore(const String& objectStoreName, ExceptionCode& ec)
126 LOG(IndexedDB, "IDBTransaction::objectStore");
128 if (objectStoreName.isEmpty()) {
133 if (isFinishedOrFinishing()) {
134 ec = INVALID_STATE_ERR;
138 auto iterator = m_referencedObjectStores.find(objectStoreName);
139 if (iterator != m_referencedObjectStores.end())
140 return iterator->value;
143 for (auto& objectStore : m_info.objectStores()) {
144 if (objectStore == objectStoreName) {
150 auto* info = m_database->info().infoForExistingObjectStore(objectStoreName);
156 // Version change transactions are scoped to every object store in the database.
157 if (!found && !isVersionChange()) {
162 auto objectStore = IDBObjectStore::create(*info, *this);
163 m_referencedObjectStores.set(objectStoreName, &objectStore.get());
165 return adoptRef(&objectStore.leakRef());
168 void IDBTransaction::abort(ExceptionCode& ec)
170 LOG(IndexedDB, "IDBTransaction::abort");
172 if (isFinishedOrFinishing()) {
173 ec = INVALID_STATE_ERR;
177 m_state = IndexedDB::TransactionState::Aborting;
178 m_database->willAbortTransaction(*this);
180 m_abortQueue.swap(m_transactionOperationQueue);
182 auto operation = createTransactionOperation(*this, nullptr, &IDBTransaction::abortOnServerAndCancelRequests);
183 scheduleOperation(WTF::move(operation));
186 void IDBTransaction::abortOnServerAndCancelRequests(TransactionOperation&)
188 LOG(IndexedDB, "IDBTransaction::abortOnServerAndCancelRequests");
190 ASSERT(m_transactionOperationQueue.isEmpty());
192 serverConnection().abortTransaction(*this);
194 IDBError error(IDBExceptionCode::AbortError);
195 for (auto& operation : m_abortQueue)
196 operation->completed(IDBResultData::error(operation->identifier(), error));
198 // Since we're aborting, this abortOnServerAndCancelRequests() operation should be the only
199 // in-progress operation, and it should be impossible to have queued any further operations.
200 ASSERT(m_transactionOperationMap.size() == 1);
201 ASSERT(m_transactionOperationQueue.isEmpty());
204 const char* IDBTransaction::activeDOMObjectName() const
206 return "IDBTransaction";
209 bool IDBTransaction::canSuspendForPageCache() const
214 bool IDBTransaction::hasPendingActivity() const
216 return m_state != IndexedDB::TransactionState::Finished;
219 bool IDBTransaction::isActive() const
221 return m_state == IndexedDB::TransactionState::Active;
224 bool IDBTransaction::isFinishedOrFinishing() const
226 return m_state == IndexedDB::TransactionState::Committing
227 || m_state == IndexedDB::TransactionState::Aborting
228 || m_state == IndexedDB::TransactionState::Finished;
231 void IDBTransaction::addRequest(IDBRequest& request)
233 m_openRequests.add(&request);
236 void IDBTransaction::removeRequest(IDBRequest& request)
238 ASSERT(m_openRequests.contains(&request));
239 m_openRequests.remove(&request);
242 void IDBTransaction::scheduleOperation(RefPtr<TransactionOperation>&& operation)
244 ASSERT(!m_transactionOperationMap.contains(operation->identifier()));
246 m_transactionOperationQueue.append(operation);
247 m_transactionOperationMap.set(operation->identifier(), WTF::move(operation));
249 scheduleOperationTimer();
252 void IDBTransaction::scheduleOperationTimer()
254 if (!m_operationTimer.isActive())
255 m_operationTimer.startOneShot(0);
258 void IDBTransaction::operationTimerFired()
260 LOG(IndexedDB, "IDBTransaction::operationTimerFired (%p)", this);
262 if (!m_startedOnServer)
265 if (!m_transactionOperationQueue.isEmpty()) {
266 auto operation = m_transactionOperationQueue.takeFirst();
267 operation->perform();
272 if (!m_transactionOperationMap.isEmpty() || !m_openRequests.isEmpty())
275 if (!isFinishedOrFinishing())
279 void IDBTransaction::commit()
281 LOG(IndexedDB, "IDBTransaction::commit");
283 ASSERT(!isFinishedOrFinishing());
285 m_state = IndexedDB::TransactionState::Committing;
286 m_database->willCommitTransaction(*this);
288 auto operation = createTransactionOperation(*this, nullptr, &IDBTransaction::commitOnServer);
289 scheduleOperation(WTF::move(operation));
292 void IDBTransaction::commitOnServer(TransactionOperation&)
294 LOG(IndexedDB, "IDBTransaction::commitOnServer");
295 serverConnection().commitTransaction(*this);
298 void IDBTransaction::finishAbortOrCommit()
300 ASSERT(m_state != IndexedDB::TransactionState::Finished);
301 m_state = IndexedDB::TransactionState::Finished;
303 m_originalDatabaseInfo = nullptr;
306 void IDBTransaction::didStart(const IDBError& error)
308 LOG(IndexedDB, "IDBTransaction::didStart");
310 m_database->didStartTransaction(*this);
312 m_startedOnServer = true;
314 // It's possible the transaction failed to start on the server.
315 // That equates to an abort.
316 if (!error.isNull()) {
321 scheduleOperationTimer();
324 void IDBTransaction::didAbort(const IDBError& error)
326 LOG(IndexedDB, "IDBTransaction::didAbort");
328 if (m_state == IndexedDB::TransactionState::Finished)
331 m_database->didAbortTransaction(*this);
336 finishAbortOrCommit();
339 void IDBTransaction::didCommit(const IDBError& error)
341 LOG(IndexedDB, "IDBTransaction::didCommit");
343 ASSERT(m_state == IndexedDB::TransactionState::Committing);
345 if (error.isNull()) {
346 m_database->didCommitTransaction(*this);
349 m_database->didAbortTransaction(*this);
354 finishAbortOrCommit();
357 void IDBTransaction::fireOnComplete()
359 LOG(IndexedDB, "IDBTransaction::fireOnComplete");
360 enqueueEvent(Event::create(eventNames().completeEvent, false, false));
363 void IDBTransaction::fireOnAbort()
365 LOG(IndexedDB, "IDBTransaction::fireOnAbort");
366 enqueueEvent(Event::create(eventNames().abortEvent, true, false));
369 void IDBTransaction::enqueueEvent(Ref<Event>&& event)
371 ASSERT(m_state != IndexedDB::TransactionState::Finished);
373 if (!scriptExecutionContext())
376 event->setTarget(this);
377 scriptExecutionContext()->eventQueue().enqueueEvent(WTF::move(event));
380 bool IDBTransaction::dispatchEvent(Event& event)
382 LOG(IndexedDB, "IDBTransaction::dispatchEvent");
384 ASSERT(scriptExecutionContext());
385 ASSERT(event.target() == this);
386 ASSERT(event.type() == eventNames().completeEvent || event.type() == eventNames().abortEvent);
388 Vector<RefPtr<EventTarget>> targets;
389 targets.append(this);
390 targets.append(db());
392 bool result = IDBEventDispatcher::dispatch(event, targets);
394 if (isVersionChange() && event.type() == eventNames().completeEvent) {
395 ASSERT(m_openDBRequest);
396 m_openDBRequest->fireSuccessAfterVersionChangeCommit();
402 Ref<IDBObjectStore> IDBTransaction::createObjectStore(const IDBObjectStoreInfo& info)
404 LOG(IndexedDB, "IDBTransaction::createObjectStore");
405 ASSERT(isVersionChange());
407 Ref<IDBObjectStore> objectStore = IDBObjectStore::create(info, *this);
408 m_referencedObjectStores.set(info.name(), &objectStore.get());
410 auto operation = createTransactionOperation(*this, &IDBTransaction::didCreateObjectStoreOnServer, &IDBTransaction::createObjectStoreOnServer, info);
411 scheduleOperation(WTF::move(operation));
413 return WTF::move(objectStore);
416 void IDBTransaction::createObjectStoreOnServer(TransactionOperation& operation, const IDBObjectStoreInfo& info)
418 LOG(IndexedDB, "IDBTransaction::createObjectStoreOnServer");
420 ASSERT(isVersionChange());
422 m_database->serverConnection().createObjectStore(operation, info);
425 void IDBTransaction::didCreateObjectStoreOnServer(const IDBResultData& resultData)
427 LOG(IndexedDB, "IDBTransaction::didCreateObjectStoreOnServer");
429 ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::CreateObjectStoreSuccess || resultData.type() == IDBResultType::Error);
432 Ref<IDBIndex> IDBTransaction::createIndex(IDBObjectStore& objectStore, const IDBIndexInfo& info)
434 LOG(IndexedDB, "IDBTransaction::createIndex");
435 ASSERT(isVersionChange());
437 Ref<IDBIndex> index = IDBIndex::create(info, objectStore);
439 auto operation = createTransactionOperation(*this, &IDBTransaction::didCreateIndexOnServer, &IDBTransaction::createIndexOnServer, info);
440 scheduleOperation(WTF::move(operation));
442 return WTF::move(index);
445 void IDBTransaction::createIndexOnServer(TransactionOperation& operation, const IDBIndexInfo& info)
447 LOG(IndexedDB, "IDBTransaction::createIndexOnServer");
449 ASSERT(isVersionChange());
451 m_database->serverConnection().createIndex(operation, info);
454 void IDBTransaction::didCreateIndexOnServer(const IDBResultData& resultData)
456 LOG(IndexedDB, "IDBTransaction::didCreateIndexOnServer");
458 if (resultData.type() == IDBResultType::CreateIndexSuccess)
461 ASSERT(resultData.type() == IDBResultType::Error);
463 // This operation might have failed because the transaction is already aborting.
464 if (m_state == IndexedDB::TransactionState::Aborting)
467 // Otherwise, failure to create an index forced abortion of the transaction.
472 Ref<IDBRequest> IDBTransaction::requestOpenCursor(ScriptExecutionContext& context, IDBObjectStore& objectStore, const IDBCursorInfo& info)
474 LOG(IndexedDB, "IDBTransaction::requestOpenCursor");
476 return doRequestOpenCursor(context, IDBCursorWithValue::create(*this, objectStore, info));
479 Ref<IDBRequest> IDBTransaction::requestOpenCursor(ScriptExecutionContext& context, IDBIndex& index, const IDBCursorInfo& info)
481 LOG(IndexedDB, "IDBTransaction::requestOpenCursor");
483 if (info.cursorType() == IndexedDB::CursorType::KeyOnly)
484 return doRequestOpenCursor(context, IDBCursor::create(*this, index, info));
486 return doRequestOpenCursor(context, IDBCursorWithValue::create(*this, index, info));
489 Ref<IDBRequest> IDBTransaction::doRequestOpenCursor(ScriptExecutionContext& context, Ref<IDBCursor>&& cursor)
493 Ref<IDBRequest> request = IDBRequest::create(context, cursor.get(), *this);
494 addRequest(request.get());
496 auto operation = createTransactionOperation(*this, request.get(), &IDBTransaction::didOpenCursorOnServer, &IDBTransaction::openCursorOnServer, cursor->info());
497 scheduleOperation(WTF::move(operation));
499 return WTF::move(request);
502 void IDBTransaction::openCursorOnServer(TransactionOperation& operation, const IDBCursorInfo& info)
504 LOG(IndexedDB, "IDBTransaction::openCursorOnServer");
506 m_database->serverConnection().openCursor(operation, info);
509 void IDBTransaction::didOpenCursorOnServer(IDBRequest& request, const IDBResultData& resultData)
511 LOG(IndexedDB, "IDBTransaction::didOpenCursorOnServer");
513 request.didOpenOrIterateCursor(resultData);
516 void IDBTransaction::iterateCursor(IDBCursor& cursor, const IDBKeyData& key, unsigned long count)
518 LOG(IndexedDB, "IDBTransaction::iterateCursor");
520 ASSERT(cursor.request());
522 addRequest(*cursor.request());
524 auto operation = createTransactionOperation(*this, *cursor.request(), &IDBTransaction::didIterateCursorOnServer, &IDBTransaction::iterateCursorOnServer, key, count);
525 scheduleOperation(WTF::move(operation));
528 void IDBTransaction::iterateCursorOnServer(TransactionOperation& operation, const IDBKeyData& key, const unsigned long& count)
530 LOG(IndexedDB, "IDBTransaction::iterateCursorOnServer");
532 serverConnection().iterateCursor(operation, key, count);
535 void IDBTransaction::didIterateCursorOnServer(IDBRequest& request, const IDBResultData& resultData)
537 LOG(IndexedDB, "IDBTransaction::didIterateCursorOnServer");
539 request.didOpenOrIterateCursor(resultData);
542 Ref<IDBRequest> IDBTransaction::requestGetRecord(ScriptExecutionContext& context, IDBObjectStore& objectStore, const IDBKeyRangeData& keyRangeData)
544 LOG(IndexedDB, "IDBTransaction::requestGetRecord");
546 ASSERT(!keyRangeData.isNull);
548 Ref<IDBRequest> request = IDBRequest::create(context, objectStore, *this);
549 addRequest(request.get());
551 auto operation = createTransactionOperation(*this, request.get(), &IDBTransaction::didGetRecordOnServer, &IDBTransaction::getRecordOnServer, keyRangeData);
552 scheduleOperation(WTF::move(operation));
554 return WTF::move(request);
557 Ref<IDBRequest> IDBTransaction::requestGetValue(ScriptExecutionContext& context, IDBIndex& index, const IDBKeyRangeData& range)
559 LOG(IndexedDB, "IDBTransaction::requestGetValue");
560 return requestIndexRecord(context, index, IndexedDB::IndexRecordType::Value, range);
563 Ref<IDBRequest> IDBTransaction::requestGetKey(ScriptExecutionContext& context, IDBIndex& index, const IDBKeyRangeData& range)
565 LOG(IndexedDB, "IDBTransaction::requestGetValue");
566 return requestIndexRecord(context, index, IndexedDB::IndexRecordType::Key, range);
569 Ref<IDBRequest> IDBTransaction::requestIndexRecord(ScriptExecutionContext& context, IDBIndex& index, IndexedDB::IndexRecordType type, const IDBKeyRangeData&range)
571 LOG(IndexedDB, "IDBTransaction::requestGetValue");
573 ASSERT(!range.isNull);
575 Ref<IDBRequest> request = IDBRequest::createGet(context, index, type, *this);
576 addRequest(request.get());
578 auto operation = createTransactionOperation(*this, request.get(), &IDBTransaction::didGetRecordOnServer, &IDBTransaction::getRecordOnServer, range);
579 scheduleOperation(WTF::move(operation));
581 return WTF::move(request);
584 void IDBTransaction::getRecordOnServer(TransactionOperation& operation, const IDBKeyRangeData& keyRange)
586 LOG(IndexedDB, "IDBTransaction::getRecordOnServer");
588 serverConnection().getRecord(operation, keyRange);
591 void IDBTransaction::didGetRecordOnServer(IDBRequest& request, const IDBResultData& resultData)
593 LOG(IndexedDB, "IDBTransaction::didGetRecordOnServer");
595 if (resultData.type() == IDBResultType::Error) {
596 request.requestCompleted(resultData);
600 ASSERT(resultData.type() == IDBResultType::GetRecordSuccess);
602 const IDBGetResult& result = resultData.getResult();
604 if (request.sourceIndexIdentifier() && request.requestedIndexRecordType() == IndexedDB::IndexRecordType::Key) {
605 if (!result.keyData().isNull())
606 request.setResult(&result.keyData());
608 request.setResultToUndefined();
610 if (resultData.getResult().valueBuffer().data())
611 request.setResultToStructuredClone(resultData.getResult().valueBuffer());
613 request.setResultToUndefined();
616 request.requestCompleted(resultData);
619 Ref<IDBRequest> IDBTransaction::requestCount(ScriptExecutionContext& context, IDBObjectStore& objectStore, const IDBKeyRangeData& range)
621 LOG(IndexedDB, "IDBTransaction::requestCount (IDBObjectStore)");
623 ASSERT(!range.isNull);
625 Ref<IDBRequest> request = IDBRequest::create(context, objectStore, *this);
626 addRequest(request.get());
628 scheduleOperation(createTransactionOperation(*this, request.get(), &IDBTransaction::didGetCountOnServer, &IDBTransaction::getCountOnServer, range));
633 Ref<IDBRequest> IDBTransaction::requestCount(ScriptExecutionContext& context, IDBIndex& index, const IDBKeyRangeData& range)
635 LOG(IndexedDB, "IDBTransaction::requestCount (IDBIndex)");
637 ASSERT(!range.isNull);
639 Ref<IDBRequest> request = IDBRequest::createCount(context, index, *this);
640 addRequest(request.get());
642 scheduleOperation(createTransactionOperation(*this, request.get(), &IDBTransaction::didGetCountOnServer, &IDBTransaction::getCountOnServer, range));
647 void IDBTransaction::getCountOnServer(TransactionOperation& operation, const IDBKeyRangeData& keyRange)
649 LOG(IndexedDB, "IDBTransaction::getCountOnServer");
651 serverConnection().getCount(operation, keyRange);
654 void IDBTransaction::didGetCountOnServer(IDBRequest& request, const IDBResultData& resultData)
656 LOG(IndexedDB, "IDBTransaction::didGetCountOnServer");
658 request.setResult(resultData.resultInteger());
659 request.requestCompleted(resultData);
662 Ref<IDBRequest> IDBTransaction::requestDeleteRecord(ScriptExecutionContext& context, IDBObjectStore& objectStore, const IDBKeyRangeData& range)
664 LOG(IndexedDB, "IDBTransaction::requestDeleteRecord");
666 ASSERT(!range.isNull);
668 Ref<IDBRequest> request = IDBRequest::create(context, objectStore, *this);
669 addRequest(request.get());
671 scheduleOperation(createTransactionOperation(*this, request.get(), &IDBTransaction::didDeleteRecordOnServer, &IDBTransaction::deleteRecordOnServer, range));
675 void IDBTransaction::deleteRecordOnServer(TransactionOperation& operation, const IDBKeyRangeData& keyRange)
677 LOG(IndexedDB, "IDBTransaction::deleteRecordOnServer");
679 serverConnection().deleteRecord(operation, keyRange);
682 void IDBTransaction::didDeleteRecordOnServer(IDBRequest& request, const IDBResultData& resultData)
684 LOG(IndexedDB, "IDBTransaction::didDeleteRecordOnServer");
686 request.setResultToUndefined();
687 request.requestCompleted(resultData);
690 Ref<IDBRequest> IDBTransaction::requestClearObjectStore(ScriptExecutionContext& context, IDBObjectStore& objectStore)
692 LOG(IndexedDB, "IDBTransaction::requestClearObjectStore");
695 Ref<IDBRequest> request = IDBRequest::create(context, objectStore, *this);
696 addRequest(request.get());
698 uint64_t objectStoreIdentifier = objectStore.info().identifier();
699 auto operation = createTransactionOperation(*this, request.get(), &IDBTransaction::didClearObjectStoreOnServer, &IDBTransaction::clearObjectStoreOnServer, objectStoreIdentifier);
700 scheduleOperation(WTF::move(operation));
702 return WTF::move(request);
705 void IDBTransaction::clearObjectStoreOnServer(TransactionOperation& operation, const uint64_t& objectStoreIdentifier)
707 LOG(IndexedDB, "IDBTransaction::clearObjectStoreOnServer");
709 serverConnection().clearObjectStore(operation, objectStoreIdentifier);
712 void IDBTransaction::didClearObjectStoreOnServer(IDBRequest& request, const IDBResultData& resultData)
714 LOG(IndexedDB, "IDBTransaction::didClearObjectStoreOnServer");
716 request.setResultToUndefined();
717 request.requestCompleted(resultData);
720 Ref<IDBRequest> IDBTransaction::requestPutOrAdd(ScriptExecutionContext& context, IDBObjectStore& objectStore, IDBKey* key, SerializedScriptValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
722 LOG(IndexedDB, "IDBTransaction::requestPutOrAdd");
724 ASSERT(!isReadOnly());
725 ASSERT(objectStore.info().autoIncrement() || key);
727 Ref<IDBRequest> request = IDBRequest::create(context, objectStore, *this);
728 addRequest(request.get());
730 auto operation = createTransactionOperation(*this, request.get(), &IDBTransaction::didPutOrAddOnServer, &IDBTransaction::putOrAddOnServer, key, &value, overwriteMode);
731 scheduleOperation(WTF::move(operation));
733 return WTF::move(request);
736 void IDBTransaction::putOrAddOnServer(TransactionOperation& operation, RefPtr<IDBKey> key, RefPtr<SerializedScriptValue> value, const IndexedDB::ObjectStoreOverwriteMode& overwriteMode)
738 LOG(IndexedDB, "IDBTransaction::putOrAddOnServer");
740 ASSERT(!isReadOnly());
742 serverConnection().putOrAdd(operation, key, value, overwriteMode);
745 void IDBTransaction::didPutOrAddOnServer(IDBRequest& request, const IDBResultData& resultData)
747 LOG(IndexedDB, "IDBTransaction::didPutOrAddOnServer");
749 request.setResult(resultData.resultKey());
750 request.requestCompleted(resultData);
753 void IDBTransaction::deleteObjectStore(const String& objectStoreName)
755 LOG(IndexedDB, "IDBTransaction::deleteObjectStore");
757 ASSERT(isVersionChange());
759 if (auto objectStore = m_referencedObjectStores.take(objectStoreName))
760 objectStore->markAsDeleted();
762 auto operation = createTransactionOperation(*this, &IDBTransaction::didDeleteObjectStoreOnServer, &IDBTransaction::deleteObjectStoreOnServer, objectStoreName);
763 scheduleOperation(WTF::move(operation));
766 void IDBTransaction::deleteObjectStoreOnServer(TransactionOperation& operation, const String& objectStoreName)
768 LOG(IndexedDB, "IDBTransaction::deleteObjectStoreOnServer");
769 ASSERT(isVersionChange());
771 serverConnection().deleteObjectStore(operation, objectStoreName);
774 void IDBTransaction::didDeleteObjectStoreOnServer(const IDBResultData& resultData)
776 LOG(IndexedDB, "IDBTransaction::didDeleteObjectStoreOnServer");
777 ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteObjectStoreSuccess || resultData.type() == IDBResultType::Error);
780 void IDBTransaction::deleteIndex(uint64_t objectStoreIdentifier, const String& indexName)
782 LOG(IndexedDB, "IDBTransaction::deleteIndex");
784 ASSERT(isVersionChange());
786 auto operation = createTransactionOperation(*this, &IDBTransaction::didDeleteIndexOnServer, &IDBTransaction::deleteIndexOnServer, objectStoreIdentifier, indexName);
787 scheduleOperation(WTF::move(operation));
790 void IDBTransaction::deleteIndexOnServer(TransactionOperation& operation, const uint64_t& objectStoreIdentifier, const String& indexName)
792 LOG(IndexedDB, "IDBTransaction::deleteIndexOnServer");
793 ASSERT(isVersionChange());
795 serverConnection().deleteIndex(operation, objectStoreIdentifier, indexName);
798 void IDBTransaction::didDeleteIndexOnServer(const IDBResultData& resultData)
800 LOG(IndexedDB, "IDBTransaction::didDeleteIndexOnServer");
801 ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteIndexSuccess || resultData.type() == IDBResultType::Error);
804 void IDBTransaction::operationDidComplete(TransactionOperation& operation)
806 ASSERT(m_transactionOperationMap.get(operation.identifier()) == &operation);
807 m_transactionOperationMap.remove(operation.identifier());
809 scheduleOperationTimer();
812 void IDBTransaction::establishOnServer()
814 LOG(IndexedDB, "IDBTransaction::establishOnServer");
816 serverConnection().establishTransaction(*this);
819 void IDBTransaction::activate()
821 if (isFinishedOrFinishing())
824 m_state = IndexedDB::TransactionState::Active;
827 void IDBTransaction::deactivate()
829 if (m_state == IndexedDB::TransactionState::Active)
830 m_state = IndexedDB::TransactionState::Inactive;
832 scheduleOperationTimer();
835 } // namespace IDBClient
836 } // namespace WebCore
838 #endif // ENABLE(INDEXED_DATABASE)