IndexedDB: Move method precondition checks to front end objects
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / IDBIndex.cpp
1 /*
2  * Copyright (C) 2010 Google 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "IDBIndex.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBCursorBackendInterface.h"
32 #include "IDBDatabaseException.h"
33 #include "IDBIndexBackendInterface.h"
34 #include "IDBKey.h"
35 #include "IDBKeyRange.h"
36 #include "IDBObjectStore.h"
37 #include "IDBRequest.h"
38 #include "IDBTracing.h"
39 #include "IDBTransaction.h"
40
41 namespace WebCore {
42
43 static const unsigned short defaultDirection = IDBCursor::NEXT;
44
45 IDBIndex::IDBIndex(const IDBIndexMetadata& metadata, PassRefPtr<IDBIndexBackendInterface> backend, IDBObjectStore* objectStore, IDBTransaction* transaction)
46     : m_metadata(metadata)
47     , m_backend(backend)
48     , m_objectStore(objectStore)
49     , m_transaction(transaction)
50     , m_deleted(false)
51 {
52     ASSERT(m_backend);
53     ASSERT(m_objectStore);
54     ASSERT(m_transaction);
55 }
56
57 IDBIndex::~IDBIndex()
58 {
59 }
60
61 PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, const String& directionString, ExceptionCode& ec)
62 {
63     IDB_TRACE("IDBIndex::openCursor");
64     if (m_deleted) {
65         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
66         return 0;
67     }
68     if (!m_transaction->isActive()) {
69         ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
70         return 0;
71     }
72     unsigned short direction = IDBCursor::stringToDirection(directionString, ec);
73     if (ec)
74         return 0;
75
76     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
77     request->setCursorType(IDBCursorBackendInterface::IndexCursor);
78     m_backend->openCursor(keyRange, direction, request, m_transaction->backend(), ec);
79     if (ec) {
80         request->markEarlyDeath();
81         return 0;
82     }
83     return request;
84 }
85
86 PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, ExceptionCode& ec)
87 {
88     IDB_TRACE("IDBIndex::openCursor");
89     DEFINE_STATIC_LOCAL(String, consoleMessage, ("Numeric direction values are deprecated in IDBIndex.openCursor. Use \"next\", \"nextunique\", \"prev\", or \"prevunique\"."));
90     context->addConsoleMessage(JSMessageSource, LogMessageType, WarningMessageLevel, consoleMessage);
91     const String& directionString = IDBCursor::directionToString(direction, ec);
92     if (ec)
93         return 0;
94     return openCursor(context, keyRange, directionString, ec);
95 }
96
97 PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, const String& direction, ExceptionCode& ec)
98 {
99     IDB_TRACE("IDBIndex::openCursor");
100     RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(key, ec);
101     if (ec)
102         return 0;
103     return openCursor(context, keyRange.release(), ec);
104 }
105
106 PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, unsigned short direction, ExceptionCode& ec)
107 {
108     IDB_TRACE("IDBIndex::openCursor");
109     RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(key, ec);
110     if (ec)
111         return 0;
112     return openCursor(context, keyRange.release(), ec);
113 }
114
115 PassRefPtr<IDBRequest> IDBIndex::count(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec)
116 {
117     IDB_TRACE("IDBIndex::count");
118     if (m_deleted) {
119         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
120         return 0;
121     }
122     if (!m_transaction->isActive()) {
123         ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
124         return 0;
125     }
126     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
127     m_backend->count(keyRange, request, m_transaction->backend(), ec);
128     if (ec) {
129         request->markEarlyDeath();
130         return 0;
131     }
132     return request;
133 }
134
135 PassRefPtr<IDBRequest> IDBIndex::count(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec)
136 {
137     IDB_TRACE("IDBIndex::count");
138     RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(key, ec);
139     if (ec)
140         return 0;
141     return count(context, keyRange.release(), ec);
142 }
143
144 PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, const String& directionString, ExceptionCode& ec)
145 {
146     IDB_TRACE("IDBIndex::openKeyCursor");
147     if (m_deleted) {
148         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
149         return 0;
150     }
151     if (!m_transaction->isActive()) {
152         ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
153         return 0;
154     }
155
156     unsigned short direction = IDBCursor::stringToDirection(directionString, ec);
157     if (ec)
158         return 0;
159
160     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
161     request->setCursorType(IDBCursorBackendInterface::IndexKeyCursor);
162     m_backend->openKeyCursor(keyRange, direction, request, m_transaction->backend(), ec);
163     if (ec) {
164         request->markEarlyDeath();
165         return 0;
166     }
167     return request;
168 }
169
170 PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, ExceptionCode& ec)
171 {
172     IDB_TRACE("IDBIndex::openKeyCursor");
173     DEFINE_STATIC_LOCAL(String, consoleMessage, ("Numeric direction values are deprecated in IDBIndex.openKeyCursor. Use \"next\", \"nextunique\", \"prev\", or \"prevunique\"."));
174     context->addConsoleMessage(JSMessageSource, LogMessageType, WarningMessageLevel, consoleMessage);
175     const String& directionString = IDBCursor::directionToString(direction, ec);
176     if (ec)
177         return 0;
178     return openKeyCursor(context, keyRange, directionString, ec);
179 }
180
181 PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, const String& direction, ExceptionCode& ec)
182 {
183     IDB_TRACE("IDBIndex::openKeyCursor");
184     RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(key, ec);
185     if (ec)
186         return 0;
187     return openKeyCursor(context, keyRange.release(), ec);
188 }
189
190 PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, unsigned short direction, ExceptionCode& ec)
191 {
192     IDB_TRACE("IDBIndex::openKeyCursor");
193     RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(key, ec);
194     if (ec)
195         return 0;
196     return openKeyCursor(context, keyRange.release(), ec);
197 }
198
199 PassRefPtr<IDBRequest> IDBIndex::get(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec)
200 {
201     IDB_TRACE("IDBIndex::get");
202     RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(key, ec);
203     if (ec)
204         return 0;
205     return get(context, keyRange.release(), ec);
206 }
207
208 PassRefPtr<IDBRequest> IDBIndex::get(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec)
209 {
210     IDB_TRACE("IDBIndex::get");
211     if (m_deleted) {
212         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
213         return 0;
214     }
215     if (!m_transaction->isActive()) {
216         ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
217         return 0;
218     }
219     if (!keyRange) {
220         ec = IDBDatabaseException::DATA_ERR;
221         return 0;
222     }
223
224     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
225     m_backend->get(keyRange, request, m_transaction->backend(), ec);
226     if (ec) {
227         request->markEarlyDeath();
228         return 0;
229     }
230     return request;
231 }
232
233 PassRefPtr<IDBRequest> IDBIndex::getKey(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec)
234 {
235     IDB_TRACE("IDBIndex::getKey");
236     RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(key, ec);
237     if (ec)
238         return 0;
239
240     return getKey(context, keyRange.release(), ec);
241 }
242
243 PassRefPtr<IDBRequest> IDBIndex::getKey(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec)
244 {
245     IDB_TRACE("IDBIndex::getKey");
246     if (m_deleted) {
247         ec = IDBDatabaseException::IDB_INVALID_STATE_ERR;
248         return 0;
249     }
250     if (!m_transaction->isActive()) {
251         ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
252         return 0;
253     }
254     if (!keyRange) {
255         ec = IDBDatabaseException::DATA_ERR;
256         return 0;
257     }
258
259     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
260     m_backend->getKey(keyRange, request, m_transaction->backend(), ec);
261     if (ec) {
262         request->markEarlyDeath();
263         return 0;
264     }
265     return request;
266 }
267
268 } // namespace WebCore
269
270 #endif // ENABLE(INDEXED_DATABASE)