1/*
2 * Copyright (C) 2013 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#ifndef UniqueIDBDatabase_h
27#define UniqueIDBDatabase_h
28
29#if ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
30
31#include "IDBIdentifier.h"
32#include "UniqueIDBDatabaseIdentifier.h"
33#include <WebCore/IDBDatabaseBackend.h>
34#include <WebCore/IndexedDB.h>
35#include <functional>
36#include <wtf/Deque.h>
37#include <wtf/HashSet.h>
38#include <wtf/PassRefPtr.h>
39#include <wtf/RefCounted.h>
40#include <wtf/text/WTFString.h>
41
42namespace WebCore {
43class SharedBuffer;
44
45struct IDBDatabaseMetadata;
46struct IDBKeyData;
47}
48
49namespace WebKit {
50
51class AsyncRequest;
52class AsyncTask;
53class DatabaseProcessIDBConnection;
54class UniqueIDBDatabaseBackingStore;
55
56struct SecurityOriginData;
57
58enum class UniqueIDBDatabaseShutdownType {
59    NormalShutdown,
60    DeleteShutdown
61};
62
63class UniqueIDBDatabase : public ThreadSafeRefCounted<UniqueIDBDatabase> {
64public:
65    static PassRefPtr<UniqueIDBDatabase> create(const UniqueIDBDatabaseIdentifier& identifier)
66    {
67        return adoptRef(new UniqueIDBDatabase(identifier));
68    }
69
70    ~UniqueIDBDatabase();
71
72    static String calculateAbsoluteDatabaseFilename(const String& absoluteDatabaseDirectory);
73
74    const UniqueIDBDatabaseIdentifier& identifier() const { return m_identifier; }
75
76    void registerConnection(DatabaseProcessIDBConnection&);
77    void unregisterConnection(DatabaseProcessIDBConnection&);
78
79    void deleteDatabase(std::function<void(bool)> successCallback);
80
81    void getOrEstablishIDBDatabaseMetadata(std::function<void(bool, const WebCore::IDBDatabaseMetadata&)> completionCallback);
82
83    void openTransaction(const IDBIdentifier& transactionIdentifier, const Vector<int64_t>& objectStoreIDs, WebCore::IndexedDB::TransactionMode, std::function<void(bool)> successCallback);
84    void beginTransaction(const IDBIdentifier& transactionIdentifier, std::function<void(bool)> successCallback);
85    void commitTransaction(const IDBIdentifier& transactionIdentifier, std::function<void(bool)> successCallback);
86    void resetTransaction(const IDBIdentifier& transactionIdentifier, std::function<void(bool)> successCallback);
87    void rollbackTransaction(const IDBIdentifier& transactionIdentifier, std::function<void(bool)> successCallback);
88
89    void changeDatabaseVersion(const IDBIdentifier& transactionIdentifier, uint64_t newVersion, std::function<void(bool)> successCallback);
90    void createObjectStore(const IDBIdentifier& transactionIdentifier, const WebCore::IDBObjectStoreMetadata&, std::function<void(bool)> successCallback);
91    void deleteObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, std::function<void(bool)> successCallback);
92    void clearObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, std::function<void(bool)> successCallback);
93    void createIndex(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBIndexMetadata&, std::function<void(bool)> successCallback);
94    void deleteIndex(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, std::function<void(bool)> successCallback);
95
96    void putRecord(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBKeyData&, const IPC::DataReference& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<WebCore::IDBKeyData>>& indexKeys, std::function<void(const WebCore::IDBKeyData&, uint32_t, const String&)> callback);
97    void getRecord(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyRangeData&, WebCore::IndexedDB::CursorType, std::function<void(const WebCore::IDBGetResult&, uint32_t, const String&)> callback);
98
99    void openCursor(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, WebCore::IndexedDB::CursorDirection, WebCore::IndexedDB::CursorType, WebCore::IDBDatabaseBackend::TaskType, const WebCore::IDBKeyRangeData&, std::function<void(int64_t, const WebCore::IDBKeyData&, const WebCore::IDBKeyData&, PassRefPtr<WebCore::SharedBuffer>, uint32_t, const String&)> callback);
100    void cursorAdvance(const IDBIdentifier& cursorIdentifier, uint64_t count, std::function<void(const WebCore::IDBKeyData&, const WebCore::IDBKeyData&, PassRefPtr<WebCore::SharedBuffer>, uint32_t, const String&)> callback);
101    void cursorIterate(const IDBIdentifier& cursorIdentifier, const WebCore::IDBKeyData&, std::function<void(const WebCore::IDBKeyData&, const WebCore::IDBKeyData&, PassRefPtr<WebCore::SharedBuffer>, uint32_t, const String&)> callback);
102
103    void count(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyRangeData&, std::function<void(int64_t, uint32_t, const String&)> callback);
104    void deleteRange(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBKeyRangeData&, std::function<void(uint32_t, const String&)> callback);
105
106private:
107    UniqueIDBDatabase(const UniqueIDBDatabaseIdentifier&);
108
109    UniqueIDBDatabaseIdentifier m_identifier;
110
111    bool m_inMemory;
112    String m_databaseRelativeDirectory;
113
114    HashSet<RefPtr<DatabaseProcessIDBConnection>> m_connections;
115    HashMap<uint64_t, RefPtr<AsyncRequest>> m_databaseRequests;
116
117    String absoluteDatabaseDirectory() const;
118
119    enum class DatabaseTaskType {
120        Normal,
121        Shutdown
122    };
123    void postDatabaseTask(std::unique_ptr<AsyncTask>, DatabaseTaskType = DatabaseTaskType::Normal);
124
125    void shutdown(UniqueIDBDatabaseShutdownType);
126
127    // Method that attempts to make legal filenames from all legal database names
128    String filenameForDatabaseName() const;
129
130    // Returns a string that is appropriate for use as a unique filename
131    String databaseFilenameIdentifier(const SecurityOriginData&) const;
132
133    // Returns true if this origin can use the same databases as the given origin.
134    bool canShareDatabases(const SecurityOriginData&, const SecurityOriginData&) const;
135
136    void postTransactionOperation(const IDBIdentifier& transactionIdentifier, std::unique_ptr<AsyncTask>, std::function<void(bool)> successCallback);
137
138    // To be called from the database workqueue thread only
139    void performNextDatabaseTask();
140    void postMainThreadTask(std::unique_ptr<AsyncTask>, DatabaseTaskType = DatabaseTaskType::Normal);
141    void openBackingStoreAndReadMetadata(const UniqueIDBDatabaseIdentifier&, const String& databaseDirectory);
142    void openBackingStoreTransaction(const IDBIdentifier& transactionIdentifier, const Vector<int64_t>& objectStoreIDs, WebCore::IndexedDB::TransactionMode);
143    void beginBackingStoreTransaction(const IDBIdentifier&);
144    void commitBackingStoreTransaction(const IDBIdentifier&);
145    void resetBackingStoreTransaction(const IDBIdentifier&);
146    void rollbackBackingStoreTransaction(const IDBIdentifier&);
147
148    void changeDatabaseVersionInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, uint64_t newVersion);
149    void createObjectStoreInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, const WebCore::IDBObjectStoreMetadata&);
150    void deleteObjectStoreInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID);
151    void clearObjectStoreInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID);
152
153    void createIndexInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBIndexMetadata&);
154    void deleteIndexInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID);
155
156    void putRecordInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, const WebCore::IDBObjectStoreMetadata&, const WebCore::IDBKeyData&, const Vector<uint8_t>& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<WebCore::IDBKeyData>>& indexKeys);
157    void getRecordFromBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, const WebCore::IDBObjectStoreMetadata&, int64_t indexID, const WebCore::IDBKeyRangeData&, WebCore::IndexedDB::CursorType);
158    void openCursorInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, WebCore::IndexedDB::CursorDirection, WebCore::IndexedDB::CursorType, WebCore::IDBDatabaseBackend::TaskType, const WebCore::IDBKeyRangeData&);
159    void advanceCursorInBackingStore(uint64_t requestID, const IDBIdentifier& cursorIdentifier, uint64_t count);
160    void iterateCursorInBackingStore(uint64_t requestID, const IDBIdentifier& cursorIdentifier, const WebCore::IDBKeyData&);
161    void countInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyRangeData&);
162    void deleteRangeInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBKeyRangeData&);
163
164    void shutdownBackingStore(UniqueIDBDatabaseShutdownType, const String& databaseDirectory);
165
166    // Callbacks from the database workqueue thread, to be performed on the main thread only
167    void performNextMainThreadTask();
168    bool performNextMainThreadTaskWithoutAdoptRef();
169    void didOpenBackingStoreAndReadMetadata(const WebCore::IDBDatabaseMetadata&, bool success);
170    void didCompleteTransactionOperation(const IDBIdentifier& transactionIdentifier, bool success);
171    void didChangeDatabaseVersion(uint64_t requestID, bool success);
172    void didCreateObjectStore(uint64_t requestID, bool success);
173    void didDeleteObjectStore(uint64_t requestID, bool success);
174    void didClearObjectStore(uint64_t requestID, bool success);
175    void didCreateIndex(uint64_t requestID, bool success);
176    void didDeleteIndex(uint64_t requestID, bool success);
177    void didPutRecordInBackingStore(uint64_t requestID, const WebCore::IDBKeyData&, uint32_t errorCode, const String& errorMessage);
178    void didGetRecordFromBackingStore(uint64_t requestID, const WebCore::IDBGetResult&, uint32_t errorCode, const String& errorMessage);
179    void didOpenCursorInBackingStore(uint64_t requestID, int64_t cursorID, const WebCore::IDBKeyData&, const WebCore::IDBKeyData&, const Vector<uint8_t>&, uint32_t errorCode, const String& errorMessage);
180    void didAdvanceCursorInBackingStore(uint64_t requestID, const WebCore::IDBKeyData&, const WebCore::IDBKeyData&, const Vector<uint8_t>&, uint32_t errorCode, const String& errorMessage);
181    void didIterateCursorInBackingStore(uint64_t requestID, const WebCore::IDBKeyData&, const WebCore::IDBKeyData&, const Vector<uint8_t>&, uint32_t errorCode, const String& errorMessage);
182    void didCountInBackingStore(uint64_t requestID, int64_t count, uint32_t errorCode, const String& errorMessage);
183    void didDeleteRangeInBackingStore(uint64_t requestID, uint32_t errorCode, const String& errorMessage);
184
185    void didShutdownBackingStore(UniqueIDBDatabaseShutdownType);
186    void didCompleteBoolRequest(uint64_t requestID, bool success);
187
188    void didEstablishTransaction(const IDBIdentifier& transactionIdentifier, bool success);
189    void didResetTransaction(const IDBIdentifier& transactionIdentifier, bool success);
190    void resetAllTransactions(const DatabaseProcessIDBConnection&);
191    void finalizeRollback(const IDBIdentifier& transactionId);
192
193    bool m_acceptingNewRequests;
194
195    HashMap<const DatabaseProcessIDBConnection*, HashSet<IDBIdentifier>> m_establishedTransactions;
196    Deque<RefPtr<AsyncRequest>> m_pendingMetadataRequests;
197    HashMap<IDBIdentifier, RefPtr<AsyncRequest>> m_pendingTransactionRequests;
198    HashSet<IDBIdentifier> m_pendingTransactionRollbacks;
199    HashMap<uint64_t, RefPtr<AsyncRequest>> m_pendingDatabaseTasks;
200    RefPtr<AsyncRequest> m_pendingShutdownTask;
201
202    std::unique_ptr<WebCore::IDBDatabaseMetadata> m_metadata;
203    bool m_didGetMetadataFromBackingStore;
204
205    RefPtr<UniqueIDBDatabaseBackingStore> m_backingStore;
206
207    Deque<std::unique_ptr<AsyncTask>> m_databaseTasks;
208    Mutex m_databaseTaskMutex;
209
210    Deque<std::unique_ptr<AsyncTask>> m_mainThreadTasks;
211    Mutex m_mainThreadTaskMutex;
212};
213
214} // namespace WebKit
215
216#endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
217#endif // UniqueIDBDatabase_h
218