Home | History | Annotate | Download | only in storage
      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 (!indexKey)
    345             return true;
    346         if (!m_backingStore.putIndexDataForRecord(m_databaseId, m_objectStoreId, m_indexId, *indexKey, recordIdentifier))
    347             return false;
    348 
    349         return true;
    350     }
    351 
    352 private:
    353     IDBBackingStore& m_backingStore;
    354     const String& m_indexKeyPath;
    355     int64_t m_databaseId;
    356     int64_t m_objectStoreId;
    357     int64_t m_indexId;
    358 };
    359 }
    360 
    361 static bool populateIndex(IDBBackingStore& backingStore, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& indexKeyPath)
    362 {
    363     PopulateIndexCallback callback(backingStore, indexKeyPath, databaseId, objectStoreId, indexId);
    364     if (!backingStore.forEachObjectStoreRecord(databaseId, objectStoreId, callback))
    365         return false;
    366     return true;
    367 }
    368 
    369 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
    370 {
    371     if (m_indexes.contains(name)) {
    372         ec = IDBDatabaseException::CONSTRAINT_ERR;
    373         return 0;
    374     }
    375     if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
    376         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
    377         return 0;
    378     }
    379 
    380     RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, name, m_name, keyPath, unique);
    381     ASSERT(index->name() == name);
    382 
    383     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
    384     RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
    385     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::createIndexInternal, objectStore, index, transaction),
    386                                    createCallbackTask(&IDBObjectStoreBackendImpl::removeIndexFromMap, objectStore, index))) {
    387         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
    388         return 0;
    389     }
    390 
    391     m_indexes.set(name, index);
    392     return index.release();
    393 }
    394 
    395 void IDBObjectStoreBackendImpl::createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
    396 {
    397     int64_t id;
    398     if (!objectStore->m_backingStore->createIndex(objectStore->m_databaseId, objectStore->id(), index->name(), index->keyPath(), index->unique(), id)) {
    399         transaction->abort();
    400         return;
    401     }
    402 
    403     index->setId(id);
    404 
    405     if (!populateIndex(*objectStore->m_backingStore, objectStore->m_databaseId, objectStore->m_id, id, index->keyPath())) {
    406         transaction->abort();
    407         return;
    408     }
    409 
    410     transaction->didCompleteTaskEvents();
    411 }
    412 
    413 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::index(const String& name, ExceptionCode& ec)
    414 {
    415     RefPtr<IDBIndexBackendInterface> index = m_indexes.get(name);
    416     if (!index) {
    417         ec = IDBDatabaseException::NOT_FOUND_ERR;
    418         return 0;
    419     }
    420     return index.release();
    421 }
    422 
    423 void IDBObjectStoreBackendImpl::deleteIndex(const String& name, IDBTransactionBackendInterface* transaction, ExceptionCode& ec)
    424 {
    425     if (transaction->mode() != IDBTransaction::VERSION_CHANGE) {
    426         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
    427         return;
    428     }
    429 
    430     RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
    431     if (!index) {
    432         ec = IDBDatabaseException::NOT_FOUND_ERR;
    433         return;
    434     }
    435 
    436     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
    437     RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction;
    438     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::deleteIndexInternal, objectStore, index, transactionPtr),
    439                                    createCallbackTask(&IDBObjectStoreBackendImpl::addIndexToMap, objectStore, index))) {
    440         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
    441         return;
    442     }
    443     m_indexes.remove(name);
    444 }
    445 
    446 void IDBObjectStoreBackendImpl::deleteIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction)
    447 {
    448     objectStore->m_backingStore->deleteIndex(objectStore->m_databaseId, objectStore->id(), index->id());
    449     transaction->didCompleteTaskEvents();
    450 }
    451 
    452 void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
    453 {
    454     RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
    455     RefPtr<IDBKeyRange> range = prpRange;
    456     RefPtr<IDBCallbacks> callbacks = prpCallbacks;
    457     RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
    458     if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::openCursorInternal, objectStore, range, direction, callbacks, transaction)))
    459         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
    460 }
    461 
    462 void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> range, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
    463 {
    464     IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(tmpDirection);
    465 
    466     RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->m_backingStore->openObjectStoreCursor(objectStore->m_databaseId, objectStore->id(), range.get(), direction);
    467     if (!backingStoreCursor) {
    468         callbacks->onSuccess(SerializedScriptValue::nullValue());
    469         return;
    470     }
    471 
    472     RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(backingStoreCursor.release(), direction, IDBCursorBackendInterface::ObjectStoreCursor, transaction.get(), objectStore.get());
    473     callbacks->onSuccess(cursor.release());
    474 }
    475 
    476 void IDBObjectStoreBackendImpl::loadIndexes()
    477 {
    478     Vector<int64_t> ids;
    479     Vector<String> names;
    480     Vector<String> keyPaths;
    481     Vector<bool> uniqueFlags;
    482     m_backingStore->getIndexes(m_databaseId, m_id, ids, names, keyPaths, uniqueFlags);
    483 
    484     ASSERT(names.size() == ids.size());
    485     ASSERT(keyPaths.size() == ids.size());
    486     ASSERT(uniqueFlags.size() == ids.size());
    487 
    488     for (size_t i = 0; i < ids.size(); i++)
    489         m_indexes.set(names[i], IDBIndexBackendImpl::create(m_backingStore.get(), m_databaseId, this, ids[i], names[i], m_name, keyPaths[i], uniqueFlags[i]));
    490 }
    491 
    492 void IDBObjectStoreBackendImpl::removeIndexFromMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
    493 {
    494     ASSERT(objectStore->m_indexes.contains(index->name()));
    495     objectStore->m_indexes.remove(index->name());
    496 }
    497 
    498 void IDBObjectStoreBackendImpl::addIndexToMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index)
    499 {
    500     RefPtr<IDBIndexBackendImpl> indexPtr = index;
    501     ASSERT(!objectStore->m_indexes.contains(indexPtr->name()));
    502     objectStore->m_indexes.set(indexPtr->name(), indexPtr);
    503 }
    504 
    505 PassRefPtr<IDBKey> IDBObjectStoreBackendImpl::genAutoIncrementKey()
    506 {
    507     if (m_autoIncrementNumber > 0)
    508         return IDBKey::createNumber(m_autoIncrementNumber++);
    509 
    510     m_autoIncrementNumber = static_cast<int>(m_backingStore->nextAutoIncrementNumber(m_databaseId, id()));
    511     return IDBKey::createNumber(m_autoIncrementNumber++);
    512 }
    513 
    514 
    515 } // namespace WebCore
    516 
    517 #endif
    518