initial import
[vuplus_webkit] / 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
134     if (key && (key->type() == IDBKey::NullType)) {
135         ec = IDBDatabaseException::DATA_ERR;
136         return;
137     }
138
139     const bool autoIncrement = objectStore->autoIncrement();
140     const bool hasKeyPath = !objectStore->m_keyPath.isNull();
141     if (!key && !autoIncrement && !hasKeyPath) {
142         ec = IDBDatabaseException::DATA_ERR;
143         return;
144     }
145
146     // FIXME: This should throw a SERIAL_ERR on structured clone problems.
147     // FIXME: This should throw a DATA_ERR when the wrong key/keyPath data is supplied.
148     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::putInternal, objectStore, value, key, putMode, callbacks, transaction)))
149         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
150 }
151
152 PassRefPtr<IDBKey> IDBObjectStoreBackendImpl::selectKeyForPut(IDBObjectStoreBackendImpl* objectStore, IDBKey* key, PutMode putMode, IDBCallbacks* callbacks, RefPtr<SerializedScriptValue>& value)
153 {
154     if (putMode == CursorUpdate)
155         ASSERT(key);
156
157     const bool autoIncrement = objectStore->autoIncrement();
158     const bool hasKeyPath = !objectStore->m_keyPath.isNull();
159
160     if (hasKeyPath && key && putMode != CursorUpdate) {
161         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "A key was supplied for an objectStore that has a keyPath."));
162         return 0;
163     }
164
165     if (autoIncrement && key) {
166         objectStore->resetAutoIncrementKeyCache();
167         return key;
168     }
169
170     if (autoIncrement) {
171         ASSERT(!key);
172         if (!hasKeyPath)
173             return objectStore->genAutoIncrementKey();
174
175         RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
176         if (keyPathKey) {
177             objectStore->resetAutoIncrementKeyCache();
178             return keyPathKey;
179         }
180
181         RefPtr<IDBKey> autoIncKey = objectStore->genAutoIncrementKey();
182         RefPtr<SerializedScriptValue> valueAfterInjection = injectKeyIntoKeyPath(autoIncKey, value, objectStore->m_keyPath);
183         if (!valueAfterInjection) {
184             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The generated key could not be inserted into the object using the keyPath."));
185             return 0;
186         }
187         value = valueAfterInjection;
188         return autoIncKey.release();
189     }
190
191     if (hasKeyPath) {
192         RefPtr<IDBKey> keyPathKey = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
193
194         if (!keyPathKey) {
195             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key could not be fetched from the keyPath."));
196             return 0;
197         }
198
199         if (putMode == CursorUpdate && !keyPathKey->isEqual(key)) {
200             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "The key fetched from the keyPath does not match the key of the cursor."));
201             return 0;
202         }
203
204         return keyPathKey.release();
205     }
206
207     if (!key) {
208         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied"));
209         return 0;
210     }
211
212     return key;
213 }
214
215 void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
216 {
217     RefPtr<SerializedScriptValue> value = prpValue;
218     RefPtr<IDBKey> key = selectKeyForPut(objectStore.get(), prpKey.get(), putMode, callbacks.get(), value);
219     if (!key)
220         return;
221
222     if (key->type() == IDBKey::NullType) {
223         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "NULL key is not allowed."));
224         return;
225     }
226
227     Vector<RefPtr<IDBKey> > indexKeys;
228     for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
229         const RefPtr<IDBIndexBackendImpl>& index = it->second;
230
231         RefPtr<IDBKey> indexKey = fetchKeyFromKeyPath(value.get(), index->keyPath());
232         if (!indexKey) {
233             indexKeys.append(indexKey.release());
234             continue;
235         }
236         if (indexKey->type() == IDBKey::NullType) {
237             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "One of the derived (from a keyPath) keys for an index is NULL."));
238             return;
239         }
240         if (!index->addingKeyAllowed(indexKey.get(), key.get())) { // So problem is that if key() is the same as the old key for this record in this index, then we're not really *adding it*, just updating it...
241             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "One of the derived (from a keyPath) keys for an index does not satisfy its uniqueness requirements."));
242             return;
243         }
244         indexKeys.append(indexKey.release());
245     }
246
247     RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = objectStore->m_backingStore->createInvalidRecordIdentifier();
248     bool isExistingValue = objectStore->m_backingStore->keyExistsInObjectStore(objectStore->m_databaseId, objectStore->id(), *key, recordIdentifier.get());
249
250     if (putMode == AddOnly && isExistingValue) {
251         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
252         return;
253     }
254
255     // Before this point, don't do any mutation.  After this point, rollback the transaction in case of error.
256
257     if (!objectStore->m_backingStore->putObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), *key, value->toWireString(), recordIdentifier.get())) {
258         // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
259         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
260         transaction->abort();
261         return;
262     }
263
264     int i = 0;
265     for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it, ++i) {
266         if (!it->second->hasValidId())
267             continue; // The index object has been created, but does not exist in the database yet.
268
269         if (!objectStore->m_backingStore->deleteIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), recordIdentifier.get())) {
270             // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
271             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
272             transaction->abort();
273             return;
274         }
275
276         if (!indexKeys[i])
277             continue;
278         if (!objectStore->m_backingStore->putIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), *indexKeys[i], recordIdentifier.get())) {
279             // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
280             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
281             transaction->abort();
282             return;
283         }
284     }
285
286     callbacks->onSuccess(key.get());
287 }
288
289 void IDBObjectStoreBackendImpl::deleteFunction(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
290 {
291     if (transaction->mode() == IDBTransaction::READ_ONLY) {
292         ec = IDBDatabaseException::READ_ONLY_ERR;
293         return;
294     }
295
296     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
297     RefPtr<IDBKey> key = prpKey;
298     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
299     if (key->type() == IDBKey::NullType) {
300         ec = IDBDatabaseException::DATA_ERR;
301         return;
302     }
303
304     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::deleteInternal, objectStore, key, callbacks)))
305         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
306 }
307
308 void IDBObjectStoreBackendImpl::deleteInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
309 {
310     RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = objectStore->m_backingStore->createInvalidRecordIdentifier();
311     if (!objectStore->m_backingStore->keyExistsInObjectStore(objectStore->m_databaseId, objectStore->id(), *key, recordIdentifier.get())) {
312         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
313         return;
314     }
315
316     for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
317         if (!it->second->hasValidId())
318             continue; // The index object has been created, but does not exist in the database yet.
319
320         if (!objectStore->m_backingStore->deleteIndexDataForRecord(objectStore->m_databaseId, objectStore->id(), it->second->id(), recordIdentifier.get()))
321             ASSERT_NOT_REACHED();
322     }
323
324     objectStore->m_backingStore->deleteObjectStoreRecord(objectStore->m_databaseId, objectStore->id(), recordIdentifier.get());
325     callbacks->onSuccess(SerializedScriptValue::nullValue());
326 }
327
328 void IDBObjectStoreBackendImpl::clear(PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
329 {
330     if (transaction->mode() == IDBTransaction::READ_ONLY) {
331         ec = IDBDatabaseException::READ_ONLY_ERR;
332         return;
333     }
334
335     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
336     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
337
338     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::clearInternal, objectStore, callbacks)))
339         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
340 }
341
342 void IDBObjectStoreBackendImpl::clearInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBCallbacks> callbacks)
343 {
344     objectStore->m_backingStore->clearObjectStore(objectStore->m_databaseId, objectStore->id());
345     callbacks->onSuccess(SerializedScriptValue::undefinedValue());
346 }
347
348 namespace {
349 class PopulateIndexCallback : public IDBBackingStore::ObjectStoreRecordCallback {
350 public:
351     PopulateIndexCallback(IDBBackingStore& backingStore, const String& indexKeyPath, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
352         : m_backingStore(backingStore)
353         , m_indexKeyPath(indexKeyPath)
354         , m_databaseId(databaseId)
355         , m_objectStoreId(objectStoreId)
356         , m_indexId(indexId)
357     {
358     }
359
360     virtual bool callback(const IDBBackingStore::ObjectStoreRecordIdentifier* recordIdentifier, const String& value)
361     {
362         RefPtr<SerializedScriptValue> objectValue = SerializedScriptValue::createFromWire(value);
363         RefPtr<IDBKey> indexKey = fetchKeyFromKeyPath(objectValue.get(), m_indexKeyPath);
364
365         if (!indexKey)
366             return true;
367         if (!m_backingStore.putIndexDataForRecord(m_databaseId, m_objectStoreId, m_indexId, *indexKey, recordIdentifier))
368             return false;
369
370         return true;
371     }
372
373 private:
374     IDBBackingStore& m_backingStore;
375     const String& m_indexKeyPath;
376     int64_t m_databaseId;
377     int64_t m_objectStoreId;
378     int64_t m_indexId;
379 };
380 }
381
382 bool IDBObjectStoreBackendImpl::populateIndex(IDBBackingStore& backingStore, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& indexKeyPath)
383 {
384     PopulateIndexCallback callback(backingStore, indexKeyPath, databaseId, objectStoreId, indexId);
385     if (!backingStore.forEachObjectStoreRecord(databaseId, objectStoreId, callback))
386         return false;
387     return true;
388 }
389
390 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
391 {
392     if (name.isNull()) {
393         ec = IDBDatabaseException::NON_TRANSIENT_ERR;
394         return 0;
395     }
396     if (m_indexes.contains(name)) {
397         ec = IDBDatabaseException::CONSTRAINT_ERR;
398         return 0;
399     }
400     if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
401         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
402         return 0;
403     }
404
405     RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, name, m_name, keyPath, unique);
406     ASSERT(index->name() == name);
407
408     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
409     RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
410     if (!transaction->scheduleTask(
411               createCallbackTask(&IDBObjectStoreBackendImpl::createIndexInternal,
412                                  objectStore, index, transactionPtr),
413               createCallbackTask(&IDBObjectStoreBackendImpl::removeIndexFromMap,
414                                  objectStore, index))) {
415         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
416         return 0;
417     }
418
419     m_indexes.set(name, index);
420     return index.release();
421 }
422
423 void IDBObjectStoreBackendImpl::createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
424 {
425     int64_t id;
426     if (!objectStore->m_backingStore->createIndex(objectStore->m_databaseId, objectStore->id(), index->name(), index->keyPath(), index->unique(), id)) {
427         transaction->abort();
428         return;
429     }
430
431     index->setId(id);
432
433     if (!populateIndex(*objectStore->m_backingStore, objectStore->m_databaseId, objectStore->m_id, id, index->keyPath())) {
434         transaction->abort();
435         return;
436     }
437
438     transaction->didCompleteTaskEvents();
439 }
440
441 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::index(const String& name, ExceptionCode& ec)
442 {
443     RefPtr<IDBIndexBackendInterface> index = m_indexes.get(name);
444     if (!index) {
445         ec = IDBDatabaseException::NOT_FOUND_ERR;
446         return 0;
447     }
448     return index.release();
449 }
450
451 void IDBObjectStoreBackendImpl::deleteIndex(const String& name, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
452 {
453     if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
454         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
455         return;
456     }
457
458     RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
459     if (!index) {
460         ec = IDBDatabaseException::NOT_FOUND_ERR;
461         return;
462     }
463
464     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
465     RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
466     if (!transaction->scheduleTask(
467               createCallbackTask(&IDBObjectStoreBackendImpl::deleteIndexInternal,
468                                  objectStore, index, transactionPtr),
469               createCallbackTask(&IDBObjectStoreBackendImpl::addIndexToMap,
470                                  objectStore, index))) {
471         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
472         return;
473     }
474     m_indexes.remove(name);
475 }
476
477 void IDBObjectStoreBackendImpl::deleteIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
478 {
479     objectStore->m_backingStore->deleteIndex(objectStore->m_databaseId, objectStore->id(), index->id());
480     transaction->didCompleteTaskEvents();
481 }
482
483 void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
484 {
485     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
486     RefPtr<IDBKeyRange> range = prpRange;
487     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
488     RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
489     if (!transaction->scheduleTask(
490             createCallbackTask(&IDBObjectStoreBackendImpl::openCursorInternal,
491                                objectStore, range, direction, callbacks, transactionPtr))) {
492         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
493     }
494 }
495
496 void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> range, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
497 {
498     IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(tmpDirection);
499
500     RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->m_backingStore->openObjectStoreCursor(objectStore->m_databaseId, objectStore->id(), range.get(), direction);
501     if (!backingStoreCursor) {
502         callbacks->onSuccess(SerializedScriptValue::nullValue());
503         return;
504     }
505
506     RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(backingStoreCursor.release(), direction, IDBCursorBackendInterface::ObjectStoreCursor, transaction.get(), objectStore.get());
507     callbacks->onSuccess(cursor.release());
508 }
509
510 void IDBObjectStoreBackendImpl::loadIndexes()
511 {
512     Vector<int64_t> ids;
513     Vector<String> names;
514     Vector<String> keyPaths;
515     Vector<bool> uniqueFlags;
516     m_backingStore->getIndexes(m_databaseId, m_id, ids, names, keyPaths, uniqueFlags);
517
518     ASSERT(names.size() == ids.size());
519     ASSERT(keyPaths.size() == ids.size());
520     ASSERT(uniqueFlags.size() == ids.size());
521
522     for (size_t i = 0; i < ids.size(); i++)
523         m_indexes.set(names[i], IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, ids[i], names[i], m_name, keyPaths[i], uniqueFlags[i]));
524 }
525
526 void IDBObjectStoreBackendImpl::removeIndexFromMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
527 {
528     ASSERT(objectStore->m_indexes.contains(index->name()));
529     objectStore->m_indexes.remove(index->name());
530 }
531
532 void IDBObjectStoreBackendImpl::addIndexToMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
533 {
534     RefPtr<IDBIndexBackendImpl> indexPtr = index;
535     ASSERT(!objectStore->m_indexes.contains(indexPtr->name()));
536     objectStore->m_indexes.set(indexPtr->name(), indexPtr);
537 }
538
539 PassRefPtr<IDBKey> IDBObjectStoreBackendImpl::genAutoIncrementKey()
540 {
541     if (m_autoIncrementNumber > 0)
542         return IDBKey::createNumber(m_autoIncrementNumber++);
543
544     m_autoIncrementNumber = static_cast<int>(m_backingStore->nextAutoIncrementNumber(m_databaseId, id()));
545     return IDBKey::createNumber(m_autoIncrementNumber++);
546 }
547
548
549 } // namespace WebCore
550
551 #endif