Unreviewed test gardening.
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / legacy / IDBTransactionBackendOperations.cpp
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 #include "config.h"
27 #include "IDBTransactionBackendOperations.h"
28
29 #include "IDBCursorBackend.h"
30 #include "IDBDatabaseCallbacks.h"
31 #include "IDBKeyRange.h"
32 #include "IDBRecordIdentifier.h"
33 #include "IDBServerConnection.h"
34 #include "Logging.h"
35 #include <wtf/text/CString.h>
36
37 #if ENABLE(INDEXED_DATABASE)
38
39 #define STANDARD_DATABASE_ERROR_CALLBACK std::function<void(PassRefPtr<IDBDatabaseError>)> operationCallback = \
40     [operation, completionCallback](PassRefPtr<IDBDatabaseError> error) { \
41         if (error) \
42             operation->m_transaction->abort(error); \
43         completionCallback(); \
44     };
45
46 namespace WebCore {
47
48 void CreateObjectStoreOperation::perform(std::function<void()> completionCallback)
49 {
50     LOG(StorageAPI, "CreateObjectStoreOperation");
51
52     RefPtr<CreateObjectStoreOperation> operation(this);
53     STANDARD_DATABASE_ERROR_CALLBACK;
54
55     m_transaction->database().serverConnection().createObjectStore(*m_transaction, *this, operationCallback);
56 }
57
58 void CreateIndexOperation::perform(std::function<void()> completionCallback)
59 {
60     LOG(StorageAPI, "CreateIndexOperation");
61
62     RefPtr<CreateIndexOperation> operation(this);
63     STANDARD_DATABASE_ERROR_CALLBACK;
64
65     m_transaction->database().serverConnection().createIndex(*m_transaction, *this, operationCallback);
66 }
67
68 void CreateIndexAbortOperation::perform()
69 {
70     LOG(StorageAPI, "CreateIndexAbortOperation");
71     m_transaction->database().removeIndex(m_objectStoreID, m_indexID);
72 }
73
74 void DeleteIndexOperation::perform(std::function<void()> completionCallback)
75 {
76     LOG(StorageAPI, "DeleteIndexOperation");
77
78     RefPtr<DeleteIndexOperation> operation(this);
79     STANDARD_DATABASE_ERROR_CALLBACK;
80
81     m_transaction->database().serverConnection().deleteIndex(*m_transaction, *this, operationCallback);
82 }
83
84 void DeleteIndexAbortOperation::perform()
85 {
86     LOG(StorageAPI, "DeleteIndexAbortOperation");
87     m_transaction->database().addIndex(m_objectStoreID, m_indexMetadata, IDBIndexMetadata::InvalidId);
88 }
89
90 void GetOperation::perform(std::function<void()> completionCallback)
91 {
92     LOG(StorageAPI, "GetOperation");
93
94     RefPtr<GetOperation> operation(this);
95     STANDARD_DATABASE_ERROR_CALLBACK;
96
97     m_transaction->database().serverConnection().get(*m_transaction, *this, [this, operation, operationCallback](const IDBGetResult& result, PassRefPtr<IDBDatabaseError> prpError) {
98         RefPtr<IDBDatabaseError> error = prpError;
99
100         if (error)
101             m_callbacks->onError(error);
102         else {
103             if (!result.valueBuffer().data()) {
104                 if (result.keyData().isNull())
105                     m_callbacks->onSuccess();
106                 else
107                     m_callbacks->onSuccess(result.keyData().maybeCreateIDBKey());
108             } else {
109                 auto valueBuffer = SharedBuffer::create(result.valueBuffer().data()->data(), result.valueBuffer().data()->size());
110                 if (!result.keyData().isNull())
111                     m_callbacks->onSuccess(valueBuffer, result.keyData().maybeCreateIDBKey(), result.keyPath());
112                 else
113                     m_callbacks->onSuccess(valueBuffer);
114             }
115         }
116
117         operationCallback(error.release());
118     });
119 }
120
121 void PutOperation::perform(std::function<void()> completionCallback)
122 {
123     LOG(StorageAPI, "PutOperation");
124     ASSERT(m_transaction->mode() != IndexedDB::TransactionMode::ReadOnly);
125     ASSERT(m_indexIDs.size() == m_indexKeys.size());
126
127     m_transaction->database().serverConnection().put(*m_transaction, *this, [this, completionCallback](PassRefPtr<IDBKey> key, PassRefPtr<IDBDatabaseError> prpError) {
128         RefPtr<IDBDatabaseError> error = prpError;
129         if (key) {
130             ASSERT(!error);
131             m_callbacks->onSuccess(key);
132         } else {
133             ASSERT(error);
134             m_callbacks->onError(error);
135         }
136         completionCallback();
137     });
138 }
139
140 void SetIndexesReadyOperation::perform(std::function<void()> completionCallback)
141 {
142     LOG(StorageAPI, "SetIndexesReadyOperation");
143
144     for (size_t i = 0; i < m_indexCount; ++i)
145         m_transaction->didCompletePreemptiveEvent();
146
147     callOnMainThread(completionCallback);
148 }
149
150 void OpenCursorOperation::perform(std::function<void()> completionCallback)
151 {
152     LOG(StorageAPI, "OpenCursorOperation");
153
154     RefPtr<OpenCursorOperation> operation(this);
155     auto callback = [this, operation, completionCallback](int64_t cursorID, PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> valueBuffer, PassRefPtr<IDBDatabaseError> error) {
156         if (error) {
157             m_callbacks->onError(error);
158         } else if (!key) {
159             // If there's no error but also no key, then the cursor had no records.
160             m_callbacks->onSuccess(static_cast<SharedBuffer*>(nullptr));
161         } else {
162             RefPtr<IDBCursorBackend> cursor = IDBCursorBackend::create(cursorID, m_cursorType, m_taskType, *m_transaction, m_objectStoreID);
163             cursor->updateCursorData(key.get(), primaryKey.get(), valueBuffer.get());
164             m_callbacks->onSuccess(cursor.release());
165         }
166
167         completionCallback();
168     };
169
170     m_transaction->database().serverConnection().openCursor(*m_transaction, *this, callback);
171 }
172
173 void CountOperation::perform(std::function<void()> completionCallback)
174 {
175     LOG(StorageAPI, "CountOperation");
176
177     RefPtr<CountOperation> operation(this);
178     auto callback = [this, operation, completionCallback](int64_t count, PassRefPtr<IDBDatabaseError>) {
179         // FIXME: The LevelDB port never had an error condition for the count operation.
180         // We probably need to support an error for the count operation, breaking the LevelDB port.
181         m_callbacks->onSuccess(count);
182
183         completionCallback();
184     };
185
186     m_transaction->database().serverConnection().count(*m_transaction, *this, callback);
187 }
188
189 void DeleteRangeOperation::perform(std::function<void()> completionCallback)
190 {
191     LOG(StorageAPI, "DeleteRangeOperation");
192
193     RefPtr<DeleteRangeOperation> operation(this);
194     auto callback = [this, operation, completionCallback](PassRefPtr<IDBDatabaseError> error) {
195         if (error)
196             m_callbacks->onError(error);
197         else
198             m_callbacks->onSuccess();
199
200         completionCallback();
201     };
202
203     m_transaction->database().serverConnection().deleteRange(*m_transaction, *this, callback);
204 }
205
206 void ClearObjectStoreOperation::perform(std::function<void()> completionCallback)
207 {
208     LOG(StorageAPI, "ClearObjectStoreOperation");
209
210     RefPtr<ClearObjectStoreOperation> operation(this);
211
212     auto clearCallback = [this, operation, completionCallback](PassRefPtr<IDBDatabaseError> prpError) {
213         RefPtr<IDBDatabaseError> error = prpError;
214
215         if (error) {
216             m_callbacks->onError(error);
217             m_transaction->abort(error.release());
218         } else
219             m_callbacks->onSuccess();
220
221         completionCallback();
222     };
223
224     m_transaction->database().serverConnection().clearObjectStore(*m_transaction, *this, clearCallback);
225 }
226
227 void DeleteObjectStoreOperation::perform(std::function<void()> completionCallback)
228 {
229     LOG(StorageAPI, "DeleteObjectStoreOperation");
230
231     RefPtr<DeleteObjectStoreOperation> operation(this);
232     STANDARD_DATABASE_ERROR_CALLBACK;
233
234     m_transaction->database().serverConnection().deleteObjectStore(*m_transaction, *this, operationCallback);
235 }
236
237 void IDBDatabaseBackend::VersionChangeOperation::perform(std::function<void()> completionCallback)
238 {
239     LOG(StorageAPI, "VersionChangeOperation");
240
241     uint64_t oldVersion = m_transaction->database().metadata().version;
242     if (oldVersion == IDBDatabaseMetadata::NoIntVersion)
243         oldVersion = 0;
244
245     RefPtr<IDBDatabaseBackend::VersionChangeOperation> operation(this);
246     ASSERT(static_cast<uint64_t>(m_version) > oldVersion);
247
248     std::function<void(PassRefPtr<IDBDatabaseError>)> operationCallback = [oldVersion, operation, this, completionCallback](PassRefPtr<IDBDatabaseError> prpError) {
249         RefPtr<IDBDatabaseError> error = prpError;
250         if (error) {
251             m_callbacks->onError(error);
252             m_transaction->abort(error);
253         } else {
254             ASSERT(!m_transaction->database().hasPendingSecondHalfOpen());
255             m_transaction->database().setCurrentVersion(m_version);
256             m_transaction->database().setPendingSecondHalfOpen(std::make_unique<IDBPendingOpenCall>(*m_callbacks, *m_databaseCallbacks, m_transaction->id(), m_version));
257             m_callbacks->onUpgradeNeeded(oldVersion, &m_transaction->database(), m_transaction->database().metadata());
258         }
259         completionCallback();
260     };
261
262     m_transaction->database().serverConnection().changeDatabaseVersion(*m_transaction, *this, operationCallback);
263 }
264
265 void CreateObjectStoreAbortOperation::perform()
266 {
267     LOG(StorageAPI, "CreateObjectStoreAbortOperation");
268     m_transaction->database().removeObjectStore(m_objectStoreID);
269 }
270
271 void DeleteObjectStoreAbortOperation::perform()
272 {
273     LOG(StorageAPI, "DeleteObjectStoreAbortOperation");
274     m_transaction->database().addObjectStore(m_objectStoreMetadata, IDBObjectStoreMetadata::InvalidId);
275 }
276
277 void IDBDatabaseBackend::VersionChangeAbortOperation::perform()
278 {
279     LOG(StorageAPI, "VersionChangeAbortOperation");
280     m_transaction->database().setCurrentVersion(m_previousIntVersion);
281 }
282
283 } // namespace WebCore
284
285 #endif // ENABLE(INDEXED_DATABASE)