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 "IDBDatabase.h" |
28 | |
29 | #if ENABLE(INDEXED_DATABASE) |
30 | |
31 | #include "DOMStringList.h" |
32 | #include "EventNames.h" |
33 | #include "EventQueue.h" |
34 | #include "IDBConnectionProxy.h" |
35 | #include "IDBConnectionToServer.h" |
36 | #include "IDBIndex.h" |
37 | #include "IDBObjectStore.h" |
38 | #include "IDBOpenDBRequest.h" |
39 | #include "IDBResultData.h" |
40 | #include "IDBTransaction.h" |
41 | #include "IDBVersionChangeEvent.h" |
42 | #include "Logging.h" |
43 | #include "ScriptExecutionContext.h" |
44 | #include <JavaScriptCore/HeapInlines.h> |
45 | #include <wtf/IsoMallocInlines.h> |
46 | |
47 | namespace WebCore { |
48 | |
49 | WTF_MAKE_ISO_ALLOCATED_IMPL(IDBDatabase); |
50 | |
51 | Ref<IDBDatabase> IDBDatabase::create(ScriptExecutionContext& context, IDBClient::IDBConnectionProxy& connectionProxy, const IDBResultData& resultData) |
52 | { |
53 | return adoptRef(*new IDBDatabase(context, connectionProxy, resultData)); |
54 | } |
55 | |
56 | IDBDatabase::IDBDatabase(ScriptExecutionContext& context, IDBClient::IDBConnectionProxy& connectionProxy, const IDBResultData& resultData) |
57 | : IDBActiveDOMObject(&context) |
58 | , m_connectionProxy(connectionProxy) |
59 | , m_info(resultData.databaseInfo()) |
60 | , m_databaseConnectionIdentifier(resultData.databaseConnectionIdentifier()) |
61 | , m_eventNames(eventNames()) |
62 | { |
63 | LOG(IndexedDB, "IDBDatabase::IDBDatabase - Creating database %s with version %" PRIu64 " connection %" PRIu64 " (%p)" , m_info.name().utf8().data(), m_info.version(), m_databaseConnectionIdentifier, this); |
64 | suspendIfNeeded(); |
65 | m_connectionProxy->registerDatabaseConnection(*this); |
66 | } |
67 | |
68 | IDBDatabase::~IDBDatabase() |
69 | { |
70 | ASSERT(&originThread() == &Thread::current()); |
71 | |
72 | if (!m_closedInServer) |
73 | m_connectionProxy->databaseConnectionClosed(*this); |
74 | |
75 | m_connectionProxy->unregisterDatabaseConnection(*this); |
76 | } |
77 | |
78 | bool IDBDatabase::hasPendingActivity() const |
79 | { |
80 | ASSERT(&originThread() == &Thread::current() || Thread::mayBeGCThread()); |
81 | |
82 | if (m_closedInServer || isContextStopped()) |
83 | return false; |
84 | |
85 | if (!m_activeTransactions.isEmpty() || !m_committingTransactions.isEmpty() || !m_abortingTransactions.isEmpty()) |
86 | return true; |
87 | |
88 | return hasEventListeners(m_eventNames.abortEvent) || hasEventListeners(m_eventNames.errorEvent) || hasEventListeners(m_eventNames.versionchangeEvent); |
89 | } |
90 | |
91 | const String IDBDatabase::name() const |
92 | { |
93 | ASSERT(&originThread() == &Thread::current()); |
94 | return m_info.name(); |
95 | } |
96 | |
97 | uint64_t IDBDatabase::version() const |
98 | { |
99 | ASSERT(&originThread() == &Thread::current()); |
100 | return m_info.version(); |
101 | } |
102 | |
103 | Ref<DOMStringList> IDBDatabase::objectStoreNames() const |
104 | { |
105 | ASSERT(&originThread() == &Thread::current()); |
106 | |
107 | auto objectStoreNames = DOMStringList::create(); |
108 | for (auto& name : m_info.objectStoreNames()) |
109 | objectStoreNames->append(name); |
110 | objectStoreNames->sort(); |
111 | return objectStoreNames; |
112 | } |
113 | |
114 | void IDBDatabase::renameObjectStore(IDBObjectStore& objectStore, const String& newName) |
115 | { |
116 | ASSERT(&originThread() == &Thread::current()); |
117 | ASSERT(m_versionChangeTransaction); |
118 | ASSERT(m_info.hasObjectStore(objectStore.info().name())); |
119 | |
120 | m_info.renameObjectStore(objectStore.info().identifier(), newName); |
121 | |
122 | m_versionChangeTransaction->renameObjectStore(objectStore, newName); |
123 | } |
124 | |
125 | void IDBDatabase::renameIndex(IDBIndex& index, const String& newName) |
126 | { |
127 | ASSERT(&originThread() == &Thread::current()); |
128 | ASSERT(m_versionChangeTransaction); |
129 | ASSERT(m_info.hasObjectStore(index.objectStore().info().name())); |
130 | ASSERT(m_info.infoForExistingObjectStore(index.objectStore().info().name())->hasIndex(index.info().name())); |
131 | |
132 | m_info.infoForExistingObjectStore(index.objectStore().info().name())->infoForExistingIndex(index.info().identifier())->rename(newName); |
133 | |
134 | m_versionChangeTransaction->renameIndex(index, newName); |
135 | } |
136 | |
137 | ExceptionOr<Ref<IDBObjectStore>> IDBDatabase::createObjectStore(const String& name, ObjectStoreParameters&& parameters) |
138 | { |
139 | LOG(IndexedDB, "IDBDatabase::createObjectStore - (%s %s)" , m_info.name().utf8().data(), name.utf8().data()); |
140 | |
141 | ASSERT(&originThread() == &Thread::current()); |
142 | ASSERT(!m_versionChangeTransaction || m_versionChangeTransaction->isVersionChange()); |
143 | |
144 | if (!m_versionChangeTransaction) |
145 | return Exception { InvalidStateError, "Failed to execute 'createObjectStore' on 'IDBDatabase': The database is not running a version change transaction."_s }; |
146 | |
147 | if (!m_versionChangeTransaction->isActive()) |
148 | return Exception { TransactionInactiveError }; |
149 | |
150 | auto& keyPath = parameters.keyPath; |
151 | if (keyPath && !isIDBKeyPathValid(keyPath.value())) |
152 | return Exception { SyntaxError, "Failed to execute 'createObjectStore' on 'IDBDatabase': The keyPath option is not a valid key path."_s }; |
153 | |
154 | if (m_info.hasObjectStore(name)) |
155 | return Exception { ConstraintError, "Failed to execute 'createObjectStore' on 'IDBDatabase': An object store with the specified name already exists."_s }; |
156 | |
157 | if (keyPath && parameters.autoIncrement && ((WTF::holds_alternative<String>(keyPath.value()) && WTF::get<String>(keyPath.value()).isEmpty()) || WTF::holds_alternative<Vector<String>>(keyPath.value()))) |
158 | return Exception { InvalidAccessError, "Failed to execute 'createObjectStore' on 'IDBDatabase': The autoIncrement option was set but the keyPath option was empty or an array."_s }; |
159 | |
160 | // Install the new ObjectStore into the connection's metadata. |
161 | auto info = m_info.createNewObjectStore(name, WTFMove(keyPath), parameters.autoIncrement); |
162 | |
163 | // Create the actual IDBObjectStore from the transaction, which also schedules the operation server side. |
164 | return m_versionChangeTransaction->createObjectStore(info); |
165 | } |
166 | |
167 | ExceptionOr<Ref<IDBTransaction>> IDBDatabase::transaction(StringOrVectorOfStrings&& storeNames, IDBTransactionMode mode) |
168 | { |
169 | LOG(IndexedDB, "IDBDatabase::transaction" ); |
170 | |
171 | ASSERT(&originThread() == &Thread::current()); |
172 | |
173 | if (m_versionChangeTransaction && !m_versionChangeTransaction->isFinishedOrFinishing()) |
174 | return Exception { InvalidStateError, "Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running."_s }; |
175 | |
176 | if (m_closePending) |
177 | return Exception { InvalidStateError, "Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing."_s }; |
178 | |
179 | Vector<String> objectStores; |
180 | if (WTF::holds_alternative<Vector<String>>(storeNames)) |
181 | objectStores = WTFMove(WTF::get<Vector<String>>(storeNames)); |
182 | else |
183 | objectStores.append(WTFMove(WTF::get<String>(storeNames))); |
184 | |
185 | // It is valid for javascript to pass in a list of object store names with the same name listed twice, |
186 | // so we need to put them all in a set to get a unique list. |
187 | HashSet<String> objectStoreSet; |
188 | for (auto& objectStore : objectStores) |
189 | objectStoreSet.add(objectStore); |
190 | |
191 | objectStores = copyToVector(objectStoreSet); |
192 | |
193 | for (auto& objectStoreName : objectStores) { |
194 | if (m_info.hasObjectStore(objectStoreName)) |
195 | continue; |
196 | return Exception { NotFoundError, "Failed to execute 'transaction' on 'IDBDatabase': One of the specified object stores was not found."_s }; |
197 | } |
198 | |
199 | if (objectStores.isEmpty()) |
200 | return Exception { InvalidAccessError, "Failed to execute 'transaction' on 'IDBDatabase': The storeNames parameter was empty."_s }; |
201 | |
202 | if (mode != IDBTransactionMode::Readonly && mode != IDBTransactionMode::Readwrite) |
203 | return Exception { TypeError }; |
204 | |
205 | auto info = IDBTransactionInfo::clientTransaction(m_connectionProxy.get(), objectStores, mode); |
206 | |
207 | LOG(IndexedDBOperations, "IDB creating transaction: %s" , info.loggingString().utf8().data()); |
208 | auto transaction = IDBTransaction::create(*this, info); |
209 | |
210 | LOG(IndexedDB, "IDBDatabase::transaction - Added active transaction %s" , info.identifier().loggingString().utf8().data()); |
211 | |
212 | m_activeTransactions.set(info.identifier(), transaction.ptr()); |
213 | |
214 | return transaction; |
215 | } |
216 | |
217 | ExceptionOr<void> IDBDatabase::deleteObjectStore(const String& objectStoreName) |
218 | { |
219 | LOG(IndexedDB, "IDBDatabase::deleteObjectStore" ); |
220 | |
221 | ASSERT(&originThread() == &Thread::current()); |
222 | |
223 | if (!m_versionChangeTransaction) |
224 | return Exception { InvalidStateError, "Failed to execute 'deleteObjectStore' on 'IDBDatabase': The database is not running a version change transaction."_s }; |
225 | |
226 | if (!m_versionChangeTransaction->isActive()) |
227 | return Exception { TransactionInactiveError }; |
228 | |
229 | if (!m_info.hasObjectStore(objectStoreName)) |
230 | return Exception { NotFoundError, "Failed to execute 'deleteObjectStore' on 'IDBDatabase': The specified object store was not found."_s }; |
231 | |
232 | m_info.deleteObjectStore(objectStoreName); |
233 | m_versionChangeTransaction->deleteObjectStore(objectStoreName); |
234 | |
235 | return { }; |
236 | } |
237 | |
238 | void IDBDatabase::close() |
239 | { |
240 | LOG(IndexedDB, "IDBDatabase::close - %" PRIu64, m_databaseConnectionIdentifier); |
241 | |
242 | ASSERT(&originThread() == &Thread::current()); |
243 | |
244 | if (!m_closePending) { |
245 | m_closePending = true; |
246 | m_connectionProxy->databaseConnectionPendingClose(*this); |
247 | } |
248 | |
249 | maybeCloseInServer(); |
250 | } |
251 | |
252 | void IDBDatabase::didCloseFromServer(const IDBError& error) |
253 | { |
254 | LOG(IndexedDB, "IDBDatabase::didCloseFromServer - %" PRIu64, m_databaseConnectionIdentifier); |
255 | |
256 | connectionToServerLost(error); |
257 | |
258 | m_connectionProxy->confirmDidCloseFromServer(*this); |
259 | } |
260 | |
261 | void IDBDatabase::connectionToServerLost(const IDBError& error) |
262 | { |
263 | LOG(IndexedDB, "IDBDatabase::connectionToServerLost - %" PRIu64, m_databaseConnectionIdentifier); |
264 | |
265 | ASSERT(&originThread() == &Thread::current()); |
266 | |
267 | m_closePending = true; |
268 | m_closedInServer = true; |
269 | |
270 | auto activeTransactions = copyToVector(m_activeTransactions.values()); |
271 | for (auto& transaction : activeTransactions) |
272 | transaction->connectionClosedFromServer(error); |
273 | |
274 | auto committingTransactions = copyToVector(m_committingTransactions.values()); |
275 | for (auto& transaction : committingTransactions) |
276 | transaction->connectionClosedFromServer(error); |
277 | |
278 | auto errorEvent = Event::create(m_eventNames.errorEvent, Event::CanBubble::Yes, Event::IsCancelable::No); |
279 | errorEvent->setTarget(this); |
280 | |
281 | if (auto* context = scriptExecutionContext()) |
282 | context->eventQueue().enqueueEvent(WTFMove(errorEvent)); |
283 | |
284 | auto closeEvent = Event::create(m_eventNames.closeEvent, Event::CanBubble::Yes, Event::IsCancelable::No); |
285 | closeEvent->setTarget(this); |
286 | |
287 | if (auto* context = scriptExecutionContext()) |
288 | context->eventQueue().enqueueEvent(WTFMove(closeEvent)); |
289 | } |
290 | |
291 | void IDBDatabase::maybeCloseInServer() |
292 | { |
293 | LOG(IndexedDB, "IDBDatabase::maybeCloseInServer - %" PRIu64, m_databaseConnectionIdentifier); |
294 | |
295 | ASSERT(&originThread() == &Thread::current()); |
296 | |
297 | if (m_closedInServer) |
298 | return; |
299 | |
300 | // 3.3.9 Database closing steps |
301 | // Wait for all transactions created using this connection to complete. |
302 | // Once they are complete, this connection is closed. |
303 | if (!m_activeTransactions.isEmpty() || !m_committingTransactions.isEmpty()) |
304 | return; |
305 | |
306 | m_closedInServer = true; |
307 | m_connectionProxy->databaseConnectionClosed(*this); |
308 | } |
309 | |
310 | const char* IDBDatabase::activeDOMObjectName() const |
311 | { |
312 | ASSERT(&originThread() == &Thread::current()); |
313 | return "IDBDatabase" ; |
314 | } |
315 | |
316 | bool IDBDatabase::canSuspendForDocumentSuspension() const |
317 | { |
318 | ASSERT(&originThread() == &Thread::current()); |
319 | |
320 | // FIXME: This value will sometimes be false when database operations are actually in progress. |
321 | // Such database operations do not yet exist. |
322 | return true; |
323 | } |
324 | |
325 | void IDBDatabase::stop() |
326 | { |
327 | LOG(IndexedDB, "IDBDatabase::stop - %" PRIu64, m_databaseConnectionIdentifier); |
328 | |
329 | ASSERT(&originThread() == &Thread::current()); |
330 | |
331 | removeAllEventListeners(); |
332 | |
333 | Vector<IDBResourceIdentifier> transactionIdentifiers; |
334 | transactionIdentifiers.reserveInitialCapacity(m_activeTransactions.size()); |
335 | |
336 | for (auto& id : m_activeTransactions.keys()) |
337 | transactionIdentifiers.uncheckedAppend(id); |
338 | |
339 | for (auto& id : transactionIdentifiers) { |
340 | IDBTransaction* transaction = m_activeTransactions.get(id); |
341 | if (transaction) |
342 | transaction->stop(); |
343 | } |
344 | |
345 | close(); |
346 | } |
347 | |
348 | Ref<IDBTransaction> IDBDatabase::startVersionChangeTransaction(const IDBTransactionInfo& info, IDBOpenDBRequest& request) |
349 | { |
350 | LOG(IndexedDB, "IDBDatabase::startVersionChangeTransaction %s" , info.identifier().loggingString().utf8().data()); |
351 | |
352 | ASSERT(&originThread() == &Thread::current()); |
353 | ASSERT(!m_versionChangeTransaction); |
354 | ASSERT(info.mode() == IDBTransactionMode::Versionchange); |
355 | ASSERT(!m_closePending); |
356 | ASSERT(scriptExecutionContext()); |
357 | |
358 | Ref<IDBTransaction> transaction = IDBTransaction::create(*this, info, request); |
359 | m_versionChangeTransaction = &transaction.get(); |
360 | |
361 | m_activeTransactions.set(transaction->info().identifier(), &transaction.get()); |
362 | |
363 | return transaction; |
364 | } |
365 | |
366 | void IDBDatabase::didStartTransaction(IDBTransaction& transaction) |
367 | { |
368 | LOG(IndexedDB, "IDBDatabase::didStartTransaction %s" , transaction.info().identifier().loggingString().utf8().data()); |
369 | ASSERT(!m_versionChangeTransaction); |
370 | ASSERT(&originThread() == &Thread::current()); |
371 | |
372 | // It is possible for the client to have aborted a transaction before the server replies back that it has started. |
373 | if (m_abortingTransactions.contains(transaction.info().identifier())) |
374 | return; |
375 | |
376 | m_activeTransactions.set(transaction.info().identifier(), &transaction); |
377 | } |
378 | |
379 | void IDBDatabase::willCommitTransaction(IDBTransaction& transaction) |
380 | { |
381 | LOG(IndexedDB, "IDBDatabase::willCommitTransaction %s" , transaction.info().identifier().loggingString().utf8().data()); |
382 | |
383 | ASSERT(&originThread() == &Thread::current()); |
384 | |
385 | auto refTransaction = m_activeTransactions.take(transaction.info().identifier()); |
386 | ASSERT(refTransaction); |
387 | m_committingTransactions.set(transaction.info().identifier(), WTFMove(refTransaction)); |
388 | } |
389 | |
390 | void IDBDatabase::didCommitTransaction(IDBTransaction& transaction) |
391 | { |
392 | LOG(IndexedDB, "IDBDatabase::didCommitTransaction %s" , transaction.info().identifier().loggingString().utf8().data()); |
393 | |
394 | ASSERT(&originThread() == &Thread::current()); |
395 | |
396 | if (m_versionChangeTransaction == &transaction) |
397 | m_info.setVersion(transaction.info().newVersion()); |
398 | |
399 | didCommitOrAbortTransaction(transaction); |
400 | } |
401 | |
402 | void IDBDatabase::willAbortTransaction(IDBTransaction& transaction) |
403 | { |
404 | LOG(IndexedDB, "IDBDatabase::willAbortTransaction %s" , transaction.info().identifier().loggingString().utf8().data()); |
405 | |
406 | ASSERT(&originThread() == &Thread::current()); |
407 | |
408 | auto refTransaction = m_activeTransactions.take(transaction.info().identifier()); |
409 | if (!refTransaction) |
410 | refTransaction = m_committingTransactions.take(transaction.info().identifier()); |
411 | |
412 | ASSERT(refTransaction); |
413 | m_abortingTransactions.set(transaction.info().identifier(), WTFMove(refTransaction)); |
414 | |
415 | if (transaction.isVersionChange()) { |
416 | ASSERT(transaction.originalDatabaseInfo()); |
417 | m_info = *transaction.originalDatabaseInfo(); |
418 | m_closePending = true; |
419 | } |
420 | } |
421 | |
422 | void IDBDatabase::didAbortTransaction(IDBTransaction& transaction) |
423 | { |
424 | LOG(IndexedDB, "IDBDatabase::didAbortTransaction %s" , transaction.info().identifier().loggingString().utf8().data()); |
425 | |
426 | ASSERT(&originThread() == &Thread::current()); |
427 | |
428 | if (transaction.isVersionChange()) { |
429 | ASSERT(transaction.originalDatabaseInfo()); |
430 | ASSERT(m_info.version() == transaction.originalDatabaseInfo()->version()); |
431 | m_closePending = true; |
432 | maybeCloseInServer(); |
433 | } |
434 | |
435 | didCommitOrAbortTransaction(transaction); |
436 | } |
437 | |
438 | void IDBDatabase::didCommitOrAbortTransaction(IDBTransaction& transaction) |
439 | { |
440 | LOG(IndexedDB, "IDBDatabase::didCommitOrAbortTransaction %s" , transaction.info().identifier().loggingString().utf8().data()); |
441 | |
442 | ASSERT(&originThread() == &Thread::current()); |
443 | |
444 | if (m_versionChangeTransaction == &transaction) |
445 | m_versionChangeTransaction = nullptr; |
446 | |
447 | #ifndef NDBEBUG |
448 | unsigned count = 0; |
449 | if (m_activeTransactions.contains(transaction.info().identifier())) |
450 | ++count; |
451 | if (m_committingTransactions.contains(transaction.info().identifier())) |
452 | ++count; |
453 | if (m_abortingTransactions.contains(transaction.info().identifier())) |
454 | ++count; |
455 | |
456 | ASSERT(count == 1); |
457 | #endif |
458 | |
459 | m_activeTransactions.remove(transaction.info().identifier()); |
460 | m_committingTransactions.remove(transaction.info().identifier()); |
461 | m_abortingTransactions.remove(transaction.info().identifier()); |
462 | |
463 | if (m_closePending) |
464 | maybeCloseInServer(); |
465 | } |
466 | |
467 | void IDBDatabase::fireVersionChangeEvent(const IDBResourceIdentifier& requestIdentifier, uint64_t requestedVersion) |
468 | { |
469 | uint64_t currentVersion = m_info.version(); |
470 | LOG(IndexedDB, "IDBDatabase::fireVersionChangeEvent - current version %" PRIu64 ", requested version %" PRIu64 ", connection %" PRIu64 " (%p)" , currentVersion, requestedVersion, m_databaseConnectionIdentifier, this); |
471 | |
472 | ASSERT(&originThread() == &Thread::current()); |
473 | |
474 | if (!scriptExecutionContext() || m_closePending) { |
475 | connectionProxy().didFireVersionChangeEvent(m_databaseConnectionIdentifier, requestIdentifier); |
476 | return; |
477 | } |
478 | |
479 | Ref<Event> event = IDBVersionChangeEvent::create(requestIdentifier, currentVersion, requestedVersion, m_eventNames.versionchangeEvent); |
480 | event->setTarget(this); |
481 | scriptExecutionContext()->eventQueue().enqueueEvent(WTFMove(event)); |
482 | } |
483 | |
484 | void IDBDatabase::dispatchEvent(Event& event) |
485 | { |
486 | LOG(IndexedDB, "IDBDatabase::dispatchEvent (%" PRIu64 ") (%p)" , m_databaseConnectionIdentifier, this); |
487 | ASSERT(&originThread() == &Thread::current()); |
488 | |
489 | auto protectedThis = makeRef(*this); |
490 | |
491 | EventTargetWithInlineData::dispatchEvent(event); |
492 | |
493 | if (event.isVersionChangeEvent() && event.type() == m_eventNames.versionchangeEvent) |
494 | m_connectionProxy->didFireVersionChangeEvent(m_databaseConnectionIdentifier, downcast<IDBVersionChangeEvent>(event).requestIdentifier()); |
495 | } |
496 | |
497 | void IDBDatabase::didCreateIndexInfo(const IDBIndexInfo& info) |
498 | { |
499 | ASSERT(&originThread() == &Thread::current()); |
500 | |
501 | auto* objectStore = m_info.infoForExistingObjectStore(info.objectStoreIdentifier()); |
502 | ASSERT(objectStore); |
503 | objectStore->addExistingIndex(info); |
504 | } |
505 | |
506 | void IDBDatabase::didDeleteIndexInfo(const IDBIndexInfo& info) |
507 | { |
508 | ASSERT(&originThread() == &Thread::current()); |
509 | |
510 | auto* objectStore = m_info.infoForExistingObjectStore(info.objectStoreIdentifier()); |
511 | ASSERT(objectStore); |
512 | objectStore->deleteIndex(info.name()); |
513 | } |
514 | |
515 | } // namespace WebCore |
516 | |
517 | #endif // ENABLE(INDEXED_DATABASE) |
518 | |