Modern IDB: Support IDBDatabase.close().
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / client / IDBDatabaseImpl.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 "IDBDatabaseImpl.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBConnectionToServer.h"
32 #include "IDBOpenDBRequestImpl.h"
33 #include "IDBResultData.h"
34 #include "IDBTransactionImpl.h"
35 #include "Logging.h"
36
37 namespace WebCore {
38 namespace IDBClient {
39
40 Ref<IDBDatabase> IDBDatabase::create(ScriptExecutionContext& context, IDBConnectionToServer& connection, const IDBResultData& resultData)
41 {
42     return adoptRef(*new IDBDatabase(context, connection, resultData));
43 }
44
45 IDBDatabase::IDBDatabase(ScriptExecutionContext& context, IDBConnectionToServer& connection, const IDBResultData& resultData)
46     : WebCore::IDBDatabase(&context)
47     , m_serverConnection(connection)
48     , m_info(resultData.databaseInfo())
49     , m_databaseConnectionIdentifier(resultData.databaseConnectionIdentifier())
50 {
51     suspendIfNeeded();
52     relaxAdoptionRequirement();
53     m_serverConnection->registerDatabaseConnection(*this);
54 }
55
56 IDBDatabase::~IDBDatabase()
57 {
58     m_serverConnection->unregisterDatabaseConnection(*this);
59 }
60
61 const String IDBDatabase::name() const
62 {
63     return m_info.name();
64 }
65
66 uint64_t IDBDatabase::version() const
67 {
68     return m_info.version();
69 }
70
71 RefPtr<DOMStringList> IDBDatabase::objectStoreNames() const
72 {
73     ASSERT_NOT_REACHED();
74     return nullptr;
75 }
76
77 RefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String&, const Dictionary&, ExceptionCode&)
78 {
79     ASSERT_NOT_REACHED();
80     return nullptr;
81 }
82
83 RefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String&, const IDBKeyPath&, bool, ExceptionCode&)
84 {
85     ASSERT_NOT_REACHED();
86     return nullptr;
87 }
88
89 RefPtr<WebCore::IDBTransaction> IDBDatabase::transaction(ScriptExecutionContext*, const Vector<String>&, const String&, ExceptionCode&)
90 {
91     ASSERT_NOT_REACHED();
92     return nullptr;
93 }
94
95 RefPtr<WebCore::IDBTransaction> IDBDatabase::transaction(ScriptExecutionContext*, const String&, const String&, ExceptionCode&)
96 {
97     ASSERT_NOT_REACHED();
98     return nullptr;
99 }
100
101 void IDBDatabase::deleteObjectStore(const String&, ExceptionCode&)
102 {
103     ASSERT_NOT_REACHED();
104 }
105
106 void IDBDatabase::close()
107 {
108     m_closePending = true;
109     maybeCloseInServer();
110 }
111
112 void IDBDatabase::maybeCloseInServer()
113 {
114     if (m_closedInServer)
115         return;
116
117     // 3.3.9 Database closing steps
118     // Wait for all transactions created using this connection to complete.
119     // Once they are complete, this connection is closed.
120     if (!m_activeTransactions.isEmpty() || !m_committingTransactions.isEmpty())
121         return;
122
123     m_closedInServer = true;
124     m_serverConnection->databaseConnectionClosed(*this);
125 }
126
127 const char* IDBDatabase::activeDOMObjectName() const
128 {
129     return "IDBDatabase";
130 }
131
132 bool IDBDatabase::canSuspendForPageCache() const
133 {
134     // FIXME: This value will sometimes be false when database operations are actually in progress.
135     // Such database operations do not yet exist.
136     return true;
137 }
138
139 Ref<IDBTransaction> IDBDatabase::startVersionChangeTransaction(const IDBTransactionInfo& info)
140 {
141     LOG(IndexedDB, "IDBDatabase::startVersionChangeTransaction");
142
143     ASSERT(!m_versionChangeTransaction);
144     ASSERT(info.mode() == IndexedDB::TransactionMode::VersionChange);
145
146     Ref<IDBTransaction> transaction = IDBTransaction::create(*this, info);
147     m_versionChangeTransaction = &transaction.get();
148
149     m_activeTransactions.set(transaction->info().identifier(), &transaction.get());
150
151     return WTF::move(transaction);
152 }
153
154 void IDBDatabase::commitTransaction(IDBTransaction& transaction)
155 {
156     LOG(IndexedDB, "IDBDatabase::commitTransaction");
157
158     auto refTransaction = m_activeTransactions.take(transaction.info().identifier());
159     ASSERT(refTransaction);
160     m_committingTransactions.set(transaction.info().identifier(), WTF::move(refTransaction));
161
162     m_serverConnection->commitTransaction(transaction);
163 }
164
165 void IDBDatabase::didCommitTransaction(IDBTransaction& transaction)
166 {
167     LOG(IndexedDB, "IDBDatabase::didCommitTransaction");
168
169     if (m_versionChangeTransaction == &transaction)
170         m_info.setVersion(transaction.info().newVersion());
171
172     didCommitOrAbortTransaction(transaction);
173 }
174
175 void IDBDatabase::didAbortTransaction(IDBTransaction& transaction)
176 {
177     LOG(IndexedDB, "IDBDatabase::didAbortTransaction");
178     didCommitOrAbortTransaction(transaction);
179 }
180
181 void IDBDatabase::didCommitOrAbortTransaction(IDBTransaction& transaction)
182 {
183     LOG(IndexedDB, "IDBDatabase::didCommitOrAbortTransaction");
184
185     if (m_versionChangeTransaction == &transaction)
186         m_versionChangeTransaction = nullptr;
187     
188     ASSERT(m_activeTransactions.contains(transaction.info().identifier()) || m_committingTransactions.contains(transaction.info().identifier()));
189
190     m_activeTransactions.remove(transaction.info().identifier());
191     m_committingTransactions.remove(transaction.info().identifier());
192 }
193
194 } // namespace IDBClient
195 } // namespace WebCore
196
197 #endif // ENABLE(INDEXED_DATABASE)