1/*
2 * Copyright (C) 2015 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#pragma once
27
28#if ENABLE(INDEXED_DATABASE)
29
30#include "IDBBackingStore.h"
31#include "IDBDatabaseIdentifier.h"
32#include "IDBDatabaseInfo.h"
33#include "IDBGetResult.h"
34#include "ServerOpenDBRequest.h"
35#include "Timer.h"
36#include "UniqueIDBDatabaseConnection.h"
37#include "UniqueIDBDatabaseTransaction.h"
38#include <wtf/CrossThreadQueue.h>
39#include <wtf/CrossThreadTask.h>
40#include <wtf/Deque.h>
41#include <wtf/Function.h>
42#include <wtf/HashCountedSet.h>
43#include <wtf/HashSet.h>
44#include <wtf/ListHashSet.h>
45
46namespace JSC {
47class ExecState;
48class VM;
49}
50
51namespace WebCore {
52
53class IDBError;
54class IDBGetAllResult;
55class IDBRequestData;
56class IDBTransactionInfo;
57class StorageQuotaManager;
58
59enum class IDBGetRecordDataType;
60
61namespace IndexedDB {
62enum class IndexRecordType;
63}
64
65namespace IDBServer {
66
67class IDBConnectionToClient;
68class IDBServer;
69
70typedef Function<void(const IDBError&)> ErrorCallback;
71typedef Function<void(const IDBError&, const IDBKeyData&)> KeyDataCallback;
72typedef Function<void(const IDBError&, const IDBGetResult&)> GetResultCallback;
73typedef Function<void(const IDBError&, const IDBGetAllResult&)> GetAllResultsCallback;
74typedef Function<void(const IDBError&, uint64_t)> CountCallback;
75
76class UniqueIDBDatabase : public CanMakeWeakPtr<UniqueIDBDatabase> {
77 WTF_MAKE_FAST_ALLOCATED;
78public:
79 UniqueIDBDatabase(IDBServer&, const IDBDatabaseIdentifier&);
80 UniqueIDBDatabase(UniqueIDBDatabase&) = delete;
81 WEBCORE_EXPORT ~UniqueIDBDatabase();
82
83 void openDatabaseConnection(IDBConnectionToClient&, const IDBRequestData&);
84
85 const IDBDatabaseInfo& info() const;
86 IDBServer& server() { return m_server.get(); }
87 const IDBDatabaseIdentifier& identifier() const { return m_identifier; }
88
89 void createObjectStore(UniqueIDBDatabaseTransaction&, const IDBObjectStoreInfo&, ErrorCallback);
90 void deleteObjectStore(UniqueIDBDatabaseTransaction&, const String& objectStoreName, ErrorCallback);
91 void renameObjectStore(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback);
92 void clearObjectStore(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, ErrorCallback);
93 void createIndex(UniqueIDBDatabaseTransaction&, const IDBIndexInfo&, ErrorCallback);
94 void deleteIndex(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback);
95 void renameIndex(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback);
96 void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback);
97 void getRecord(const IDBRequestData&, const IDBGetRecordData&, GetResultCallback);
98 void getAllRecords(const IDBRequestData&, const IDBGetAllRecordsData&, GetAllResultsCallback);
99 void getCount(const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
100 void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
101 void openCursor(const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
102 void iterateCursor(const IDBRequestData&, const IDBIterateCursorData&, GetResultCallback);
103 void commitTransaction(UniqueIDBDatabaseTransaction&, ErrorCallback);
104
105 enum class WaitForPendingTasks { No, Yes };
106 void abortTransaction(UniqueIDBDatabaseTransaction&, WaitForPendingTasks, ErrorCallback);
107
108 void didFinishHandlingVersionChange(UniqueIDBDatabaseConnection&, const IDBResourceIdentifier& transactionIdentifier);
109 void transactionDestroyed(UniqueIDBDatabaseTransaction&);
110 void connectionClosedFromClient(UniqueIDBDatabaseConnection&);
111 void confirmConnectionClosedOnServer(UniqueIDBDatabaseConnection&);
112 void didFireVersionChangeEvent(UniqueIDBDatabaseConnection&, const IDBResourceIdentifier& requestIdentifier);
113 void openDBRequestCancelled(const IDBResourceIdentifier& requestIdentifier);
114 void confirmDidCloseFromServer(UniqueIDBDatabaseConnection&);
115
116 void enqueueTransaction(Ref<UniqueIDBDatabaseTransaction>&&);
117
118 void handleDelete(IDBConnectionToClient&, const IDBRequestData&);
119 void immediateCloseForUserDelete();
120
121 static JSC::VM& databaseThreadVM();
122 static JSC::ExecState& databaseThreadExecState();
123
124 bool hardClosedForUserDelete() const { return m_hardClosedForUserDelete; }
125
126 uint64_t spaceUsed() const;
127
128 void setQuota(uint64_t);
129
130 void finishActiveTransactions();
131
132private:
133 void handleDatabaseOperations();
134 void handleCurrentOperation();
135 void performCurrentOpenOperation();
136 void performCurrentDeleteOperation();
137 void addOpenDatabaseConnection(Ref<UniqueIDBDatabaseConnection>&&);
138 bool hasAnyOpenConnections() const;
139 bool allConnectionsAreClosedOrClosing() const;
140
141 void startVersionChangeTransaction();
142 void maybeNotifyConnectionsOfVersionChange();
143 void notifyCurrentRequestConnectionClosedOrFiredVersionChangeEvent(uint64_t connectionIdentifier);
144 bool isVersionChangeInProgress();
145
146 void activateTransactionInBackingStore(UniqueIDBDatabaseTransaction&);
147 void transactionCompleted(RefPtr<UniqueIDBDatabaseTransaction>&&);
148
149 void connectionClosedFromServer(UniqueIDBDatabaseConnection&);
150
151 void scheduleShutdownForClose();
152
153 void createObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, const IDBObjectStoreInfo&, ErrorCallback);
154 void renameObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback);
155 void createIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, const IDBIndexInfo&, ErrorCallback);
156 void renameIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback);
157 void putOrAddAfterQuotaCheck(uint64_t taskSize, const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback);
158 void deleteRecordAfterQuotaCheck(const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
159
160 void deleteObjectStoreAfterQuotaCheck(UniqueIDBDatabaseTransaction&, const String& objectStoreName, ErrorCallback);
161 void clearObjectStoreAfetQuotaCheck(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, ErrorCallback);
162 void deleteIndexAfterQuotaCheck(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String&, ErrorCallback);
163 void getRecordAfterQuotaCheck(const IDBRequestData&, const IDBGetRecordData&, GetResultCallback);
164 void getAllRecordsAfterQuotaCheck(const IDBRequestData&, const IDBGetAllRecordsData&, GetAllResultsCallback);
165 void getCountAfterQuotaCheck(const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
166 void openCursorAfterQuotaCheck(const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
167 void iterateCursorAfterQuotaCheck(const IDBRequestData&, const IDBIterateCursorData&, GetResultCallback);
168 void commitTransactionAfterQuotaCheck(UniqueIDBDatabaseTransaction&, ErrorCallback);
169
170 // Database thread operations
171 void deleteBackingStore(const IDBDatabaseIdentifier&);
172 void openBackingStore(const IDBDatabaseIdentifier&);
173 void performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier);
174 void performAbortTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier);
175 void beginTransactionInBackingStore(const IDBTransactionInfo&);
176 void performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo&);
177 void performDeleteObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier);
178 void performRenameObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const String& newName);
179 void performClearObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier);
180 void performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo&);
181 void performDeleteIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier);
182 void performRenameIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName);
183 void performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode);
184 void performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, IDBGetRecordDataType);
185 void performGetAllRecords(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData&);
186 void performGetIndexRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&);
187 void performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&);
188 void performDeleteRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&);
189 void performOpenCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo&);
190 void performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBIterateCursorData&);
191 void performPrefetchCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier);
192
193 void performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo&);
194 void performUnconditionalDeleteBackingStore();
195 void shutdownForClose();
196
197 // Main thread callbacks
198 void didDeleteBackingStore(uint64_t deletedVersion);
199 void didOpenBackingStore(const IDBDatabaseInfo&, const IDBError&);
200 void didPerformCreateObjectStore(uint64_t callbackIdentifier, const IDBError&, const IDBObjectStoreInfo&);
201 void didPerformDeleteObjectStore(uint64_t callbackIdentifier, const IDBError&, uint64_t objectStoreIdentifier);
202 void didPerformRenameObjectStore(uint64_t callbackIdentifier, const IDBError&, uint64_t objectStoreIdentifier, const String& newName);
203 void didPerformClearObjectStore(uint64_t callbackIdentifier, const IDBError&);
204 void didPerformCreateIndex(uint64_t callbackIdentifier, const IDBError&, const IDBIndexInfo&);
205 void didPerformDeleteIndex(uint64_t callbackIdentifier, const IDBError&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier);
206 void didPerformRenameIndex(uint64_t callbackIdentifier, const IDBError&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName);
207 void didPerformPutOrAdd(uint64_t callbackIdentifier, const IDBError&, const IDBKeyData&);
208 void didPerformGetRecord(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
209 void didPerformGetAllRecords(uint64_t callbackIdentifier, const IDBError&, const IDBGetAllResult&);
210 void didPerformGetCount(uint64_t callbackIdentifier, const IDBError&, uint64_t);
211 void didPerformDeleteRecord(uint64_t callbackIdentifier, const IDBError&);
212 void didPerformOpenCursor(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
213 void didPerformIterateCursor(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
214 void didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError&, const IDBResourceIdentifier& transactionIdentifier);
215 void didPerformAbortTransaction(uint64_t callbackIdentifier, const IDBError&, const IDBResourceIdentifier& transactionIdentifier);
216 void didPerformActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBError&);
217 void didPerformUnconditionalDeleteBackingStore();
218 void didShutdownForClose();
219
220 uint64_t storeCallbackOrFireError(ErrorCallback&&, uint64_t taskSize = 0);
221 uint64_t storeCallbackOrFireError(KeyDataCallback&&, uint64_t taskSize = 0);
222 uint64_t storeCallbackOrFireError(GetAllResultsCallback&&);
223 uint64_t storeCallbackOrFireError(GetResultCallback&&);
224 uint64_t storeCallbackOrFireError(CountCallback&&);
225
226 void performErrorCallback(uint64_t callbackIdentifier, const IDBError&);
227 void performKeyDataCallback(uint64_t callbackIdentifier, const IDBError&, const IDBKeyData&);
228 void performGetResultCallback(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
229 void performGetAllResultsCallback(uint64_t callbackIdentifier, const IDBError&, const IDBGetAllResult&);
230 void performCountCallback(uint64_t callbackIdentifier, const IDBError&, uint64_t);
231
232 void forgetErrorCallback(uint64_t callbackIdentifier);
233
234 bool hasAnyPendingCallbacks() const;
235 bool isCurrentlyInUse() const;
236 bool hasUnfinishedTransactions() const;
237
238 void invokeOperationAndTransactionTimer();
239 void operationAndTransactionTimerFired();
240 RefPtr<UniqueIDBDatabaseTransaction> takeNextRunnableTransaction(bool& hadDeferredTransactions);
241
242 bool prepareToFinishTransaction(UniqueIDBDatabaseTransaction&, UniqueIDBDatabaseTransaction::State);
243 void abortTransactionOnMainThread(UniqueIDBDatabaseTransaction&);
244 void commitTransactionOnMainThread(UniqueIDBDatabaseTransaction&);
245
246 void clearStalePendingOpenDBRequests();
247
248 void postDatabaseTask(CrossThreadTask&&);
249 void postDatabaseTaskReply(CrossThreadTask&&);
250 void executeNextDatabaseTask();
251 void executeNextDatabaseTaskReply();
252
253 void maybeFinishHardClose();
254 bool isDoneWithHardClose();
255
256 void requestSpace(uint64_t taskSize, const char* errorMessage, CompletionHandler<void(Optional<IDBError>&&)>&&);
257 void waitForRequestSpaceCompletion(CompletionHandler<void(Optional<IDBError>&&)>&&);
258 void updateSpaceUsedIfNeeded(uint64_t callbackIdentifier);
259
260 Ref<IDBServer> m_server;
261 IDBDatabaseIdentifier m_identifier;
262
263 ListHashSet<RefPtr<ServerOpenDBRequest>> m_pendingOpenDBRequests;
264 RefPtr<ServerOpenDBRequest> m_currentOpenDBRequest;
265
266 ListHashSet<RefPtr<UniqueIDBDatabaseConnection>> m_openDatabaseConnections;
267 HashSet<RefPtr<UniqueIDBDatabaseConnection>> m_clientClosePendingDatabaseConnections;
268 HashSet<RefPtr<UniqueIDBDatabaseConnection>> m_serverClosePendingDatabaseConnections;
269
270 RefPtr<UniqueIDBDatabaseConnection> m_versionChangeDatabaseConnection;
271 RefPtr<UniqueIDBDatabaseTransaction> m_versionChangeTransaction;
272
273 bool m_isOpeningBackingStore { false };
274 IDBError m_backingStoreOpenError;
275 std::unique_ptr<IDBBackingStore> m_backingStore;
276 std::unique_ptr<IDBDatabaseInfo> m_databaseInfo;
277 std::unique_ptr<IDBDatabaseInfo> m_mostRecentDeletedDatabaseInfo;
278
279 bool m_backingStoreSupportsSimultaneousTransactions { false };
280 bool m_backingStoreIsEphemeral { false };
281
282 HashMap<uint64_t, ErrorCallback> m_errorCallbacks;
283 HashMap<uint64_t, KeyDataCallback> m_keyDataCallbacks;
284 HashMap<uint64_t, GetResultCallback> m_getResultCallbacks;
285 HashMap<uint64_t, GetAllResultsCallback> m_getAllResultsCallbacks;
286 HashMap<uint64_t, CountCallback> m_countCallbacks;
287 Deque<uint64_t> m_callbackQueue;
288
289 Timer m_operationAndTransactionTimer;
290
291 Deque<RefPtr<UniqueIDBDatabaseTransaction>> m_pendingTransactions;
292 HashMap<IDBResourceIdentifier, RefPtr<UniqueIDBDatabaseTransaction>> m_inProgressTransactions;
293 HashMap<IDBResourceIdentifier, RefPtr<UniqueIDBDatabaseTransaction>> m_finishingTransactions;
294
295 // The keys into these sets are the object store ID.
296 // These sets help to decide which transactions can be started and which must be deferred.
297 HashCountedSet<uint64_t> m_objectStoreTransactionCounts;
298 HashSet<uint64_t> m_objectStoreWriteTransactions;
299
300 bool m_deleteBackingStoreInProgress { false };
301
302 CrossThreadQueue<CrossThreadTask> m_databaseQueue;
303 CrossThreadQueue<CrossThreadTask> m_databaseReplyQueue;
304
305 bool m_hardClosedForUserDelete { false };
306 bool m_owningPointerReleaseScheduled { false };
307 std::unique_ptr<UniqueIDBDatabase> m_owningPointerForClose;
308
309 HashSet<IDBResourceIdentifier> m_cursorPrefetches;
310
311 HashMap<uint64_t, uint64_t> m_pendingSpaceIncreasingTasks;
312 uint64_t m_databasesSizeForOrigin { 0 };
313};
314
315} // namespace IDBServer
316} // namespace WebCore
317
318#endif // ENABLE(INDEXED_DATABASE)
319