1 | /* |
2 | * Copyright (C) 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 "IDBConnectionProxy.h" |
28 | |
29 | #if ENABLE(INDEXED_DATABASE) |
30 | |
31 | #include "IDBCursorInfo.h" |
32 | #include "IDBDatabase.h" |
33 | #include "IDBGetRecordData.h" |
34 | #include "IDBIterateCursorData.h" |
35 | #include "IDBKeyRangeData.h" |
36 | #include "IDBOpenDBRequest.h" |
37 | #include "IDBRequestData.h" |
38 | #include "IDBResultData.h" |
39 | #include "ScriptExecutionContext.h" |
40 | #include "SecurityOrigin.h" |
41 | #include <wtf/MainThread.h> |
42 | |
43 | namespace WebCore { |
44 | namespace IDBClient { |
45 | |
46 | IDBConnectionProxy::IDBConnectionProxy(IDBConnectionToServer& connection) |
47 | : m_connectionToServer(connection) |
48 | , m_serverConnectionIdentifier(connection.identifier()) |
49 | { |
50 | ASSERT(isMainThread()); |
51 | } |
52 | |
53 | void IDBConnectionProxy::ref() |
54 | { |
55 | m_connectionToServer.ref(); |
56 | } |
57 | |
58 | void IDBConnectionProxy::deref() |
59 | { |
60 | m_connectionToServer.deref(); |
61 | } |
62 | |
63 | Ref<IDBOpenDBRequest> IDBConnectionProxy::openDatabase(ScriptExecutionContext& context, const IDBDatabaseIdentifier& databaseIdentifier, uint64_t version) |
64 | { |
65 | RefPtr<IDBOpenDBRequest> request; |
66 | { |
67 | Locker<Lock> locker(m_openDBRequestMapLock); |
68 | |
69 | request = IDBOpenDBRequest::createOpenRequest(context, *this, databaseIdentifier, version); |
70 | ASSERT(!m_openDBRequestMap.contains(request->resourceIdentifier())); |
71 | m_openDBRequestMap.set(request->resourceIdentifier(), request.get()); |
72 | } |
73 | |
74 | callConnectionOnMainThread(&IDBConnectionToServer::openDatabase, IDBRequestData(*this, *request)); |
75 | |
76 | return request.releaseNonNull(); |
77 | } |
78 | |
79 | Ref<IDBOpenDBRequest> IDBConnectionProxy::deleteDatabase(ScriptExecutionContext& context, const IDBDatabaseIdentifier& databaseIdentifier) |
80 | { |
81 | RefPtr<IDBOpenDBRequest> request; |
82 | { |
83 | Locker<Lock> locker(m_openDBRequestMapLock); |
84 | |
85 | request = IDBOpenDBRequest::createDeleteRequest(context, *this, databaseIdentifier); |
86 | ASSERT(!m_openDBRequestMap.contains(request->resourceIdentifier())); |
87 | m_openDBRequestMap.set(request->resourceIdentifier(), request.get()); |
88 | } |
89 | |
90 | callConnectionOnMainThread(&IDBConnectionToServer::deleteDatabase, IDBRequestData(*this, *request)); |
91 | |
92 | return request.releaseNonNull(); |
93 | } |
94 | |
95 | void IDBConnectionProxy::didOpenDatabase(const IDBResultData& resultData) |
96 | { |
97 | completeOpenDBRequest(resultData); |
98 | } |
99 | |
100 | void IDBConnectionProxy::didDeleteDatabase(const IDBResultData& resultData) |
101 | { |
102 | completeOpenDBRequest(resultData); |
103 | } |
104 | |
105 | void IDBConnectionProxy::completeOpenDBRequest(const IDBResultData& resultData) |
106 | { |
107 | ASSERT(isMainThread()); |
108 | |
109 | RefPtr<IDBOpenDBRequest> request; |
110 | { |
111 | Locker<Lock> locker(m_openDBRequestMapLock); |
112 | request = m_openDBRequestMap.take(resultData.requestIdentifier()); |
113 | } |
114 | |
115 | if (!request) |
116 | return; |
117 | |
118 | request->performCallbackOnOriginThread(*request, &IDBOpenDBRequest::requestCompleted, resultData); |
119 | } |
120 | |
121 | void IDBConnectionProxy::createObjectStore(TransactionOperation& operation, const IDBObjectStoreInfo& info) |
122 | { |
123 | const IDBRequestData requestData { operation }; |
124 | saveOperation(operation); |
125 | |
126 | callConnectionOnMainThread(&IDBConnectionToServer::createObjectStore, requestData, info); |
127 | } |
128 | |
129 | void IDBConnectionProxy::renameObjectStore(TransactionOperation& operation, uint64_t objectStoreIdentifier, const String& newName) |
130 | { |
131 | const IDBRequestData requestData { operation }; |
132 | saveOperation(operation); |
133 | |
134 | callConnectionOnMainThread(&IDBConnectionToServer::renameObjectStore, requestData, objectStoreIdentifier, newName); |
135 | } |
136 | |
137 | void IDBConnectionProxy::renameIndex(TransactionOperation& operation, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName) |
138 | { |
139 | const IDBRequestData requestData { operation }; |
140 | saveOperation(operation); |
141 | |
142 | callConnectionOnMainThread(&IDBConnectionToServer::renameIndex, requestData, objectStoreIdentifier, indexIdentifier, newName); |
143 | } |
144 | |
145 | void IDBConnectionProxy::deleteObjectStore(TransactionOperation& operation, const String& objectStoreName) |
146 | { |
147 | const IDBRequestData requestData { operation }; |
148 | saveOperation(operation); |
149 | |
150 | callConnectionOnMainThread(&IDBConnectionToServer::deleteObjectStore, requestData, objectStoreName); |
151 | } |
152 | |
153 | void IDBConnectionProxy::clearObjectStore(TransactionOperation& operation, uint64_t objectStoreIdentifier) |
154 | { |
155 | const IDBRequestData requestData { operation }; |
156 | saveOperation(operation); |
157 | |
158 | callConnectionOnMainThread(&IDBConnectionToServer::clearObjectStore, requestData, objectStoreIdentifier); |
159 | } |
160 | |
161 | void IDBConnectionProxy::createIndex(TransactionOperation& operation, const IDBIndexInfo& info) |
162 | { |
163 | const IDBRequestData requestData { operation }; |
164 | saveOperation(operation); |
165 | |
166 | callConnectionOnMainThread(&IDBConnectionToServer::createIndex, requestData, info); |
167 | } |
168 | |
169 | void IDBConnectionProxy::deleteIndex(TransactionOperation& operation, uint64_t objectStoreIdentifier, const String& indexName) |
170 | { |
171 | const IDBRequestData requestData { operation }; |
172 | saveOperation(operation); |
173 | |
174 | callConnectionOnMainThread(&IDBConnectionToServer::deleteIndex, requestData, WTFMove(objectStoreIdentifier), indexName); |
175 | } |
176 | |
177 | void IDBConnectionProxy::putOrAdd(TransactionOperation& operation, IDBKeyData&& keyData, const IDBValue& value, const IndexedDB::ObjectStoreOverwriteMode mode) |
178 | { |
179 | const IDBRequestData requestData { operation }; |
180 | saveOperation(operation); |
181 | |
182 | callConnectionOnMainThread(&IDBConnectionToServer::putOrAdd, requestData, keyData, value, mode); |
183 | } |
184 | |
185 | void IDBConnectionProxy::getRecord(TransactionOperation& operation, const IDBGetRecordData& getRecordData) |
186 | { |
187 | const IDBRequestData requestData { operation }; |
188 | saveOperation(operation); |
189 | |
190 | callConnectionOnMainThread(&IDBConnectionToServer::getRecord, requestData, getRecordData); |
191 | } |
192 | |
193 | void IDBConnectionProxy::getAllRecords(TransactionOperation& operation, const IDBGetAllRecordsData& getAllRecordsData) |
194 | { |
195 | const IDBRequestData requestData { operation }; |
196 | saveOperation(operation); |
197 | |
198 | callConnectionOnMainThread(&IDBConnectionToServer::getAllRecords, requestData, getAllRecordsData); |
199 | } |
200 | |
201 | void IDBConnectionProxy::getCount(TransactionOperation& operation, const IDBKeyRangeData& keyRange) |
202 | { |
203 | const IDBRequestData requestData { operation }; |
204 | saveOperation(operation); |
205 | |
206 | callConnectionOnMainThread(&IDBConnectionToServer::getCount, requestData, keyRange); |
207 | } |
208 | |
209 | void IDBConnectionProxy::deleteRecord(TransactionOperation& operation, const IDBKeyRangeData& keyRange) |
210 | { |
211 | const IDBRequestData requestData { operation }; |
212 | saveOperation(operation); |
213 | |
214 | callConnectionOnMainThread(&IDBConnectionToServer::deleteRecord, requestData, keyRange); |
215 | } |
216 | |
217 | void IDBConnectionProxy::openCursor(TransactionOperation& operation, const IDBCursorInfo& info) |
218 | { |
219 | const IDBRequestData requestData { operation }; |
220 | saveOperation(operation); |
221 | |
222 | callConnectionOnMainThread(&IDBConnectionToServer::openCursor, requestData, info); |
223 | } |
224 | |
225 | void IDBConnectionProxy::iterateCursor(TransactionOperation& operation, const IDBIterateCursorData& data) |
226 | { |
227 | const IDBRequestData requestData { operation }; |
228 | saveOperation(operation); |
229 | |
230 | callConnectionOnMainThread(&IDBConnectionToServer::iterateCursor, requestData, data); |
231 | } |
232 | |
233 | void IDBConnectionProxy::saveOperation(TransactionOperation& operation) |
234 | { |
235 | Locker<Lock> locker(m_transactionOperationLock); |
236 | |
237 | ASSERT(!m_activeOperations.contains(operation.identifier())); |
238 | m_activeOperations.set(operation.identifier(), &operation); |
239 | } |
240 | |
241 | void IDBConnectionProxy::completeOperation(const IDBResultData& resultData) |
242 | { |
243 | RefPtr<TransactionOperation> operation; |
244 | { |
245 | Locker<Lock> locker(m_transactionOperationLock); |
246 | operation = m_activeOperations.take(resultData.requestIdentifier()); |
247 | } |
248 | |
249 | if (!operation) |
250 | return; |
251 | |
252 | operation->transitionToComplete(resultData, WTFMove(operation)); |
253 | } |
254 | |
255 | void IDBConnectionProxy::abortOpenAndUpgradeNeeded(uint64_t databaseConnectionIdentifier, const IDBResourceIdentifier& transactionIdentifier) |
256 | { |
257 | callConnectionOnMainThread(&IDBConnectionToServer::abortOpenAndUpgradeNeeded, databaseConnectionIdentifier, transactionIdentifier); |
258 | } |
259 | |
260 | void IDBConnectionProxy::fireVersionChangeEvent(uint64_t databaseConnectionIdentifier, const IDBResourceIdentifier& requestIdentifier, uint64_t requestedVersion) |
261 | { |
262 | RefPtr<IDBDatabase> database; |
263 | { |
264 | Locker<Lock> locker(m_databaseConnectionMapLock); |
265 | database = m_databaseConnectionMap.get(databaseConnectionIdentifier); |
266 | } |
267 | |
268 | if (!database) |
269 | return; |
270 | |
271 | database->performCallbackOnOriginThread(*database, &IDBDatabase::fireVersionChangeEvent, requestIdentifier, requestedVersion); |
272 | } |
273 | |
274 | void IDBConnectionProxy::didFireVersionChangeEvent(uint64_t databaseConnectionIdentifier, const IDBResourceIdentifier& requestIdentifier) |
275 | { |
276 | callConnectionOnMainThread(&IDBConnectionToServer::didFireVersionChangeEvent, databaseConnectionIdentifier, requestIdentifier); |
277 | } |
278 | |
279 | void IDBConnectionProxy::notifyOpenDBRequestBlocked(const IDBResourceIdentifier& requestIdentifier, uint64_t oldVersion, uint64_t newVersion) |
280 | { |
281 | ASSERT(isMainThread()); |
282 | |
283 | RefPtr<IDBOpenDBRequest> request; |
284 | { |
285 | Locker<Lock> locker(m_openDBRequestMapLock); |
286 | request = m_openDBRequestMap.get(requestIdentifier); |
287 | } |
288 | |
289 | if (!request) |
290 | return; |
291 | |
292 | request->performCallbackOnOriginThread(*request, &IDBOpenDBRequest::requestBlocked, oldVersion, newVersion); |
293 | } |
294 | |
295 | void IDBConnectionProxy::openDBRequestCancelled(const IDBRequestData& requestData) |
296 | { |
297 | callConnectionOnMainThread(&IDBConnectionToServer::openDBRequestCancelled, requestData); |
298 | } |
299 | |
300 | void IDBConnectionProxy::establishTransaction(IDBTransaction& transaction) |
301 | { |
302 | { |
303 | Locker<Lock> locker(m_transactionMapLock); |
304 | ASSERT(!hasRecordOfTransaction(transaction)); |
305 | m_pendingTransactions.set(transaction.info().identifier(), &transaction); |
306 | } |
307 | |
308 | callConnectionOnMainThread(&IDBConnectionToServer::establishTransaction, transaction.database().databaseConnectionIdentifier(), transaction.info()); |
309 | } |
310 | |
311 | void IDBConnectionProxy::didStartTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error) |
312 | { |
313 | RefPtr<IDBTransaction> transaction; |
314 | { |
315 | Locker<Lock> locker(m_transactionMapLock); |
316 | transaction = m_pendingTransactions.take(transactionIdentifier); |
317 | } |
318 | |
319 | if (!transaction) |
320 | return; |
321 | |
322 | transaction->performCallbackOnOriginThread(*transaction, &IDBTransaction::didStart, error); |
323 | } |
324 | |
325 | void IDBConnectionProxy::commitTransaction(IDBTransaction& transaction) |
326 | { |
327 | { |
328 | Locker<Lock> locker(m_transactionMapLock); |
329 | ASSERT(!m_committingTransactions.contains(transaction.info().identifier())); |
330 | m_committingTransactions.set(transaction.info().identifier(), &transaction); |
331 | } |
332 | |
333 | callConnectionOnMainThread(&IDBConnectionToServer::commitTransaction, transaction.info().identifier()); |
334 | } |
335 | |
336 | void IDBConnectionProxy::didCommitTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error) |
337 | { |
338 | RefPtr<IDBTransaction> transaction; |
339 | { |
340 | Locker<Lock> locker(m_transactionMapLock); |
341 | transaction = m_committingTransactions.take(transactionIdentifier); |
342 | } |
343 | |
344 | if (!transaction) |
345 | return; |
346 | |
347 | transaction->performCallbackOnOriginThread(*transaction, &IDBTransaction::didCommit, error); |
348 | } |
349 | |
350 | void IDBConnectionProxy::abortTransaction(IDBTransaction& transaction) |
351 | { |
352 | { |
353 | Locker<Lock> locker(m_transactionMapLock); |
354 | ASSERT(!m_abortingTransactions.contains(transaction.info().identifier())); |
355 | m_abortingTransactions.set(transaction.info().identifier(), &transaction); |
356 | } |
357 | |
358 | callConnectionOnMainThread(&IDBConnectionToServer::abortTransaction, transaction.info().identifier()); |
359 | } |
360 | |
361 | void IDBConnectionProxy::didAbortTransaction(const IDBResourceIdentifier& transactionIdentifier, const IDBError& error) |
362 | { |
363 | RefPtr<IDBTransaction> transaction; |
364 | { |
365 | Locker<Lock> locker(m_transactionMapLock); |
366 | transaction = m_abortingTransactions.take(transactionIdentifier); |
367 | } |
368 | |
369 | if (!transaction) |
370 | return; |
371 | |
372 | transaction->performCallbackOnOriginThread(*transaction, &IDBTransaction::didAbort, error); |
373 | } |
374 | |
375 | bool IDBConnectionProxy::hasRecordOfTransaction(const IDBTransaction& transaction) const |
376 | { |
377 | ASSERT(m_transactionMapLock.isLocked()); |
378 | |
379 | auto identifier = transaction.info().identifier(); |
380 | return m_pendingTransactions.contains(identifier) || m_committingTransactions.contains(identifier) || m_abortingTransactions.contains(identifier); |
381 | } |
382 | |
383 | void IDBConnectionProxy::didFinishHandlingVersionChangeTransaction(uint64_t databaseConnectionIdentifier, IDBTransaction& transaction) |
384 | { |
385 | callConnectionOnMainThread(&IDBConnectionToServer::didFinishHandlingVersionChangeTransaction, databaseConnectionIdentifier, transaction.info().identifier()); |
386 | } |
387 | |
388 | void IDBConnectionProxy::databaseConnectionPendingClose(IDBDatabase& database) |
389 | { |
390 | callConnectionOnMainThread(&IDBConnectionToServer::databaseConnectionPendingClose, database.databaseConnectionIdentifier()); |
391 | } |
392 | |
393 | void IDBConnectionProxy::databaseConnectionClosed(IDBDatabase& database) |
394 | { |
395 | callConnectionOnMainThread(&IDBConnectionToServer::databaseConnectionClosed, database.databaseConnectionIdentifier()); |
396 | } |
397 | |
398 | void IDBConnectionProxy::didCloseFromServer(uint64_t databaseConnectionIdentifier, const IDBError& error) |
399 | { |
400 | RefPtr<IDBDatabase> database; |
401 | { |
402 | Locker<Lock> locker(m_databaseConnectionMapLock); |
403 | database = m_databaseConnectionMap.get(databaseConnectionIdentifier); |
404 | } |
405 | |
406 | // If the IDBDatabase object is gone, message back to the server so it doesn't hang |
407 | // waiting for a reply that will never come. |
408 | if (!database) { |
409 | m_connectionToServer.confirmDidCloseFromServer(databaseConnectionIdentifier); |
410 | return; |
411 | } |
412 | |
413 | database->performCallbackOnOriginThread(*database, &IDBDatabase::didCloseFromServer, error); |
414 | } |
415 | |
416 | void IDBConnectionProxy::confirmDidCloseFromServer(IDBDatabase& database) |
417 | { |
418 | callConnectionOnMainThread(&IDBConnectionToServer::confirmDidCloseFromServer, database.databaseConnectionIdentifier()); |
419 | } |
420 | |
421 | void IDBConnectionProxy::connectionToServerLost(const IDBError& error) |
422 | { |
423 | Vector<uint64_t> databaseConnectionIdentifiers; |
424 | { |
425 | Locker<Lock> locker(m_databaseConnectionMapLock); |
426 | databaseConnectionIdentifiers = copyToVector(m_databaseConnectionMap.keys()); |
427 | } |
428 | |
429 | for (auto connectionIdentifier : databaseConnectionIdentifiers) { |
430 | RefPtr<IDBDatabase> database; |
431 | { |
432 | Locker<Lock> locker(m_databaseConnectionMapLock); |
433 | database = m_databaseConnectionMap.get(connectionIdentifier); |
434 | } |
435 | |
436 | if (!database) |
437 | continue; |
438 | |
439 | database->performCallbackOnOriginThread(*database, &IDBDatabase::connectionToServerLost, error); |
440 | } |
441 | |
442 | Vector<IDBResourceIdentifier> openDBRequestIdentifiers; |
443 | { |
444 | Locker<Lock> locker(m_openDBRequestMapLock); |
445 | openDBRequestIdentifiers = copyToVector(m_openDBRequestMap.keys()); |
446 | } |
447 | |
448 | for (auto& requestIdentifier : openDBRequestIdentifiers) { |
449 | RefPtr<IDBOpenDBRequest> request; |
450 | { |
451 | Locker<Lock> locker(m_openDBRequestMapLock); |
452 | request = m_openDBRequestMap.get(requestIdentifier); |
453 | } |
454 | |
455 | if (!request) |
456 | continue; |
457 | |
458 | auto result = IDBResultData::error(requestIdentifier, error); |
459 | request->performCallbackOnOriginThread(*request, &IDBOpenDBRequest::requestCompleted, result); |
460 | } |
461 | } |
462 | |
463 | void IDBConnectionProxy::scheduleMainThreadTasks() |
464 | { |
465 | Locker<Lock> locker(m_mainThreadTaskLock); |
466 | if (m_mainThreadProtector) |
467 | return; |
468 | |
469 | m_mainThreadProtector = &m_connectionToServer; |
470 | callOnMainThread([this] { |
471 | handleMainThreadTasks(); |
472 | }); |
473 | } |
474 | |
475 | void IDBConnectionProxy::handleMainThreadTasks() |
476 | { |
477 | RefPtr<IDBConnectionToServer> protector; |
478 | { |
479 | Locker<Lock> locker(m_mainThreadTaskLock); |
480 | ASSERT(m_mainThreadProtector); |
481 | protector = WTFMove(m_mainThreadProtector); |
482 | } |
483 | |
484 | while (auto task = m_mainThreadQueue.tryGetMessage()) |
485 | task->performTask(); |
486 | } |
487 | |
488 | void IDBConnectionProxy::getAllDatabaseNames(const SecurityOrigin& mainFrameOrigin, const SecurityOrigin& openingOrigin, Function<void (const Vector<String>&)>&& callback) |
489 | { |
490 | // This method is only meant to be called by the web inspector on the main thread. |
491 | RELEASE_ASSERT(isMainThread()); |
492 | |
493 | m_connectionToServer.getAllDatabaseNames(mainFrameOrigin, openingOrigin, WTFMove(callback)); |
494 | } |
495 | |
496 | void IDBConnectionProxy::registerDatabaseConnection(IDBDatabase& database) |
497 | { |
498 | Locker<Lock> locker(m_databaseConnectionMapLock); |
499 | |
500 | ASSERT(!m_databaseConnectionMap.contains(database.databaseConnectionIdentifier())); |
501 | m_databaseConnectionMap.set(database.databaseConnectionIdentifier(), &database); |
502 | } |
503 | |
504 | void IDBConnectionProxy::unregisterDatabaseConnection(IDBDatabase& database) |
505 | { |
506 | Locker<Lock> locker(m_databaseConnectionMapLock); |
507 | |
508 | ASSERT(!m_databaseConnectionMap.contains(database.databaseConnectionIdentifier()) || m_databaseConnectionMap.get(database.databaseConnectionIdentifier()) == &database); |
509 | m_databaseConnectionMap.remove(database.databaseConnectionIdentifier()); |
510 | } |
511 | |
512 | void IDBConnectionProxy::forgetActiveOperations(const Vector<RefPtr<TransactionOperation>>& operations) |
513 | { |
514 | Locker<Lock> locker(m_transactionOperationLock); |
515 | |
516 | for (auto& operation : operations) |
517 | m_activeOperations.remove(operation->identifier()); |
518 | } |
519 | |
520 | void IDBConnectionProxy::forgetTransaction(IDBTransaction& transaction) |
521 | { |
522 | Locker<Lock> locker(m_transactionMapLock); |
523 | |
524 | m_pendingTransactions.remove(transaction.info().identifier()); |
525 | m_committingTransactions.remove(transaction.info().identifier()); |
526 | m_abortingTransactions.remove(transaction.info().identifier()); |
527 | } |
528 | |
529 | template<typename KeyType, typename ValueType> |
530 | void removeItemsMatchingCurrentThread(HashMap<KeyType, ValueType>& map) |
531 | { |
532 | auto& currentThread = Thread::current(); |
533 | |
534 | Vector<KeyType> keys; |
535 | keys.reserveInitialCapacity(map.size()); |
536 | for (auto& iterator : map) { |
537 | if (&iterator.value->originThread() == ¤tThread) |
538 | keys.uncheckedAppend(iterator.key); |
539 | } |
540 | |
541 | for (auto& key : keys) |
542 | map.remove(key); |
543 | } |
544 | |
545 | void IDBConnectionProxy::forgetActivityForCurrentThread() |
546 | { |
547 | ASSERT(!isMainThread()); |
548 | |
549 | { |
550 | Locker<Lock> lock(m_databaseConnectionMapLock); |
551 | removeItemsMatchingCurrentThread(m_databaseConnectionMap); |
552 | } |
553 | { |
554 | Locker<Lock> lock(m_openDBRequestMapLock); |
555 | removeItemsMatchingCurrentThread(m_openDBRequestMap); |
556 | } |
557 | { |
558 | Locker<Lock> lock(m_transactionMapLock); |
559 | removeItemsMatchingCurrentThread(m_pendingTransactions); |
560 | removeItemsMatchingCurrentThread(m_committingTransactions); |
561 | removeItemsMatchingCurrentThread(m_abortingTransactions); |
562 | } |
563 | { |
564 | Locker<Lock> lock(m_transactionOperationLock); |
565 | removeItemsMatchingCurrentThread(m_activeOperations); |
566 | } |
567 | } |
568 | |
569 | } // namesapce IDBClient |
570 | } // namespace WebCore |
571 | |
572 | #endif // ENABLE(INDEXED_DATABASE) |
573 | |