d62f759cf543f5b3717009a5376b3e12f7acc49d
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / IDBTransaction.cpp
1 /*
2  * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27 #include "IDBTransaction.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "DOMError.h"
32 #include "DOMStringList.h"
33 #include "DOMWindow.h"
34 #include "Event.h"
35 #include "EventNames.h"
36 #include "EventQueue.h"
37 #include "IDBCursorWithValue.h"
38 #include "IDBDatabase.h"
39 #include "IDBDatabaseException.h"
40 #include "IDBError.h"
41 #include "IDBEventDispatcher.h"
42 #include "IDBGetRecordData.h"
43 #include "IDBIndex.h"
44 #include "IDBKeyData.h"
45 #include "IDBKeyRangeData.h"
46 #include "IDBObjectStore.h"
47 #include "IDBOpenDBRequest.h"
48 #include "IDBRequest.h"
49 #include "IDBResultData.h"
50 #include "IDBValue.h"
51 #include "JSDOMWindowBase.h"
52 #include "Logging.h"
53 #include "ScriptExecutionContext.h"
54 #include "ScriptState.h"
55 #include "TransactionOperation.h"
56 #include <wtf/NeverDestroyed.h>
57
58 using namespace JSC;
59
60 namespace WebCore {
61
62 Ref<IDBTransaction> IDBTransaction::create(IDBDatabase& database, const IDBTransactionInfo& info)
63 {
64     return adoptRef(*new IDBTransaction(database, info, nullptr));
65 }
66
67 Ref<IDBTransaction> IDBTransaction::create(IDBDatabase& database, const IDBTransactionInfo& info, IDBOpenDBRequest& request)
68 {
69     return adoptRef(*new IDBTransaction(database, info, &request));
70 }
71
72 IDBTransaction::IDBTransaction(IDBDatabase& database, const IDBTransactionInfo& info, IDBOpenDBRequest* request)
73     : IDBActiveDOMObject(database.scriptExecutionContext())
74     , m_database(database)
75     , m_info(info)
76     , m_operationTimer(*this, &IDBTransaction::operationTimerFired)
77     , m_openDBRequest(request)
78
79 {
80     LOG(IndexedDB, "IDBTransaction::IDBTransaction - %s", m_info.loggingString().utf8().data());
81     ASSERT(currentThread() == m_database->originThreadID());
82
83     if (m_info.mode() == IDBTransactionMode::Versionchange) {
84         ASSERT(m_openDBRequest);
85         m_openDBRequest->setVersionChangeTransaction(*this);
86         m_startedOnServer = true;
87     } else {
88         activate();
89
90         auto* context = scriptExecutionContext();
91         ASSERT(context);
92
93         RefPtr<IDBTransaction> self;
94         JSC::VM& vm = context->vm();
95         vm.whenIdle([self, this]() {
96             deactivate();
97         });
98
99         establishOnServer();
100     }
101
102     suspendIfNeeded();
103 }
104
105 IDBTransaction::~IDBTransaction()
106 {
107     ASSERT(currentThread() == m_database->originThreadID());
108 }
109
110 IDBClient::IDBConnectionProxy& IDBTransaction::connectionProxy()
111 {
112     return m_database->connectionProxy();
113 }
114
115 Ref<DOMStringList> IDBTransaction::objectStoreNames() const
116 {
117     ASSERT(currentThread() == m_database->originThreadID());
118
119     const Vector<String> names = isVersionChange() ? m_database->info().objectStoreNames() : m_info.objectStores();
120
121     Ref<DOMStringList> objectStoreNames = DOMStringList::create();
122     for (auto& name : names)
123         objectStoreNames->append(name);
124
125     objectStoreNames->sort();
126     return objectStoreNames;
127 }
128
129 IDBDatabase* IDBTransaction::db()
130 {
131     ASSERT(currentThread() == m_database->originThreadID());
132     return m_database.ptr();
133 }
134
135 DOMError* IDBTransaction::error() const
136 {
137     ASSERT(currentThread() == m_database->originThreadID());
138     return m_domError.get();
139 }
140
141 ExceptionOr<Ref<IDBObjectStore>> IDBTransaction::objectStore(const String& objectStoreName)
142 {
143     LOG(IndexedDB, "IDBTransaction::objectStore");
144     ASSERT(currentThread() == m_database->originThreadID());
145
146     if (!scriptExecutionContext())
147         return Exception { IDBDatabaseException::InvalidStateError };
148
149     if (isFinishedOrFinishing())
150         return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral("Failed to execute 'objectStore' on 'IDBTransaction': The transaction finished.") };
151
152     Locker<Lock> locker(m_referencedObjectStoreLock);
153
154     auto iterator = m_referencedObjectStores.find(objectStoreName);
155     if (iterator != m_referencedObjectStores.end())
156         return Ref<IDBObjectStore> { *iterator->value };
157
158     bool found = false;
159     for (auto& objectStore : m_info.objectStores()) {
160         if (objectStore == objectStoreName) {
161             found = true;
162             break;
163         }
164     }
165
166     auto* info = m_database->info().infoForExistingObjectStore(objectStoreName);
167     if (!info)
168         return Exception { IDBDatabaseException::NotFoundError, ASCIILiteral("Failed to execute 'objectStore' on 'IDBTransaction': The specified object store was not found.") };
169
170     // Version change transactions are scoped to every object store in the database.
171     if (!info || (!found && !isVersionChange()))
172         return Exception { IDBDatabaseException::NotFoundError, ASCIILiteral("Failed to execute 'objectStore' on 'IDBTransaction': The specified object store was not found.") };
173
174     auto objectStore = std::make_unique<IDBObjectStore>(*scriptExecutionContext(), *info, *this);
175     auto* rawObjectStore = objectStore.get();
176     m_referencedObjectStores.set(objectStoreName, WTFMove(objectStore));
177
178     return Ref<IDBObjectStore>(*rawObjectStore);
179 }
180
181
182 void IDBTransaction::abortDueToFailedRequest(DOMError& error)
183 {
184     LOG(IndexedDB, "IDBTransaction::abortDueToFailedRequest");
185     ASSERT(currentThread() == m_database->originThreadID());
186
187     if (isFinishedOrFinishing())
188         return;
189
190     m_domError = &error;
191     internalAbort();
192 }
193
194 void IDBTransaction::transitionedToFinishing(IndexedDB::TransactionState state)
195 {
196     ASSERT(currentThread() == m_database->originThreadID());
197
198     ASSERT(!isFinishedOrFinishing());
199     m_state = state;
200     ASSERT(isFinishedOrFinishing());
201 }
202
203 ExceptionOr<void> IDBTransaction::abort()
204 {
205     LOG(IndexedDB, "IDBTransaction::abort");
206     ASSERT(currentThread() == m_database->originThreadID());
207
208     if (isFinishedOrFinishing())
209         return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral("Failed to execute 'abort' on 'IDBTransaction': The transaction is inactive or finished.") };
210
211     internalAbort();
212
213     return { };
214 }
215
216 void IDBTransaction::internalAbort()
217 {
218     LOG(IndexedDB, "IDBTransaction::internalAbort");
219     ASSERT(currentThread() == m_database->originThreadID());
220     ASSERT(!isFinishedOrFinishing());
221
222     m_database->willAbortTransaction(*this);
223
224     if (isVersionChange()) {
225         Locker<Lock> locker(m_referencedObjectStoreLock);
226
227         auto& info = m_database->info();
228         for (auto& iterator : m_deletedObjectStores) {
229             if (info.infoForExistingObjectStore(iterator.key)) {
230                 auto name = iterator.value->info().name();
231                 m_referencedObjectStores.set(name, WTFMove(iterator.value));
232             }
233         }
234
235         for (auto& objectStore : m_referencedObjectStores.values())
236             objectStore->rollbackForVersionChangeAbort();
237     }
238
239     transitionedToFinishing(IndexedDB::TransactionState::Aborting);
240     
241     m_abortQueue.swap(m_transactionOperationQueue);
242
243     scheduleOperation(IDBClient::createTransactionOperation(*this, nullptr, &IDBTransaction::abortOnServerAndCancelRequests));
244 }
245
246 void IDBTransaction::abortOnServerAndCancelRequests(IDBClient::TransactionOperation& operation)
247 {
248     LOG(IndexedDB, "IDBTransaction::abortOnServerAndCancelRequests");
249     ASSERT(currentThread() == m_database->originThreadID());
250     ASSERT(m_transactionOperationQueue.isEmpty());
251
252     m_database->connectionProxy().abortTransaction(*this);
253
254     ASSERT(m_transactionOperationMap.contains(operation.identifier()));
255     m_transactionOperationMap.remove(operation.identifier());
256
257     IDBError error(IDBDatabaseException::AbortError);
258     for (auto& operation : m_abortQueue)
259         operation->completed(IDBResultData::error(operation->identifier(), error));
260
261     // Since we're aborting, it should be impossible to have queued any further operations.
262     ASSERT(m_transactionOperationQueue.isEmpty());
263 }
264
265 const char* IDBTransaction::activeDOMObjectName() const
266 {
267     ASSERT(currentThread() == m_database->originThreadID());
268     return "IDBTransaction";
269 }
270
271 bool IDBTransaction::canSuspendForDocumentSuspension() const
272 {
273     ASSERT(currentThread() == m_database->originThreadID());
274     return false;
275 }
276
277 bool IDBTransaction::hasPendingActivity() const
278 {
279     ASSERT(currentThread() == m_database->originThreadID() || mayBeGCThread());
280     return !m_contextStopped && m_state != IndexedDB::TransactionState::Finished;
281 }
282
283 void IDBTransaction::stop()
284 {
285     LOG(IndexedDB, "IDBTransaction::stop - %s", m_info.loggingString().utf8().data());
286     ASSERT(currentThread() == m_database->originThreadID());
287
288     // IDBDatabase::stop() calls IDBTransaction::stop() for each of its active transactions.
289     // Since the order of calling ActiveDOMObject::stop() is random, we might already have been stopped.
290     if (m_contextStopped)
291         return;
292
293     removeAllEventListeners();
294
295     m_contextStopped = true;
296
297     if (isFinishedOrFinishing())
298         return;
299
300     internalAbort();
301 }
302
303 bool IDBTransaction::isActive() const
304 {
305     ASSERT(currentThread() == m_database->originThreadID());
306     return m_state == IndexedDB::TransactionState::Active;
307 }
308
309 bool IDBTransaction::isFinishedOrFinishing() const
310 {
311     ASSERT(currentThread() == m_database->originThreadID());
312
313     return m_state == IndexedDB::TransactionState::Committing
314         || m_state == IndexedDB::TransactionState::Aborting
315         || m_state == IndexedDB::TransactionState::Finished;
316 }
317
318 void IDBTransaction::addRequest(IDBRequest& request)
319 {
320     ASSERT(currentThread() == m_database->originThreadID());
321     m_openRequests.add(&request);
322 }
323
324 void IDBTransaction::removeRequest(IDBRequest& request)
325 {
326     ASSERT(currentThread() == m_database->originThreadID());
327     ASSERT(m_openRequests.contains(&request));
328     m_openRequests.remove(&request);
329 }
330
331 void IDBTransaction::scheduleOperation(RefPtr<IDBClient::TransactionOperation>&& operation)
332 {
333     ASSERT(!m_transactionOperationMap.contains(operation->identifier()));
334     ASSERT(currentThread() == m_database->originThreadID());
335
336     m_transactionOperationQueue.append(operation);
337     m_transactionOperationMap.set(operation->identifier(), WTFMove(operation));
338
339     scheduleOperationTimer();
340 }
341
342 void IDBTransaction::scheduleOperationTimer()
343 {
344     ASSERT(currentThread() == m_database->originThreadID());
345
346     if (!m_operationTimer.isActive())
347         m_operationTimer.startOneShot(0);
348 }
349
350 void IDBTransaction::operationTimerFired()
351 {
352     LOG(IndexedDB, "IDBTransaction::operationTimerFired (%p)", this);
353     ASSERT(currentThread() == m_database->originThreadID());
354
355     if (!m_startedOnServer)
356         return;
357
358     if (!m_transactionOperationQueue.isEmpty()) {
359         auto operation = m_transactionOperationQueue.takeFirst();
360         operation->perform();
361
362         return;
363     }
364
365     if (!m_transactionOperationMap.isEmpty() || !m_openRequests.isEmpty())
366         return;
367
368     if (!isFinishedOrFinishing())
369         commit();
370 }
371
372 void IDBTransaction::commit()
373 {
374     LOG(IndexedDB, "IDBTransaction::commit");
375     ASSERT(currentThread() == m_database->originThreadID());
376     ASSERT(!isFinishedOrFinishing());
377
378     transitionedToFinishing(IndexedDB::TransactionState::Committing);
379     m_database->willCommitTransaction(*this);
380
381     scheduleOperation(IDBClient::createTransactionOperation(*this, nullptr, &IDBTransaction::commitOnServer));
382 }
383
384 void IDBTransaction::commitOnServer(IDBClient::TransactionOperation& operation)
385 {
386     LOG(IndexedDB, "IDBTransaction::commitOnServer");
387     ASSERT(currentThread() == m_database->originThreadID());
388
389     m_database->connectionProxy().commitTransaction(*this);
390
391     ASSERT(m_transactionOperationMap.contains(operation.identifier()));
392     m_transactionOperationMap.remove(operation.identifier());
393 }
394
395 void IDBTransaction::finishAbortOrCommit()
396 {
397     ASSERT(m_state != IndexedDB::TransactionState::Finished);
398     ASSERT(currentThread() == m_database->originThreadID());
399
400     m_state = IndexedDB::TransactionState::Finished;
401 }
402
403 void IDBTransaction::didStart(const IDBError& error)
404 {
405     LOG(IndexedDB, "IDBTransaction::didStart");
406     ASSERT(currentThread() == m_database->originThreadID());
407
408     m_database->didStartTransaction(*this);
409
410     m_startedOnServer = true;
411
412     // It's possible the transaction failed to start on the server.
413     // That equates to an abort.
414     if (!error.isNull()) {
415         didAbort(error);
416         return;
417     }
418
419     scheduleOperationTimer();
420 }
421
422 void IDBTransaction::notifyDidAbort(const IDBError& error)
423 {
424     ASSERT(currentThread() == m_database->originThreadID());
425
426     m_database->didAbortTransaction(*this);
427     m_idbError = error;
428     fireOnAbort();
429
430     if (isVersionChange()) {
431         ASSERT(m_openDBRequest);
432         m_openDBRequest->fireErrorAfterVersionChangeCompletion();
433     }
434 }
435
436 void IDBTransaction::didAbort(const IDBError& error)
437 {
438     LOG(IndexedDB, "IDBTransaction::didAbort");
439     ASSERT(currentThread() == m_database->originThreadID());
440
441     if (m_state == IndexedDB::TransactionState::Finished)
442         return;
443
444     notifyDidAbort(error);
445
446     finishAbortOrCommit();
447 }
448
449 void IDBTransaction::didCommit(const IDBError& error)
450 {
451     LOG(IndexedDB, "IDBTransaction::didCommit");
452     ASSERT(currentThread() == m_database->originThreadID());
453     ASSERT(m_state == IndexedDB::TransactionState::Committing);
454
455     if (error.isNull()) {
456         m_database->didCommitTransaction(*this);
457         fireOnComplete();
458     } else {
459         m_database->willAbortTransaction(*this);
460         notifyDidAbort(error);
461     }
462
463     finishAbortOrCommit();
464 }
465
466 void IDBTransaction::fireOnComplete()
467 {
468     LOG(IndexedDB, "IDBTransaction::fireOnComplete");
469     ASSERT(currentThread() == m_database->originThreadID());
470     enqueueEvent(Event::create(eventNames().completeEvent, false, false));
471 }
472
473 void IDBTransaction::fireOnAbort()
474 {
475     LOG(IndexedDB, "IDBTransaction::fireOnAbort");
476     ASSERT(currentThread() == m_database->originThreadID());
477     enqueueEvent(Event::create(eventNames().abortEvent, true, false));
478 }
479
480 void IDBTransaction::enqueueEvent(Ref<Event>&& event)
481 {
482     ASSERT(m_state != IndexedDB::TransactionState::Finished);
483     ASSERT(currentThread() == m_database->originThreadID());
484
485     if (!scriptExecutionContext() || m_contextStopped)
486         return;
487
488     event->setTarget(this);
489     scriptExecutionContext()->eventQueue().enqueueEvent(WTFMove(event));
490 }
491
492 bool IDBTransaction::dispatchEvent(Event& event)
493 {
494     LOG(IndexedDB, "IDBTransaction::dispatchEvent");
495
496     ASSERT(currentThread() == m_database->originThreadID());
497     ASSERT(scriptExecutionContext());
498     ASSERT(!m_contextStopped);
499     ASSERT(event.target() == this);
500     ASSERT(event.type() == eventNames().completeEvent || event.type() == eventNames().abortEvent);
501
502     Vector<RefPtr<EventTarget>> targets;
503     targets.append(this);
504     targets.append(db());
505
506     bool result = IDBEventDispatcher::dispatch(event, targets);
507
508     if (isVersionChange()) {
509         ASSERT(m_openDBRequest);
510         m_openDBRequest->versionChangeTransactionDidFinish();
511
512         if (event.type() == eventNames().completeEvent) {
513             if (m_database->isClosingOrClosed())
514                 m_openDBRequest->fireErrorAfterVersionChangeCompletion();
515             else
516                 m_openDBRequest->fireSuccessAfterVersionChangeCommit();
517         }
518
519         m_openDBRequest = nullptr;
520     }
521
522     return result;
523 }
524
525 Ref<IDBObjectStore> IDBTransaction::createObjectStore(const IDBObjectStoreInfo& info)
526 {
527     LOG(IndexedDB, "IDBTransaction::createObjectStore");
528     ASSERT(isVersionChange());
529     ASSERT(scriptExecutionContext());
530     ASSERT(currentThread() == m_database->originThreadID());
531
532     Locker<Lock> locker(m_referencedObjectStoreLock);
533
534     auto objectStore = std::make_unique<IDBObjectStore>(*scriptExecutionContext(), info, *this);
535     auto* rawObjectStore = objectStore.get();
536     m_referencedObjectStores.set(info.name(), WTFMove(objectStore));
537
538     scheduleOperation(IDBClient::createTransactionOperation(*this, &IDBTransaction::didCreateObjectStoreOnServer, &IDBTransaction::createObjectStoreOnServer, info));
539
540     return *rawObjectStore;
541 }
542
543 void IDBTransaction::createObjectStoreOnServer(IDBClient::TransactionOperation& operation, const IDBObjectStoreInfo& info)
544 {
545     LOG(IndexedDB, "IDBTransaction::createObjectStoreOnServer");
546     ASSERT(currentThread() == m_database->originThreadID());
547     ASSERT(isVersionChange());
548
549     m_database->connectionProxy().createObjectStore(operation, info);
550 }
551
552 void IDBTransaction::didCreateObjectStoreOnServer(const IDBResultData& resultData)
553 {
554     LOG(IndexedDB, "IDBTransaction::didCreateObjectStoreOnServer");
555     ASSERT(currentThread() == m_database->originThreadID());
556     ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::CreateObjectStoreSuccess || resultData.type() == IDBResultType::Error);
557 }
558
559 void IDBTransaction::renameObjectStore(IDBObjectStore& objectStore, const String& newName)
560 {
561     LOG(IndexedDB, "IDBTransaction::renameObjectStore");
562
563     Locker<Lock> locker(m_referencedObjectStoreLock);
564
565     ASSERT(isVersionChange());
566     ASSERT(scriptExecutionContext());
567     ASSERT(currentThread() == m_database->originThreadID());
568
569     ASSERT(m_referencedObjectStores.contains(objectStore.info().name()));
570     ASSERT(!m_referencedObjectStores.contains(newName));
571     ASSERT(m_referencedObjectStores.get(objectStore.info().name()) == &objectStore);
572
573     uint64_t objectStoreIdentifier = objectStore.info().identifier();
574     scheduleOperation(IDBClient::createTransactionOperation(*this, &IDBTransaction::didRenameObjectStoreOnServer, &IDBTransaction::renameObjectStoreOnServer, objectStoreIdentifier, newName));
575
576     m_referencedObjectStores.set(newName, m_referencedObjectStores.take(objectStore.info().name()));
577 }
578
579 void IDBTransaction::renameObjectStoreOnServer(IDBClient::TransactionOperation& operation, const uint64_t& objectStoreIdentifier, const String& newName)
580 {
581     LOG(IndexedDB, "IDBTransaction::renameObjectStoreOnServer");
582     ASSERT(currentThread() == m_database->originThreadID());
583     ASSERT(isVersionChange());
584
585     m_database->connectionProxy().renameObjectStore(operation, objectStoreIdentifier, newName);
586 }
587
588 void IDBTransaction::didRenameObjectStoreOnServer(const IDBResultData& resultData)
589 {
590     LOG(IndexedDB, "IDBTransaction::didRenameObjectStoreOnServer");
591     ASSERT(currentThread() == m_database->originThreadID());
592     ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::RenameObjectStoreSuccess || resultData.type() == IDBResultType::Error);
593 }
594
595 std::unique_ptr<IDBIndex> IDBTransaction::createIndex(IDBObjectStore& objectStore, const IDBIndexInfo& info)
596 {
597     LOG(IndexedDB, "IDBTransaction::createIndex");
598     ASSERT(isVersionChange());
599     ASSERT(currentThread() == m_database->originThreadID());
600
601     if (!scriptExecutionContext())
602         return nullptr;
603
604     scheduleOperation(IDBClient::createTransactionOperation(*this, &IDBTransaction::didCreateIndexOnServer, &IDBTransaction::createIndexOnServer, info));
605
606     return std::make_unique<IDBIndex>(*scriptExecutionContext(), info, objectStore);
607 }
608
609 void IDBTransaction::createIndexOnServer(IDBClient::TransactionOperation& operation, const IDBIndexInfo& info)
610 {
611     LOG(IndexedDB, "IDBTransaction::createIndexOnServer");
612     ASSERT(currentThread() == m_database->originThreadID());
613     ASSERT(isVersionChange());
614
615     m_database->connectionProxy().createIndex(operation, info);
616 }
617
618 void IDBTransaction::didCreateIndexOnServer(const IDBResultData& resultData)
619 {
620     LOG(IndexedDB, "IDBTransaction::didCreateIndexOnServer");
621     ASSERT(currentThread() == m_database->originThreadID());
622
623     if (resultData.type() == IDBResultType::CreateIndexSuccess)
624         return;
625
626     ASSERT(resultData.type() == IDBResultType::Error);
627
628     // This operation might have failed because the transaction is already aborting.
629     if (m_state == IndexedDB::TransactionState::Aborting)
630         return;
631
632     // Otherwise, failure to create an index forced abortion of the transaction.
633     abortDueToFailedRequest(DOMError::create(IDBDatabaseException::getErrorName(resultData.error().code()), resultData.error().message()));
634 }
635
636 void IDBTransaction::renameIndex(IDBIndex& index, const String& newName)
637 {
638     LOG(IndexedDB, "IDBTransaction::renameIndex");
639     Locker<Lock> locker(m_referencedObjectStoreLock);
640
641     ASSERT(isVersionChange());
642     ASSERT(scriptExecutionContext());
643     ASSERT(currentThread() == m_database->originThreadID());
644
645     ASSERT(m_referencedObjectStores.contains(index.objectStore().info().name()));
646     ASSERT(m_referencedObjectStores.get(index.objectStore().info().name()) == &index.objectStore());
647
648     index.objectStore().renameReferencedIndex(index, newName);
649
650     uint64_t objectStoreIdentifier = index.objectStore().info().identifier();
651     uint64_t indexIdentifier = index.info().identifier();
652     scheduleOperation(IDBClient::createTransactionOperation(*this, &IDBTransaction::didRenameIndexOnServer, &IDBTransaction::renameIndexOnServer, objectStoreIdentifier, indexIdentifier, newName));
653 }
654
655 void IDBTransaction::renameIndexOnServer(IDBClient::TransactionOperation& operation, const uint64_t& objectStoreIdentifier, const uint64_t& indexIdentifier, const String& newName)
656 {
657     LOG(IndexedDB, "IDBTransaction::renameIndexOnServer");
658     ASSERT(currentThread() == m_database->originThreadID());
659     ASSERT(isVersionChange());
660
661     m_database->connectionProxy().renameIndex(operation, objectStoreIdentifier, indexIdentifier, newName);
662 }
663
664 void IDBTransaction::didRenameIndexOnServer(const IDBResultData& resultData)
665 {
666     LOG(IndexedDB, "IDBTransaction::didRenameIndexOnServer");
667     ASSERT(currentThread() == m_database->originThreadID());
668     ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::RenameIndexSuccess || resultData.type() == IDBResultType::Error);
669 }
670
671 Ref<IDBRequest> IDBTransaction::requestOpenCursor(ExecState& state, IDBObjectStore& objectStore, const IDBCursorInfo& info)
672 {
673     LOG(IndexedDB, "IDBTransaction::requestOpenCursor");
674     ASSERT(currentThread() == m_database->originThreadID());
675
676     if (info.cursorType() == IndexedDB::CursorType::KeyOnly)
677         return doRequestOpenCursor(state, IDBCursor::create(*this, objectStore, info));
678
679     return doRequestOpenCursor(state, IDBCursorWithValue::create(*this, objectStore, info));
680 }
681
682 Ref<IDBRequest> IDBTransaction::requestOpenCursor(ExecState& state, IDBIndex& index, const IDBCursorInfo& info)
683 {
684     LOG(IndexedDB, "IDBTransaction::requestOpenCursor");
685     ASSERT(currentThread() == m_database->originThreadID());
686
687     if (info.cursorType() == IndexedDB::CursorType::KeyOnly)
688         return doRequestOpenCursor(state, IDBCursor::create(*this, index, info));
689
690     return doRequestOpenCursor(state, IDBCursorWithValue::create(*this, index, info));
691 }
692
693 Ref<IDBRequest> IDBTransaction::doRequestOpenCursor(ExecState& state, Ref<IDBCursor>&& cursor)
694 {
695     ASSERT(isActive());
696     ASSERT(currentThread() == m_database->originThreadID());
697
698     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
699
700     auto request = IDBRequest::create(*scriptExecutionContext(), cursor.get(), *this);
701     addRequest(request.get());
702
703     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didOpenCursorOnServer, &IDBTransaction::openCursorOnServer, cursor->info()));
704
705     return request;
706 }
707
708 void IDBTransaction::openCursorOnServer(IDBClient::TransactionOperation& operation, const IDBCursorInfo& info)
709 {
710     LOG(IndexedDB, "IDBTransaction::openCursorOnServer");
711     ASSERT(currentThread() == m_database->originThreadID());
712
713     m_database->connectionProxy().openCursor(operation, info);
714 }
715
716 void IDBTransaction::didOpenCursorOnServer(IDBRequest& request, const IDBResultData& resultData)
717 {
718     LOG(IndexedDB, "IDBTransaction::didOpenCursorOnServer");
719     ASSERT(currentThread() == m_database->originThreadID());
720
721     request.didOpenOrIterateCursor(resultData);
722 }
723
724 void IDBTransaction::iterateCursor(IDBCursor& cursor, const IDBKeyData& key, unsigned long count)
725 {
726     LOG(IndexedDB, "IDBTransaction::iterateCursor");
727     ASSERT(isActive());
728     ASSERT(cursor.request());
729     ASSERT(currentThread() == m_database->originThreadID());
730
731     addRequest(*cursor.request());
732
733     scheduleOperation(IDBClient::createTransactionOperation(*this, *cursor.request(), &IDBTransaction::didIterateCursorOnServer, &IDBTransaction::iterateCursorOnServer, key, count));
734 }
735
736 void IDBTransaction::iterateCursorOnServer(IDBClient::TransactionOperation& operation, const IDBKeyData& key, const unsigned long& count)
737 {
738     LOG(IndexedDB, "IDBTransaction::iterateCursorOnServer");
739     ASSERT(currentThread() == m_database->originThreadID());
740
741     m_database->connectionProxy().iterateCursor(operation, key, count);
742 }
743
744 void IDBTransaction::didIterateCursorOnServer(IDBRequest& request, const IDBResultData& resultData)
745 {
746     LOG(IndexedDB, "IDBTransaction::didIterateCursorOnServer");
747     ASSERT(currentThread() == m_database->originThreadID());
748
749     request.didOpenOrIterateCursor(resultData);
750 }
751
752 Ref<IDBRequest> IDBTransaction::requestGetAllObjectStoreRecords(JSC::ExecState& state, IDBObjectStore& objectStore, const IDBKeyRangeData& keyRangeData, IndexedDB::GetAllType getAllType, Optional<uint32_t> count)
753 {
754     LOG(IndexedDB, "IDBTransaction::requestGetAllObjectStoreRecords");
755     ASSERT(isActive());
756     ASSERT(currentThread() == m_database->originThreadID());
757
758     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
759
760     auto request = IDBRequest::create(*scriptExecutionContext(), objectStore, *this);
761     addRequest(request.get());
762
763     IDBGetAllRecordsData getAllRecordsData { keyRangeData, getAllType, count, objectStore.info().identifier(), 0 };
764
765     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didGetAllRecordsOnServer, &IDBTransaction::getAllRecordsOnServer, getAllRecordsData));
766
767     return request;
768 }
769
770 Ref<IDBRequest> IDBTransaction::requestGetAllIndexRecords(JSC::ExecState& state, IDBIndex& index, const IDBKeyRangeData& keyRangeData, IndexedDB::GetAllType getAllType, Optional<uint32_t> count)
771 {
772     LOG(IndexedDB, "IDBTransaction::requestGetAllIndexRecords");
773     ASSERT(isActive());
774     ASSERT(currentThread() == m_database->originThreadID());
775
776     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
777
778     auto request = IDBRequest::create(*scriptExecutionContext(), index, *this);
779     addRequest(request.get());
780
781     IDBGetAllRecordsData getAllRecordsData { keyRangeData, getAllType, count, index.objectStore().info().identifier(), index.info().identifier() };
782
783     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didGetAllRecordsOnServer, &IDBTransaction::getAllRecordsOnServer, getAllRecordsData));
784
785     return request;
786 }
787
788 void IDBTransaction::getAllRecordsOnServer(IDBClient::TransactionOperation& operation, const IDBGetAllRecordsData& getAllRecordsData)
789 {
790     LOG(IndexedDB, "IDBTransaction::getAllRecordsOnServer");
791     ASSERT(currentThread() == m_database->originThreadID());
792
793     m_database->connectionProxy().getAllRecords(operation, getAllRecordsData);
794 }
795
796 void IDBTransaction::didGetAllRecordsOnServer(IDBRequest& request, const IDBResultData& resultData)
797 {
798     LOG(IndexedDB, "IDBTransaction::didGetAllRecordsOnServer");
799     ASSERT(currentThread() == m_database->originThreadID());
800
801     if (resultData.type() == IDBResultType::Error) {
802         request.requestCompleted(resultData);
803         return;
804     }
805
806     ASSERT(resultData.type() == IDBResultType::GetAllRecordsSuccess);
807
808     auto& getAllResult = resultData.getAllResult();
809     switch (getAllResult.type()) {
810     case IndexedDB::GetAllType::Keys:
811         request.setResult(getAllResult.keys());
812         break;
813     case IndexedDB::GetAllType::Values:
814         request.setResult(getAllResult.values());
815         break;
816     }
817
818     request.requestCompleted(resultData);
819 }
820
821 Ref<IDBRequest> IDBTransaction::requestGetRecord(ExecState& state, IDBObjectStore& objectStore, const IDBGetRecordData& getRecordData)
822 {
823     LOG(IndexedDB, "IDBTransaction::requestGetRecord");
824     ASSERT(isActive());
825     ASSERT(!getRecordData.keyRangeData.isNull);
826     ASSERT(currentThread() == m_database->originThreadID());
827
828     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
829
830     auto request = IDBRequest::create(*scriptExecutionContext(), objectStore, *this);
831     addRequest(request.get());
832
833     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didGetRecordOnServer, &IDBTransaction::getRecordOnServer, getRecordData));
834
835     return request;
836 }
837
838 Ref<IDBRequest> IDBTransaction::requestGetValue(ExecState& state, IDBIndex& index, const IDBKeyRangeData& range)
839 {
840     LOG(IndexedDB, "IDBTransaction::requestGetValue");
841     ASSERT(currentThread() == m_database->originThreadID());
842
843     return requestIndexRecord(state, index, IndexedDB::IndexRecordType::Value, range);
844 }
845
846 Ref<IDBRequest> IDBTransaction::requestGetKey(ExecState& state, IDBIndex& index, const IDBKeyRangeData& range)
847 {
848     LOG(IndexedDB, "IDBTransaction::requestGetValue");
849     ASSERT(currentThread() == m_database->originThreadID());
850
851     return requestIndexRecord(state, index, IndexedDB::IndexRecordType::Key, range);
852 }
853
854 Ref<IDBRequest> IDBTransaction::requestIndexRecord(ExecState& state, IDBIndex& index, IndexedDB::IndexRecordType type, const IDBKeyRangeData& range)
855 {
856     LOG(IndexedDB, "IDBTransaction::requestGetValue");
857     ASSERT(isActive());
858     ASSERT(!range.isNull);
859     ASSERT(currentThread() == m_database->originThreadID());
860
861     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
862
863     auto request = IDBRequest::createIndexGet(*scriptExecutionContext(), index, type, *this);
864     addRequest(request.get());
865
866     IDBGetRecordData getRecordData = { range };
867     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didGetRecordOnServer, &IDBTransaction::getRecordOnServer, getRecordData));
868
869     return request;
870 }
871
872 void IDBTransaction::getRecordOnServer(IDBClient::TransactionOperation& operation, const IDBGetRecordData& getRecordData)
873 {
874     LOG(IndexedDB, "IDBTransaction::getRecordOnServer");
875     ASSERT(currentThread() == m_database->originThreadID());
876
877     m_database->connectionProxy().getRecord(operation, getRecordData);
878 }
879
880 void IDBTransaction::didGetRecordOnServer(IDBRequest& request, const IDBResultData& resultData)
881 {
882     LOG(IndexedDB, "IDBTransaction::didGetRecordOnServer");
883     ASSERT(currentThread() == m_database->originThreadID());
884
885     if (resultData.type() == IDBResultType::Error) {
886         request.requestCompleted(resultData);
887         return;
888     }
889
890     ASSERT(resultData.type() == IDBResultType::GetRecordSuccess);
891
892     const IDBGetResult& result = resultData.getResult();
893
894     if (request.sourceIndexIdentifier() && request.requestedIndexRecordType() == IndexedDB::IndexRecordType::Key) {
895         if (!result.keyData().isNull())
896             request.setResult(result.keyData());
897         else
898             request.setResultToUndefined();
899     } else {
900         if (resultData.getResult().value().data().data())
901             request.setResultToStructuredClone(resultData.getResult().value());
902         else
903             request.setResultToUndefined();
904     }
905
906     request.requestCompleted(resultData);
907 }
908
909 Ref<IDBRequest> IDBTransaction::requestCount(ExecState& state, IDBObjectStore& objectStore, const IDBKeyRangeData& range)
910 {
911     LOG(IndexedDB, "IDBTransaction::requestCount (IDBObjectStore)");
912     ASSERT(isActive());
913     ASSERT(!range.isNull);
914     ASSERT(currentThread() == m_database->originThreadID());
915
916     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
917
918     auto request = IDBRequest::create(*scriptExecutionContext(), objectStore, *this);
919     addRequest(request.get());
920
921     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didGetCountOnServer, &IDBTransaction::getCountOnServer, range));
922
923     return request;
924 }
925
926 Ref<IDBRequest> IDBTransaction::requestCount(ExecState& state, IDBIndex& index, const IDBKeyRangeData& range)
927 {
928     LOG(IndexedDB, "IDBTransaction::requestCount (IDBIndex)");
929     ASSERT(isActive());
930     ASSERT(!range.isNull);
931     ASSERT(currentThread() == m_database->originThreadID());
932
933     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
934
935     auto request = IDBRequest::create(*scriptExecutionContext(), index, *this);
936     addRequest(request.get());
937
938     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didGetCountOnServer, &IDBTransaction::getCountOnServer, range));
939
940     return request;
941 }
942
943 void IDBTransaction::getCountOnServer(IDBClient::TransactionOperation& operation, const IDBKeyRangeData& keyRange)
944 {
945     LOG(IndexedDB, "IDBTransaction::getCountOnServer");
946     ASSERT(currentThread() == m_database->originThreadID());
947
948     m_database->connectionProxy().getCount(operation, keyRange);
949 }
950
951 void IDBTransaction::didGetCountOnServer(IDBRequest& request, const IDBResultData& resultData)
952 {
953     LOG(IndexedDB, "IDBTransaction::didGetCountOnServer");
954     ASSERT(currentThread() == m_database->originThreadID());
955
956     request.setResult(resultData.resultInteger());
957     request.requestCompleted(resultData);
958 }
959
960 Ref<IDBRequest> IDBTransaction::requestDeleteRecord(ExecState& state, IDBObjectStore& objectStore, const IDBKeyRangeData& range)
961 {
962     LOG(IndexedDB, "IDBTransaction::requestDeleteRecord");
963     ASSERT(isActive());
964     ASSERT(!range.isNull);
965     ASSERT(currentThread() == m_database->originThreadID());
966
967     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
968
969     auto request = IDBRequest::create(*scriptExecutionContext(), objectStore, *this);
970     addRequest(request.get());
971
972     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didDeleteRecordOnServer, &IDBTransaction::deleteRecordOnServer, range));
973     return request;
974 }
975
976 void IDBTransaction::deleteRecordOnServer(IDBClient::TransactionOperation& operation, const IDBKeyRangeData& keyRange)
977 {
978     LOG(IndexedDB, "IDBTransaction::deleteRecordOnServer");
979     ASSERT(currentThread() == m_database->originThreadID());
980
981     m_database->connectionProxy().deleteRecord(operation, keyRange);
982 }
983
984 void IDBTransaction::didDeleteRecordOnServer(IDBRequest& request, const IDBResultData& resultData)
985 {
986     LOG(IndexedDB, "IDBTransaction::didDeleteRecordOnServer");
987     ASSERT(currentThread() == m_database->originThreadID());
988
989     request.setResultToUndefined();
990     request.requestCompleted(resultData);
991 }
992
993 Ref<IDBRequest> IDBTransaction::requestClearObjectStore(ExecState& state, IDBObjectStore& objectStore)
994 {
995     LOG(IndexedDB, "IDBTransaction::requestClearObjectStore");
996     ASSERT(isActive());
997     ASSERT(currentThread() == m_database->originThreadID());
998
999     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
1000
1001     auto request = IDBRequest::create(*scriptExecutionContext(), objectStore, *this);
1002     addRequest(request.get());
1003
1004     uint64_t objectStoreIdentifier = objectStore.info().identifier();
1005     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didClearObjectStoreOnServer, &IDBTransaction::clearObjectStoreOnServer, objectStoreIdentifier));
1006
1007     return request;
1008 }
1009
1010 void IDBTransaction::clearObjectStoreOnServer(IDBClient::TransactionOperation& operation, const uint64_t& objectStoreIdentifier)
1011 {
1012     LOG(IndexedDB, "IDBTransaction::clearObjectStoreOnServer");
1013     ASSERT(currentThread() == m_database->originThreadID());
1014
1015     m_database->connectionProxy().clearObjectStore(operation, objectStoreIdentifier);
1016 }
1017
1018 void IDBTransaction::didClearObjectStoreOnServer(IDBRequest& request, const IDBResultData& resultData)
1019 {
1020     LOG(IndexedDB, "IDBTransaction::didClearObjectStoreOnServer");
1021     ASSERT(currentThread() == m_database->originThreadID());
1022
1023     request.setResultToUndefined();
1024     request.requestCompleted(resultData);
1025 }
1026
1027 Ref<IDBRequest> IDBTransaction::requestPutOrAdd(ExecState& state, IDBObjectStore& objectStore, IDBKey* key, SerializedScriptValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
1028 {
1029     LOG(IndexedDB, "IDBTransaction::requestPutOrAdd");
1030     ASSERT(isActive());
1031     ASSERT(!isReadOnly());
1032     ASSERT(objectStore.info().autoIncrement() || key);
1033     ASSERT(currentThread() == m_database->originThreadID());
1034
1035     ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
1036
1037     auto request = IDBRequest::create(*scriptExecutionContext(), objectStore, *this);
1038     addRequest(request.get());
1039
1040     scheduleOperation(IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didPutOrAddOnServer, &IDBTransaction::putOrAddOnServer, key, &value, overwriteMode));
1041
1042     return request;
1043 }
1044
1045 void IDBTransaction::putOrAddOnServer(IDBClient::TransactionOperation& operation, RefPtr<IDBKey> key, RefPtr<SerializedScriptValue> value, const IndexedDB::ObjectStoreOverwriteMode& overwriteMode)
1046 {
1047     LOG(IndexedDB, "IDBTransaction::putOrAddOnServer");
1048     ASSERT(currentThread() == originThreadID());
1049     ASSERT(!isReadOnly());
1050     ASSERT(value);
1051
1052     if (!value->hasBlobURLs()) {
1053         m_database->connectionProxy().putOrAdd(operation, key.get(), *value, overwriteMode);
1054         return;
1055     }
1056
1057     // Due to current limitations on our ability to post tasks back to a worker thread,
1058     // workers currently write blobs to disk synchronously.
1059     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=157958 - Make this asynchronous after refactoring allows it.
1060     if (!isMainThread()) {
1061         auto idbValue = value->writeBlobsToDiskForIndexedDBSynchronously();
1062         if (idbValue.data().data())
1063             m_database->connectionProxy().putOrAdd(operation, key.get(), idbValue, overwriteMode);
1064         else {
1065             // If the IDBValue doesn't have any data, then something went wrong writing the blobs to disk.
1066             // In that case, we cannot successfully store this record, so we callback with an error.
1067             RefPtr<IDBClient::TransactionOperation> protectedOperation(&operation);
1068             auto result = IDBResultData::error(operation.identifier(), { IDBDatabaseException::UnknownError, ASCIILiteral("Error preparing Blob/File data to be stored in object store") });
1069             scriptExecutionContext()->postTask([protectedOperation = WTFMove(protectedOperation), result = WTFMove(result)](ScriptExecutionContext&) {
1070                 protectedOperation->completed(result);
1071             });
1072         }
1073         return;
1074     }
1075
1076     value->writeBlobsToDiskForIndexedDB([protectedThis = makeRef(*this), this, protectedOperation = Ref<IDBClient::TransactionOperation>(operation), keyData = IDBKeyData(key.get()).isolatedCopy(), overwriteMode](const IDBValue& idbValue) mutable {
1077         ASSERT(currentThread() == originThreadID());
1078         ASSERT(isMainThread());
1079         if (idbValue.data().data()) {
1080             m_database->connectionProxy().putOrAdd(protectedOperation.get(), WTFMove(keyData), idbValue, overwriteMode);
1081             return;
1082         }
1083
1084         // If the IDBValue doesn't have any data, then something went wrong writing the blobs to disk.
1085         // In that case, we cannot successfully store this record, so we callback with an error.
1086         auto result = IDBResultData::error(protectedOperation->identifier(), { IDBDatabaseException::UnknownError, ASCIILiteral("Error preparing Blob/File data to be stored in object store") });
1087         callOnMainThread([protectedThis = WTFMove(protectedThis), protectedOperation = WTFMove(protectedOperation), result = WTFMove(result)]() mutable {
1088             protectedOperation->completed(result);
1089         });
1090     });
1091 }
1092
1093 void IDBTransaction::didPutOrAddOnServer(IDBRequest& request, const IDBResultData& resultData)
1094 {
1095     LOG(IndexedDB, "IDBTransaction::didPutOrAddOnServer");
1096     ASSERT(currentThread() == m_database->originThreadID());
1097
1098     if (auto* result = resultData.resultKey())
1099         request.setResult(*result);
1100     else
1101         request.setResultToUndefined();
1102     request.requestCompleted(resultData);
1103 }
1104
1105 void IDBTransaction::deleteObjectStore(const String& objectStoreName)
1106 {
1107     LOG(IndexedDB, "IDBTransaction::deleteObjectStore");
1108     ASSERT(currentThread() == m_database->originThreadID());
1109     ASSERT(isVersionChange());
1110
1111     Locker<Lock> locker(m_referencedObjectStoreLock);
1112
1113     if (auto objectStore = m_referencedObjectStores.take(objectStoreName)) {
1114         objectStore->markAsDeleted();
1115         auto identifier = objectStore->info().identifier();
1116         m_deletedObjectStores.set(identifier, WTFMove(objectStore));
1117     }
1118
1119     scheduleOperation(IDBClient::createTransactionOperation(*this, &IDBTransaction::didDeleteObjectStoreOnServer, &IDBTransaction::deleteObjectStoreOnServer, objectStoreName));
1120 }
1121
1122 void IDBTransaction::deleteObjectStoreOnServer(IDBClient::TransactionOperation& operation, const String& objectStoreName)
1123 {
1124     LOG(IndexedDB, "IDBTransaction::deleteObjectStoreOnServer");
1125     ASSERT(isVersionChange());
1126     ASSERT(currentThread() == m_database->originThreadID());
1127
1128     m_database->connectionProxy().deleteObjectStore(operation, objectStoreName);
1129 }
1130
1131 void IDBTransaction::didDeleteObjectStoreOnServer(const IDBResultData& resultData)
1132 {
1133     LOG(IndexedDB, "IDBTransaction::didDeleteObjectStoreOnServer");
1134     ASSERT(currentThread() == m_database->originThreadID());
1135     ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteObjectStoreSuccess || resultData.type() == IDBResultType::Error);
1136 }
1137
1138 void IDBTransaction::deleteIndex(uint64_t objectStoreIdentifier, const String& indexName)
1139 {
1140     LOG(IndexedDB, "IDBTransaction::deleteIndex");
1141     ASSERT(currentThread() == m_database->originThreadID());
1142     ASSERT(isVersionChange());
1143
1144     scheduleOperation(IDBClient::createTransactionOperation(*this, &IDBTransaction::didDeleteIndexOnServer, &IDBTransaction::deleteIndexOnServer, objectStoreIdentifier, indexName));
1145 }
1146
1147 void IDBTransaction::deleteIndexOnServer(IDBClient::TransactionOperation& operation, const uint64_t& objectStoreIdentifier, const String& indexName)
1148 {
1149     LOG(IndexedDB, "IDBTransaction::deleteIndexOnServer");
1150     ASSERT(isVersionChange());
1151     ASSERT(currentThread() == m_database->originThreadID());
1152
1153     m_database->connectionProxy().deleteIndex(operation, objectStoreIdentifier, indexName);
1154 }
1155
1156 void IDBTransaction::didDeleteIndexOnServer(const IDBResultData& resultData)
1157 {
1158     LOG(IndexedDB, "IDBTransaction::didDeleteIndexOnServer");
1159     ASSERT(currentThread() == m_database->originThreadID());
1160     ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteIndexSuccess || resultData.type() == IDBResultType::Error);
1161 }
1162
1163 void IDBTransaction::operationDidComplete(IDBClient::TransactionOperation& operation)
1164 {
1165     ASSERT(m_transactionOperationMap.get(operation.identifier()) == &operation);
1166     ASSERT(currentThread() == m_database->originThreadID());
1167     ASSERT(currentThread() == operation.originThreadID());
1168
1169     m_transactionOperationMap.remove(operation.identifier());
1170
1171     scheduleOperationTimer();
1172 }
1173
1174 void IDBTransaction::establishOnServer()
1175 {
1176     LOG(IndexedDB, "IDBTransaction::establishOnServer");
1177     ASSERT(currentThread() == m_database->originThreadID());
1178
1179     m_database->connectionProxy().establishTransaction(*this);
1180 }
1181
1182 void IDBTransaction::activate()
1183 {
1184     ASSERT(currentThread() == m_database->originThreadID());
1185
1186     if (isFinishedOrFinishing())
1187         return;
1188
1189     m_state = IndexedDB::TransactionState::Active;
1190 }
1191
1192 void IDBTransaction::deactivate()
1193 {
1194     ASSERT(currentThread() == m_database->originThreadID());
1195
1196     if (m_state == IndexedDB::TransactionState::Active)
1197         m_state = IndexedDB::TransactionState::Inactive;
1198
1199     scheduleOperationTimer();
1200 }
1201
1202 void IDBTransaction::connectionClosedFromServer(const IDBError& error)
1203 {
1204     LOG(IndexedDB, "IDBTransaction::connectionClosedFromServer - %s", error.message().utf8().data());
1205
1206     m_state = IndexedDB::TransactionState::Aborting;
1207
1208     Vector<RefPtr<IDBClient::TransactionOperation>> operations;
1209     copyValuesToVector(m_transactionOperationMap, operations);
1210
1211     for (auto& operation : operations)
1212         operation->completed(IDBResultData::error(operation->identifier(), error));
1213
1214     connectionProxy().forgetActiveOperations(operations);
1215
1216     m_transactionOperationQueue.clear();
1217     m_abortQueue.clear();
1218     m_transactionOperationMap.clear();
1219
1220     m_idbError = error;
1221     m_domError = error.toDOMError();
1222     fireOnAbort();
1223 }
1224
1225 void IDBTransaction::visitReferencedObjectStores(JSC::SlotVisitor& visitor) const
1226 {
1227     Locker<Lock> locker(m_referencedObjectStoreLock);
1228     for (auto& objectStore : m_referencedObjectStores.values())
1229         visitor.addOpaqueRoot(objectStore.get());
1230     for (auto& objectStore : m_deletedObjectStores.values())
1231         visitor.addOpaqueRoot(objectStore.get());
1232 }
1233
1234 } // namespace WebCore
1235
1236 #endif // ENABLE(INDEXED_DATABASE)