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