2011-04-05 Hans Wennborg <hans@chromium.org>
[WebKit-https.git] / Source / WebCore / storage / IDBObjectStoreBackendImpl.cpp
1 /*
2  * Copyright (C) 2011 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 "IDBObjectStoreBackendImpl.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "CrossThreadTask.h"
32 #include "DOMStringList.h"
33 #include "IDBBackingStore.h"
34 #include "IDBBindingUtilities.h"
35 #include "IDBCallbacks.h"
36 #include "IDBCursorBackendImpl.h"
37 #include "IDBDatabaseBackendImpl.h"
38 #include "IDBDatabaseException.h"
39 #include "IDBIndexBackendImpl.h"
40 #include "IDBKey.h"
41 #include "IDBKeyPath.h"
42 #include "IDBKeyPathBackendImpl.h"
43 #include "IDBKeyRange.h"
44 #include "IDBTransactionBackendInterface.h"
45 #include "ScriptExecutionContext.h"
46
47 namespace WebCore {
48
49 IDBObjectStoreBackendImpl::~IDBObjectStoreBackendImpl()
50 {
51 }
52
53 IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, int64_t id, const String& name, const String& keyPath, bool autoIncrement)
54     : m_backingStore(backingStore)
55     , m_databaseId(databaseId)
56     , m_id(id)
57     , m_name(name)
58     , m_keyPath(keyPath)
59     , m_autoIncrement(autoIncrement)
60     , m_autoIncrementNumber(-1)
61 {
62     loadIndexes();
63 }
64
65 IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(IDBBackingStore* backingStore, int64_t databaseId, const String& name, const String& keyPath, bool autoIncrement)
66     : m_backingStore(backingStore)
67     , m_databaseId(databaseId)
68     , m_id(InvalidId)
69     , m_name(name)
70     , m_keyPath(keyPath)
71     , m_autoIncrement(autoIncrement)
72     , m_autoIncrementNumber(-1)
73 {
74 }
75
76 PassRefPtr<DOMStringList> IDBObjectStoreBackendImpl::indexNames() const
77 {
78     RefPtr<DOMStringList> indexNames = DOMStringList::create();
79     for (IndexMap::const_iterator it = m_indexes.begin(); it != m_indexes.end(); ++it)
80         indexNames->append(it->first);
81     return indexNames.release();
82 }
83
84 void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
85 {
86     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
87     RefPtr<IDBKey> key = prpKey;
88     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
89     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::getInternal, objectStore, key, callbacks)))
90         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
91 }
92
93 void IDBObjectStoreBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
94 {
95     String wireData = objectStore->m_backingStore->getObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), *key);
96     if (wireData.isNull()) {
97         callbacks->onSuccess(SerializedScriptValue::undefinedValue());
98         return;
99     }
100
101     callbacks->onSuccess(SerializedScriptValue::createFromWire(wireData));
102 }
103
104 static PassRefPtr<IDBKey> fetchKeyFromKeyPath(SerializedScriptValue* value, const String& keyPath)
105 {
106     Vector<RefPtr<SerializedScriptValue> > values;
107     values.append(value);
108     Vector<RefPtr<IDBKey> > keys;
109     IDBKeyPathBackendImpl::createIDBKeysFromSerializedValuesAndKeyPath(values, keyPath, keys);
110     if (keys.isEmpty())
111         return 0;
112     ASSERT(keys.size() == 1);
113     return keys[0].release();
114 }
115
116 static PassRefPtr<SerializedScriptValue> injectKeyIntoKeyPath(PassRefPtr<IDBKey> key, PassRefPtr<SerializedScriptValue> value, const String& keyPath)
117 {
118     return IDBKeyPathBackendImpl::injectIDBKeyIntoSerializedValue(key, value, keyPath);
119 }
120
121 void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
122 {
123     if (transactionPtr->mode() == IDBTransaction::READ_ONLY) {
124         ec = IDBDatabaseException::READ_ONLY_ERR;
125         return;
126     }
127
128     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
129     RefPtr<SerializedScriptValue> value = prpValue;
130     RefPtr<IDBKey> key = prpKey;
131     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
132     RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
133     // FIXME: This should throw a SERIAL_ERR on structured clone problems.
134     // FIXME: This should throw a DATA_ERR when the wrong key/keyPath data is supplied.
135     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::putInternal, objectStore, value, key, putMode, callbacks, transaction)))
136         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
137 }
138
139 PassRefPtr<IDBKey> IDBObjectStoreBackendImpl::selectKeyForPut(IDBObjectStoreBackendImpl* objectStore, IDBKey* key, PutMode putMode, IDBCallbacks* callbacks, RefPtr<SerializedScriptValue>& value)
140 {
141     if (putMode == CursorUpdate)
142         ASSERT(key);
143
144     const bool autoIncrement = objectStore->autoIncrement();
145     const bool hasKeyPath = !objectStore->m_keyPath.isNull();
146
147     if (hasKeyPath && key && putMode != CursorUpdate) {
148         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "A key was supplied for an objectStore that has a keyPath."));
149         return 0;
150     }
151
152     if (autoIncrement && key) {
153         objectStore->resetAutoIncrementKeyCache();
154         return key;
155     }
156
157     if (autoIncrement) {
158         ASSERT(!key);
159         if (!hasKeyPath)
160             return objectStore->genAutoIncrementKey();
161
162         RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
163         if (keyPathKey) {
164             objectStore->resetAutoIncrementKeyCache();
165             return keyPathKey;
166         }
167
168         RefPtr<IDBKey> autoIncKey = objectStore->genAutoIncrementKey();
169         RefPtr<SerializedScriptValue> valueAfterInjection = injectKeyIntoKeyPath(autoIncKey, value, objectStore->m_keyPath);
170         if (!valueAfterInjection) {
171             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The generated key could not be inserted into the object using the keyPath."));
172             return 0;
173         }
174         value = valueAfterInjection;
175         return autoIncKey.release();
176     }
177
178     if (hasKeyPath) {
179         RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
180
181         if (!keyPathKey) {
182             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key could not be fetched from the keyPath."));
183             return 0;
184         }
185
186         if (putMode == CursorUpdate && !keyPathKey->isEqual(key)) {
187             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key fetched from the keyPath does not match the key of the cursor."));
188             return 0;
189         }
190
191         return keyPathKey.release();
192     }
193
194     if (!key) {
195         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied"));
196         return 0;
197     }
198
199     return key;
200 }
201
202 void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
203 {
204     RefPtr<SerializedScriptValue> value = prpValue;
205     RefPtr<IDBKey> key = selectKeyForPut(objectStore.get(), prpKey.get(), putMode, callbacks.get(), value);
206     if (!key)
207         return;
208
209     if (key->type() == IDBKey::NullType) {
210         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "NULL key is not allowed."));
211         return;
212     }
213
214     Vector<RefPtr<IDBKey> > indexKeys;
215     for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
216         RefPtr<IDBKey> key = fetchKeyFromKeyPath(value.get(), it->second->keyPath());
217         if (!key) {
218             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from an index's keyPath."));
219             return;
220         }
221         if (key->type() == IDBKey::NullType) {
222             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "One of the derived (from a keyPath) keys for an index is NULL."));
223             return;
224         }
225         if (!it->second->addingKeyAllowed(key.get())) {
226             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "One of the derived (from a keyPath) keys for an index does not satisfy its uniqueness requirements."));
227             return;
228         }
229         indexKeys.append(key.release());
230     }
231
232     RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = objectStore->m_backingStore->createInvalidRecordIdentifier();
233     bool isExistingValue = objectStore->m_backingStore->keyExistsInObjectStore(objectStore->m_databaseId, objectStore->id(), *key, recordIdentifier.get());
234
235     if (putMode == AddOnly && isExistingValue) {
236         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
237         return;
238     }
239
240     // Before this point, don't do any mutation.  After this point, rollback the transaction in case of error.
241
242     if (!objectStore->m_backingStore->putObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), *key, value->toWireString(), recordIdentifier.get())) {
243         // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
244         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
245         transaction->abort();
246         return;
247     }
248
249     int i = 0;
250     for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it, ++i) {
251         if (!it->second->hasValidId())
252             continue; // The index object has been created, but does not exist in the database yet.
253
254         if (!objectStore->m_backingStore->deleteIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), recordIdentifier.get())) {
255             // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
256             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
257             transaction->abort();
258             return;
259         }
260
261         if (!objectStore->m_backingStore->putIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), *indexKeys[i], recordIdentifier.get())) {
262             // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
263             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
264             transaction->abort();
265             return;
266         }
267     }
268
269     callbacks->onSuccess(key.get());
270 }
271
272 void IDBObjectStoreBackendImpl::deleteFunction(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
273 {
274     if (transaction->mode() == IDBTransaction::READ_ONLY) {
275         ec = IDBDatabaseException::READ_ONLY_ERR;
276         return;
277     }
278
279     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
280     RefPtr<IDBKey> key = prpKey;
281     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
282
283     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::deleteInternal, objectStore, key, callbacks)))
284         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
285 }
286
287 void IDBObjectStoreBackendImpl::deleteInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
288 {
289     RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = objectStore->m_backingStore->createInvalidRecordIdentifier();
290     if (!objectStore->m_backingStore->keyExistsInObjectStore(objectStore->m_databaseId, objectStore->id(), *key, recordIdentifier.get())) {
291         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
292         return;
293     }
294
295     for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
296         if (!it->second->hasValidId())
297             continue; // The index object has been created, but does not exist in the database yet.
298
299         if (!objectStore->m_backingStore->deleteIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), recordIdentifier.get()))
300             ASSERT_NOT_REACHED();
301     }
302
303     objectStore->m_backingStore->deleteObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), recordIdentifier.get());
304     callbacks->onSuccess(SerializedScriptValue::nullValue());
305 }
306
307 void IDBObjectStoreBackendImpl::clear(PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
308 {
309     if (transaction->mode() == IDBTransaction::READ_ONLY) {
310         ec = IDBDatabaseException::READ_ONLY_ERR;
311         return;
312     }
313
314     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
315     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
316
317     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::clearInternal, objectStore, callbacks)))
318         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
319 }
320
321 void IDBObjectStoreBackendImpl::clearInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBCallbacks> callbacks)
322 {
323     objectStore->m_backingStore->clearObjectStore(objectStore->m_databaseId, objectStore->id());
324     callbacks->onSuccess(SerializedScriptValue::undefinedValue());
325 }
326
327 namespace {
328 class PopulateIndexCallback : public IDBBackingStore::ObjectStoreRecordCallback {
329 public:
330     PopulateIndexCallback(IDBBackingStore& backingStore, const String& indexKeyPath, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
331         : m_backingStore(backingStore)
332         , m_indexKeyPath(indexKeyPath)
333         , m_databaseId(databaseId)
334         , m_objectStoreId(objectStoreId)
335         , m_indexId(indexId)
336     {
337     }
338
339     virtual bool callback(const IDBBackingStore::ObjectStoreRecordIdentifier* recordIdentifier, const String& value)
340     {
341         RefPtr<SerializedScriptValue> objectValue = SerializedScriptValue::createFromWire(value);
342         RefPtr<IDBKey> indexKey = fetchKeyFromKeyPath(objectValue.get(), m_indexKeyPath);
343
344         if (!m_backingStore.putIndexDataForRecord(m_databaseId, m_objectStoreId, m_indexId, *indexKey, recordIdentifier))
345             return false;
346
347         return true;
348     }
349
350 private:
351     IDBBackingStore& m_backingStore;
352     const String& m_indexKeyPath;
353     int64_t m_databaseId;
354     int64_t m_objectStoreId;
355     int64_t m_indexId;
356 };
357 }
358
359 static bool populateIndex(IDBBackingStore& backingStore, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& indexKeyPath)
360 {
361     PopulateIndexCallback callback(backingStore, indexKeyPath, databaseId, objectStoreId, indexId);
362     if (!backingStore.forEachObjectStoreRecord(databaseId, objectStoreId, callback))
363         return false;
364     return true;
365 }
366
367 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
368 {
369     if (m_indexes.contains(name)) {
370         ec = IDBDatabaseException::CONSTRAINT_ERR;
371         return 0;
372     }
373     if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
374         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
375         return 0;
376     }
377
378     RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, name, m_name, keyPath, unique);
379     ASSERT(index->name() == name);
380
381     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
382     RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
383     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::createIndexInternal, objectStore, index, transaction),
384                                    createCallbackTask(&IDBObjectStoreBackendImpl::removeIndexFromMap, objectStore, index))) {
385         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
386         return 0;
387     }
388
389     m_indexes.set(name, index);
390     return index.release();
391 }
392
393 void IDBObjectStoreBackendImpl::createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
394 {
395     int64_t id;
396     if (!objectStore->m_backingStore->createIndex(objectStore->m_databaseId, objectStore->id(), index->name(), index->keyPath(), index->unique(), id)) {
397         transaction->abort();
398         return;
399     }
400
401     index->setId(id);
402
403     if (!populateIndex(*objectStore->m_backingStore, objectStore->m_databaseId, objectStore->m_id, id, index->keyPath())) {
404         transaction->abort();
405         return;
406     }
407
408     transaction->didCompleteTaskEvents();
409 }
410
411 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::index(const String& name, ExceptionCode& ec)
412 {
413     RefPtr<IDBIndexBackendInterface> index = m_indexes.get(name);
414     if (!index) {
415         ec = IDBDatabaseException::NOT_FOUND_ERR;
416         return 0;
417     }
418     return index.release();
419 }
420
421 void IDBObjectStoreBackendImpl::deleteIndex(const String& name, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
422 {
423     if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
424         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
425         return;
426     }
427
428     RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
429     if (!index) {
430         ec = IDBDatabaseException::NOT_FOUND_ERR;
431         return;
432     }
433
434     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
435     RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
436     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::deleteIndexInternal, objectStore, index, transactionPtr),
437                                    createCallbackTask(&IDBObjectStoreBackendImpl::addIndexToMap, objectStore, index))) {
438         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
439         return;
440     }
441     m_indexes.remove(name);
442 }
443
444 void IDBObjectStoreBackendImpl::deleteIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
445 {
446     objectStore->m_backingStore->deleteIndex(objectStore->m_databaseId, objectStore->id(), index->id());
447     transaction->didCompleteTaskEvents();
448 }
449
450 void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
451 {
452     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
453     RefPtr<IDBKeyRange> range = prpRange;
454     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
455     RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
456     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::openCursorInternal, objectStore, range, direction, callbacks, transaction)))
457         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
458 }
459
460 void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> range, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
461 {
462     IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(tmpDirection);
463
464     RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->m_backingStore->openObjectStoreCursor(objectStore->m_databaseId, objectStore->id(), range.get(), direction);
465     if (!backingStoreCursor) {
466         callbacks->onSuccess(SerializedScriptValue::nullValue());
467         return;
468     }
469
470     RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(backingStoreCursor.release(), direction, IDBCursorBackendInterface::ObjectStoreCursor, transaction.get(), objectStore.get());
471     callbacks->onSuccess(cursor.release());
472 }
473
474 void IDBObjectStoreBackendImpl::loadIndexes()
475 {
476     Vector<int64_t> ids;
477     Vector<String> names;
478     Vector<String> keyPaths;
479     Vector<bool> uniqueFlags;
480     m_backingStore->getIndexes(m_databaseId, m_id, ids, names, keyPaths, uniqueFlags);
481
482     ASSERT(names.size() == ids.size());
483     ASSERT(keyPaths.size() == ids.size());
484     ASSERT(uniqueFlags.size() == ids.size());
485
486     for (size_t i = 0; i < ids.size(); i++)
487         m_indexes.set(names[i], IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, ids[i], names[i], m_name, keyPaths[i], uniqueFlags[i]));
488 }
489
490 void IDBObjectStoreBackendImpl::removeIndexFromMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
491 {
492     ASSERT(objectStore->m_indexes.contains(index->name()));
493     objectStore->m_indexes.remove(index->name());
494 }
495
496 void IDBObjectStoreBackendImpl::addIndexToMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
497 {
498     RefPtr<IDBIndexBackendImpl> indexPtr = index;
499     ASSERT(!objectStore->m_indexes.contains(indexPtr->name()));
500     objectStore->m_indexes.set(indexPtr->name(), indexPtr);
501 }
502
503 PassRefPtr<IDBKey> IDBObjectStoreBackendImpl::genAutoIncrementKey()
504 {
505     if (m_autoIncrementNumber > 0)
506         return IDBKey::createNumber(m_autoIncrementNumber++);
507
508     m_autoIncrementNumber = static_cast<int>(m_backingStore->nextAutoIncrementNumber(m_databaseId, id()));
509     return IDBKey::createNumber(m_autoIncrementNumber++);
510 }
511
512
513 } // namespace WebCore
514
515 #endif