IndexedDB 2.0: "close pending flag" and firing blocked events all need fixing.
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / UniqueIDBDatabaseConnection.cpp
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 #include "config.h"
27 #include "UniqueIDBDatabaseConnection.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBConnectionToClient.h"
32 #include "IDBServer.h"
33 #include "IDBTransactionInfo.h"
34 #include "Logging.h"
35 #include "ServerOpenDBRequest.h"
36 #include "UniqueIDBDatabase.h"
37
38 namespace WebCore {
39 namespace IDBServer {
40
41 static uint64_t nextDatabaseConnectionIdentifier()
42 {
43     static uint64_t nextIdentifier = 0;
44     return ++nextIdentifier;
45 }
46
47 Ref<UniqueIDBDatabaseConnection> UniqueIDBDatabaseConnection::create(UniqueIDBDatabase& database, ServerOpenDBRequest& request)
48 {
49     return adoptRef(*new UniqueIDBDatabaseConnection(database, request));
50 }
51
52 UniqueIDBDatabaseConnection::UniqueIDBDatabaseConnection(UniqueIDBDatabase& database, ServerOpenDBRequest& request)
53     : m_identifier(nextDatabaseConnectionIdentifier())
54     , m_database(database)
55     , m_connectionToClient(request.connection())
56     , m_openRequestIdentifier(request.requestData().requestIdentifier())
57 {
58     m_database.server().registerDatabaseConnection(*this);
59     m_connectionToClient.registerDatabaseConnection(*this);
60 }
61
62 UniqueIDBDatabaseConnection::~UniqueIDBDatabaseConnection()
63 {
64     m_database.server().unregisterDatabaseConnection(*this);
65     m_connectionToClient.unregisterDatabaseConnection(*this);
66 }
67
68 bool UniqueIDBDatabaseConnection::hasNonFinishedTransactions() const
69 {
70     return !m_transactionMap.isEmpty();
71 }
72
73 void UniqueIDBDatabaseConnection::abortTransactionWithoutCallback(UniqueIDBDatabaseTransaction& transaction)
74 {
75     ASSERT(m_transactionMap.contains(transaction.info().identifier()));
76
77     const auto& transactionIdentifier = transaction.info().identifier();
78     RefPtr<UniqueIDBDatabaseConnection> protectedThis(this);
79
80     m_database.abortTransaction(transaction, [this, protectedThis, transactionIdentifier](const IDBError&) {
81         ASSERT(m_transactionMap.contains(transactionIdentifier));
82         m_transactionMap.remove(transactionIdentifier);
83     });
84 }
85
86 void UniqueIDBDatabaseConnection::connectionPendingCloseFromClient()
87 {
88     LOG(IndexedDB, "UniqueIDBDatabaseConnection::connectionPendingCloseFromClient - %s - %" PRIu64, m_openRequestIdentifier.loggingString().utf8().data(), m_identifier);
89
90     m_closePending = true;
91 }
92
93 void UniqueIDBDatabaseConnection::connectionClosedFromClient()
94 {
95     LOG(IndexedDB, "UniqueIDBDatabaseConnection::connectionClosedFromClient - %s - %" PRIu64, m_openRequestIdentifier.loggingString().utf8().data(), m_identifier);
96
97     m_database.connectionClosedFromClient(*this);
98 }
99
100 void UniqueIDBDatabaseConnection::confirmDidCloseFromServer()
101 {
102     LOG(IndexedDB, "UniqueIDBDatabaseConnection::confirmDidCloseFromServer - %s - %" PRIu64, m_openRequestIdentifier.loggingString().utf8().data(), m_identifier);
103
104     m_database.confirmDidCloseFromServer(*this);
105 }
106
107 void UniqueIDBDatabaseConnection::didFireVersionChangeEvent(const IDBResourceIdentifier& requestIdentifier)
108 {
109     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didFireVersionChangeEvent - %s - %" PRIu64, m_openRequestIdentifier.loggingString().utf8().data(), m_identifier);
110
111     m_database.didFireVersionChangeEvent(*this, requestIdentifier);
112 }
113
114 void UniqueIDBDatabaseConnection::didFinishHandlingVersionChange(const IDBResourceIdentifier& transactionIdentifier)
115 {
116     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didFinishHandlingVersionChange - %s - %" PRIu64, transactionIdentifier.loggingString().utf8().data(), m_identifier);
117
118     m_database.didFinishHandlingVersionChange(*this, transactionIdentifier);
119 }
120
121 void UniqueIDBDatabaseConnection::fireVersionChangeEvent(const IDBResourceIdentifier& requestIdentifier, uint64_t requestedVersion)
122 {
123     ASSERT(!m_closePending);
124     m_connectionToClient.fireVersionChangeEvent(*this, requestIdentifier, requestedVersion);
125 }
126
127 UniqueIDBDatabaseTransaction& UniqueIDBDatabaseConnection::createVersionChangeTransaction(uint64_t newVersion)
128 {
129     LOG(IndexedDB, "UniqueIDBDatabaseConnection::createVersionChangeTransaction - %s - %" PRIu64, m_openRequestIdentifier.loggingString().utf8().data(), m_identifier);
130     ASSERT(!m_closePending);
131
132     IDBTransactionInfo info = IDBTransactionInfo::versionChange(m_connectionToClient, m_database.info(), newVersion);
133
134     Ref<UniqueIDBDatabaseTransaction> transaction = UniqueIDBDatabaseTransaction::create(*this, info);
135     m_transactionMap.set(transaction->info().identifier(), &transaction.get());
136
137     return transaction.get();
138 }
139
140 void UniqueIDBDatabaseConnection::establishTransaction(const IDBTransactionInfo& info)
141 {
142     LOG(IndexedDB, "UniqueIDBDatabaseConnection::establishTransaction - %s - %" PRIu64, m_openRequestIdentifier.loggingString().utf8().data(), m_identifier);
143
144     ASSERT(info.mode() != IDBTransactionMode::Versionchange);
145
146     // No transactions should ever come from the client after the client has already told us
147     // the connection is closing.
148     ASSERT(!m_closePending);
149
150     Ref<UniqueIDBDatabaseTransaction> transaction = UniqueIDBDatabaseTransaction::create(*this, info);
151     m_transactionMap.set(transaction->info().identifier(), &transaction.get());
152     m_database.enqueueTransaction(WTFMove(transaction));
153 }
154
155 void UniqueIDBDatabaseConnection::didAbortTransaction(UniqueIDBDatabaseTransaction& transaction, const IDBError& error)
156 {
157     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didAbortTransaction - %s - %" PRIu64, m_openRequestIdentifier.loggingString().utf8().data(), m_identifier);
158
159     auto transactionIdentifier = transaction.info().identifier();
160     auto takenTransaction = m_transactionMap.take(transactionIdentifier);
161
162     ASSERT(takenTransaction || m_database.hardClosedForUserDelete());
163     if (takenTransaction)
164         m_connectionToClient.didAbortTransaction(transactionIdentifier, error);
165 }
166
167 void UniqueIDBDatabaseConnection::didCommitTransaction(UniqueIDBDatabaseTransaction& transaction, const IDBError& error)
168 {
169     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didCommitTransaction - %s - %" PRIu64, m_openRequestIdentifier.loggingString().utf8().data(), m_identifier);
170
171     auto transactionIdentifier = transaction.info().identifier();
172
173     ASSERT(m_transactionMap.contains(transactionIdentifier));
174     m_transactionMap.remove(transactionIdentifier);
175
176     m_connectionToClient.didCommitTransaction(transactionIdentifier, error);
177 }
178
179 void UniqueIDBDatabaseConnection::didCreateObjectStore(const IDBResultData& resultData)
180 {
181     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didCreateObjectStore");
182
183     m_connectionToClient.didCreateObjectStore(resultData);
184 }
185
186 void UniqueIDBDatabaseConnection::didDeleteObjectStore(const IDBResultData& resultData)
187 {
188     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didDeleteObjectStore");
189
190     m_connectionToClient.didDeleteObjectStore(resultData);
191 }
192
193 void UniqueIDBDatabaseConnection::didRenameObjectStore(const IDBResultData& resultData)
194 {
195     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didRenameObjectStore");
196
197     m_connectionToClient.didRenameObjectStore(resultData);
198 }
199
200 void UniqueIDBDatabaseConnection::didClearObjectStore(const IDBResultData& resultData)
201 {
202     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didClearObjectStore");
203
204     m_connectionToClient.didClearObjectStore(resultData);
205 }
206
207 void UniqueIDBDatabaseConnection::didCreateIndex(const IDBResultData& resultData)
208 {
209     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didCreateIndex");
210
211     m_connectionToClient.didCreateIndex(resultData);
212 }
213
214 void UniqueIDBDatabaseConnection::didDeleteIndex(const IDBResultData& resultData)
215 {
216     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didDeleteIndex");
217
218     m_connectionToClient.didDeleteIndex(resultData);
219 }
220
221 void UniqueIDBDatabaseConnection::didRenameIndex(const IDBResultData& resultData)
222 {
223     LOG(IndexedDB, "UniqueIDBDatabaseConnection::didRenameIndex");
224
225     m_connectionToClient.didRenameIndex(resultData);
226 }
227
228 bool UniqueIDBDatabaseConnection::connectionIsClosing() const
229 {
230     return m_closePending;
231 }
232
233 } // namespace IDBServer
234 } // namespace WebCore
235
236 #endif // ENABLE(INDEXED_DATABASE)