diff options
Diffstat (limited to 'WebCore/storage')
35 files changed, 316 insertions, 252 deletions
diff --git a/WebCore/storage/IDBCursor.idl b/WebCore/storage/IDBCursor.idl index 0cef3f9..2d250d5 100644 --- a/WebCore/storage/IDBCursor.idl +++ b/WebCore/storage/IDBCursor.idl @@ -37,11 +37,13 @@ module storage { readonly attribute IDBKey key; readonly attribute IDBAny value; - [CallWith=ScriptExecutionContext] IDBRequest update(in SerializedScriptValue value) - raises (IDBDatabaseException); + // FIXME: Implement. + //[CallWith=ScriptExecutionContext] IDBRequest update(in SerializedScriptValue value) + // raises (IDBDatabaseException); [ImplementationFunction=continueFunction] void continue(in [Optional] IDBKey key) raises (IDBDatabaseException); - [CallWith=ScriptExecutionContext] IDBRequest remove() - raises (IDBDatabaseException); + // FIXME: Implement. + //[CallWith=ScriptExecutionContext] IDBRequest remove() + // raises (IDBDatabaseException); }; } diff --git a/WebCore/storage/IDBDatabase.cpp b/WebCore/storage/IDBDatabase.cpp index 1ee0fa9..7a9141a 100644 --- a/WebCore/storage/IDBDatabase.cpp +++ b/WebCore/storage/IDBDatabase.cpp @@ -35,11 +35,15 @@ #include "IDBRequest.h" #include "IDBTransaction.h" #include "ScriptExecutionContext.h" +#include <limits> #if ENABLE(INDEXED_DATABASE) namespace WebCore { +// FIXME: We need to spec this differently. +const unsigned long defaultTimeout = 0; // Infinite. + IDBDatabase::IDBDatabase(PassRefPtr<IDBDatabaseBackendInterface> backend) : m_backend(backend) { @@ -56,27 +60,41 @@ void IDBDatabase::setSetVersionTransaction(IDBTransactionBackendInterface* trans m_setVersionTransaction = transaction; } -PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const String& keyPath, bool autoIncrement, ExceptionCode& ec) +PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const OptionsObject& options, ExceptionCode& ec) { if (!m_setVersionTransaction) { ec = IDBDatabaseException::NOT_ALLOWED_ERR; return 0; } + String keyPath; + options.getKeyString("keyPath", keyPath); + bool autoIncrement = false; + options.getKeyBool("autoIncrement", autoIncrement); + // FIXME: Look up evictable and pass that on as well. + + if (autoIncrement) { + // FIXME: Implement support for auto increment. + ec = IDBDatabaseException::UNKNOWN_ERR; + return 0; + } + RefPtr<IDBObjectStoreBackendInterface> objectStore = m_backend->createObjectStore(name, keyPath, autoIncrement, m_setVersionTransaction.get(), ec); - if (!objectStore) + if (!objectStore) { + ASSERT(ec); return 0; + } return IDBObjectStore::create(objectStore.release(), m_setVersionTransaction.get()); } -void IDBDatabase::removeObjectStore(const String& name, ExceptionCode& ec) +void IDBDatabase::deleteObjectStore(const String& name, ExceptionCode& ec) { if (!m_setVersionTransaction) { ec = IDBDatabaseException::NOT_ALLOWED_ERR; return; } - m_backend->removeObjectStore(name, m_setVersionTransaction.get(), ec); + m_backend->deleteObjectStore(name, m_setVersionTransaction.get(), ec); } PassRefPtr<IDBRequest> IDBDatabase::setVersion(ScriptExecutionContext* context, const String& version, ExceptionCode& ec) @@ -86,13 +104,42 @@ PassRefPtr<IDBRequest> IDBDatabase::setVersion(ScriptExecutionContext* context, return request; } -PassRefPtr<IDBTransaction> IDBDatabase::transaction(ScriptExecutionContext* context, DOMStringList* storeNames, unsigned short mode, unsigned long timeout, ExceptionCode& ec) +PassRefPtr<IDBTransaction> IDBDatabase::transaction(ScriptExecutionContext* context, const OptionsObject& options, ExceptionCode& ec) { + RefPtr<DOMStringList> storeNames = options.getKeyDOMStringList("objectStoreNames"); + if (!storeNames) { + storeNames = DOMStringList::create(); + String storeName; + if (options.getKeyString("objectStoreNames", storeName)) + storeNames->append(storeName); + } + + // Gets cast to an unsigned short. + int32_t mode = IDBTransaction::READ_ONLY; + options.getKeyInt32("mode", mode); + if (mode != IDBTransaction::READ_WRITE && mode != IDBTransaction::READ_ONLY) { + // FIXME: May need to change when specced: http://www.w3.org/Bugs/Public/show_bug.cgi?id=11406 + ec = IDBDatabaseException::CONSTRAINT_ERR; + return 0; + } + + // Gets cast to an unsigned long. + // FIXME: The spec needs to be updated on this. It should probably take a double. + int32_t timeout = defaultTimeout; + options.getKeyInt32("timeout", timeout); + int64_t unsignedLongMax = std::numeric_limits<unsigned long>::max(); + if (timeout < 0 || timeout > unsignedLongMax) + timeout = defaultTimeout; // Ignore illegal values. + // We need to create a new transaction synchronously. Locks are acquired asynchronously. Operations // can be queued against the transaction at any point. They will start executing as soon as the // appropriate locks have been acquired. // Also note that each backend object corresponds to exactly one IDBTransaction object. - RefPtr<IDBTransactionBackendInterface> transactionBackend = m_backend->transaction(storeNames, mode, timeout, ec); + RefPtr<IDBTransactionBackendInterface> transactionBackend = m_backend->transaction(storeNames.get(), mode, timeout, ec); + if (!transactionBackend) { + ASSERT(ec); + return 0; + } RefPtr<IDBTransaction> transaction = IDBTransaction::create(context, transactionBackend, this); transactionBackend->setCallbacks(transaction.get()); return transaction.release(); diff --git a/WebCore/storage/IDBDatabase.h b/WebCore/storage/IDBDatabase.h index df56f46..9ebbf00 100644 --- a/WebCore/storage/IDBDatabase.h +++ b/WebCore/storage/IDBDatabase.h @@ -31,6 +31,7 @@ #include "IDBDatabaseBackendInterface.h" #include "IDBObjectStore.h" #include "IDBTransaction.h" +#include "OptionsObject.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -56,19 +57,16 @@ public: // Implement the IDL String name() const { return m_backend->name(); } String version() const { return m_backend->version(); } - PassRefPtr<DOMStringList> objectStores() const { return m_backend->objectStores(); } + PassRefPtr<DOMStringList> objectStoreNames() const { return m_backend->objectStoreNames(); } // FIXME: Try to modify the code generator so this is unneeded. - PassRefPtr<IDBObjectStore> createObjectStore(const String& name, ExceptionCode& ec) { return createObjectStore(name, String(), ec); } - PassRefPtr<IDBObjectStore> createObjectStore(const String& name, const String& keyPath, ExceptionCode& ec) { return createObjectStore(name, keyPath, false, ec); } - PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext* context, ExceptionCode& ec) { return transaction(context, 0, ec); } - PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext* context, DOMStringList* storeNames, ExceptionCode& ec) { return transaction(context, storeNames, IDBTransaction::READ_ONLY, ec); } - PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext* context, DOMStringList* storeNames, unsigned short mode, ExceptionCode& ec) { return transaction(context, storeNames, mode, 0, ec); } // FIXME: what should the default timeout be? + PassRefPtr<IDBObjectStore> createObjectStore(const String& name, ExceptionCode& ec) { return createObjectStore(name, OptionsObject(), ec); } + PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext* context, ExceptionCode& ec) { return transaction(context, OptionsObject(), ec); } - PassRefPtr<IDBObjectStore> createObjectStore(const String& name, const String& keyPath, bool autoIncrement, ExceptionCode&); - void removeObjectStore(const String& name, ExceptionCode&); + PassRefPtr<IDBObjectStore> createObjectStore(const String& name, const OptionsObject&, ExceptionCode&); + void deleteObjectStore(const String& name, ExceptionCode&); PassRefPtr<IDBRequest> setVersion(ScriptExecutionContext*, const String& version, ExceptionCode&); - PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext*, DOMStringList*, unsigned short mode, unsigned long timeout, ExceptionCode&); + PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext*, const OptionsObject&, ExceptionCode&); void close(); private: diff --git a/WebCore/storage/IDBDatabase.idl b/WebCore/storage/IDBDatabase.idl index b529c9a..c6edd48 100644 --- a/WebCore/storage/IDBDatabase.idl +++ b/WebCore/storage/IDBDatabase.idl @@ -30,17 +30,18 @@ module storage { ] IDBDatabase { readonly attribute DOMString name; readonly attribute DOMString version; - readonly attribute DOMStringList objectStores; + readonly attribute DOMStringList objectStoreNames; - IDBObjectStore createObjectStore(in DOMString name, in [Optional, ConvertNullToNullString] DOMString keyPath, in [Optional] boolean autoIncrement) + IDBObjectStore createObjectStore(in DOMString name, in [Optional] OptionsObject options) raises (IDBDatabaseException); - void removeObjectStore(in DOMString name) + void deleteObjectStore(in DOMString name) raises (IDBDatabaseException); [CallWith=ScriptExecutionContext] IDBRequest setVersion(in DOMString version) raises (IDBDatabaseException); - [CallWith=ScriptExecutionContext] IDBTransaction transaction (in [Optional] DOMStringList storeNames, in [Optional] unsigned short mode, in [Optional] unsigned long timeout) + [CallWith=ScriptExecutionContext] IDBTransaction transaction (in [Optional] OptionsObject optionsObject) raises (IDBDatabaseException); - void close(); + // FIXME: Implement. + //void close(); }; } diff --git a/WebCore/storage/IDBDatabaseBackendImpl.cpp b/WebCore/storage/IDBDatabaseBackendImpl.cpp index 004dc7b..fa9a336 100644 --- a/WebCore/storage/IDBDatabaseBackendImpl.cpp +++ b/WebCore/storage/IDBDatabaseBackendImpl.cpp @@ -60,14 +60,13 @@ static bool extractMetaData(SQLiteDatabase& sqliteDatabase, const String& name, return true; } -static bool setMetaData(SQLiteDatabase& sqliteDatabase, const String& name, const String& description, const String& version, int64_t& rowId) +static bool setMetaData(SQLiteDatabase& sqliteDatabase, const String& name, const String& version, int64_t& rowId) { ASSERT(!name.isNull()); - ASSERT(!description.isNull()); ASSERT(!version.isNull()); - String sql = rowId != IDBDatabaseBackendImpl::InvalidId ? "UPDATE Databases SET name = ?, description = ?, version = ? WHERE id = ?" - : "INSERT INTO Databases (name, description, version) VALUES (?, ?, ?)"; + String sql = rowId != IDBDatabaseBackendImpl::InvalidId ? "UPDATE Databases SET name = ?, version = ? WHERE id = ?" + : "INSERT INTO Databases (name, description, version) VALUES (?, '', ?)"; SQLiteStatement query(sqliteDatabase, sql); if (query.prepare() != SQLResultOk) { ASSERT_NOT_REACHED(); @@ -75,10 +74,9 @@ static bool setMetaData(SQLiteDatabase& sqliteDatabase, const String& name, cons } query.bindText(1, name); - query.bindText(2, description); - query.bindText(3, version); + query.bindText(2, version); if (rowId != IDBDatabaseBackendImpl::InvalidId) - query.bindInt64(4, rowId); + query.bindInt64(3, rowId); if (query.step() != SQLResultDone) return false; @@ -89,22 +87,20 @@ static bool setMetaData(SQLiteDatabase& sqliteDatabase, const String& name, cons return true; } -IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, const String& description, IDBSQLiteDatabase* sqliteDatabase, IDBTransactionCoordinator* coordinator, IDBFactoryBackendImpl* factory, const String& uniqueIdentifier) +IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, IDBSQLiteDatabase* sqliteDatabase, IDBTransactionCoordinator* coordinator, IDBFactoryBackendImpl* factory, const String& uniqueIdentifier) : m_sqliteDatabase(sqliteDatabase) , m_id(InvalidId) , m_name(name) - , m_description(description) , m_version("") , m_identifier(uniqueIdentifier) , m_factory(factory) , m_transactionCoordinator(coordinator) { ASSERT(!m_name.isNull()); - ASSERT(!m_description.isNull()); bool success = extractMetaData(m_sqliteDatabase->db(), m_name, m_version, m_id); ASSERT_UNUSED(success, success == (m_id != InvalidId)); - if (!setMetaData(m_sqliteDatabase->db(), m_name, m_description, m_version, m_id)) + if (!setMetaData(m_sqliteDatabase->db(), m_name, m_version, m_id)) ASSERT_NOT_REACHED(); // FIXME: Need better error handling. loadObjectStores(); } @@ -114,21 +110,12 @@ IDBDatabaseBackendImpl::~IDBDatabaseBackendImpl() m_factory->removeIDBDatabaseBackend(m_identifier); } -void IDBDatabaseBackendImpl::setDescription(const String& description) -{ - if (description == m_description) - return; - - m_description = description; - setMetaData(m_sqliteDatabase->db(), m_name, m_description, m_version, m_id); -} - SQLiteDatabase& IDBDatabaseBackendImpl::sqliteDatabase() const { return m_sqliteDatabase->db(); } -PassRefPtr<DOMStringList> IDBDatabaseBackendImpl::objectStores() const +PassRefPtr<DOMStringList> IDBDatabaseBackendImpl::objectStoreNames() const { RefPtr<DOMStringList> objectStoreNames = DOMStringList::create(); for (ObjectStoreMap::const_iterator it = m_objectStores.begin(); it != m_objectStores.end(); ++it) @@ -138,8 +125,10 @@ PassRefPtr<DOMStringList> IDBDatabaseBackendImpl::objectStores() const PassRefPtr<IDBObjectStoreBackendInterface> IDBDatabaseBackendImpl::createObjectStore(const String& name, const String& keyPath, bool autoIncrement, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec) { + ASSERT(transactionPtr->mode() == IDBTransaction::VERSION_CHANGE); + if (m_objectStores.contains(name)) { - // FIXME: Throw CONSTRAINT_ERR in this case. + ec = IDBDatabaseException::CONSTRAINT_ERR; return 0; } @@ -150,6 +139,7 @@ PassRefPtr<IDBObjectStoreBackendInterface> IDBDatabaseBackendImpl::createObject RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr; if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::createObjectStoreInternal, database, objectStore, transaction), createCallbackTask(&IDBDatabaseBackendImpl::removeObjectStoreFromMap, database, objectStore))) { + ec = IDBDatabaseException::NOT_ALLOWED_ERR; return 0; } @@ -192,7 +182,7 @@ static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id) ASSERT_UNUSED(ok, ok); // FIXME: Better error handling. } -void IDBDatabaseBackendImpl::removeObjectStore(const String& name, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec) +void IDBDatabaseBackendImpl::deleteObjectStore(const String& name, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec) { RefPtr<IDBObjectStoreBackendImpl> objectStore = m_objectStores.get(name); if (!objectStore) { @@ -201,7 +191,7 @@ void IDBDatabaseBackendImpl::removeObjectStore(const String& name, IDBTransactio } RefPtr<IDBDatabaseBackendImpl> database = this; RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr; - if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::removeObjectStoreInternal, database, objectStore, transaction), + if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::deleteObjectStoreInternal, database, objectStore, transaction), createCallbackTask(&IDBDatabaseBackendImpl::addObjectStoreToMap, database, objectStore))) { ec = IDBDatabaseException::NOT_ALLOWED_ERR; return; @@ -209,7 +199,7 @@ void IDBDatabaseBackendImpl::removeObjectStore(const String& name, IDBTransactio m_objectStores.remove(name); } -void IDBDatabaseBackendImpl::removeObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBTransactionBackendInterface> transaction) +void IDBDatabaseBackendImpl::deleteObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBTransactionBackendInterface> transaction) { doDelete(database->sqliteDatabase(), "DELETE FROM ObjectStores WHERE id = ?", objectStore->id()); doDelete(database->sqliteDatabase(), "DELETE FROM ObjectStoreData WHERE objectStoreId = ?", objectStore->id()); @@ -223,8 +213,8 @@ void IDBDatabaseBackendImpl::setVersion(const String& version, PassRefPtr<IDBCal { RefPtr<IDBDatabaseBackendImpl> database = this; RefPtr<IDBCallbacks> callbacks = prpCallbacks; - RefPtr<DOMStringList> objectStores = DOMStringList::create(); - RefPtr<IDBTransactionBackendInterface> transaction = IDBTransactionBackendImpl::create(objectStores.get(), IDBTransaction::VERSION_CHANGE, 0, this); + RefPtr<DOMStringList> objectStoreNames = DOMStringList::create(); + RefPtr<IDBTransactionBackendInterface> transaction = IDBTransactionBackendImpl::create(objectStoreNames.get(), IDBTransaction::VERSION_CHANGE, 0, this); if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::setVersionInternal, database, version, callbacks, transaction), createCallbackTask(&IDBDatabaseBackendImpl::resetVersion, database, m_version))) { ec = IDBDatabaseException::NOT_ALLOWED_ERR; @@ -235,7 +225,7 @@ void IDBDatabaseBackendImpl::setVersionInternal(ScriptExecutionContext*, PassRef { int64_t databaseId = database->id(); database->m_version = version; - if (!setMetaData(database->m_sqliteDatabase->db(), database->m_name, database->m_description, database->m_version, databaseId)) { + if (!setMetaData(database->m_sqliteDatabase->db(), database->m_name, database->m_version, databaseId)) { // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors. callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage.")); transaction->abort(); @@ -244,10 +234,17 @@ void IDBDatabaseBackendImpl::setVersionInternal(ScriptExecutionContext*, PassRef callbacks->onSuccess(transaction); } -PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(DOMStringList* objectStores, unsigned short mode, unsigned long timeout, ExceptionCode&) +PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(DOMStringList* objectStoreNames, unsigned short mode, unsigned long timeout, ExceptionCode& ec) { + for (size_t i = 0; i < objectStoreNames->length(); ++i) { + if (!m_objectStores.contains(objectStoreNames->item(i))) { + ec = IDBDatabaseException::NOT_FOUND_ERR; + return 0; + } + } + // FIXME: Return not allowed err if close has been called. - return IDBTransactionBackendImpl::create(objectStores, mode, timeout, this); + return IDBTransactionBackendImpl::create(objectStoreNames, mode, timeout, this); } void IDBDatabaseBackendImpl::close() diff --git a/WebCore/storage/IDBDatabaseBackendImpl.h b/WebCore/storage/IDBDatabaseBackendImpl.h index 8c97a70..570f6a5 100644 --- a/WebCore/storage/IDBDatabaseBackendImpl.h +++ b/WebCore/storage/IDBDatabaseBackendImpl.h @@ -43,39 +43,37 @@ class SQLiteDatabase; class IDBDatabaseBackendImpl : public IDBDatabaseBackendInterface { public: - static PassRefPtr<IDBDatabaseBackendImpl> create(const String& name, const String& description, IDBSQLiteDatabase* database, IDBTransactionCoordinator* coordinator, IDBFactoryBackendImpl* factory, const String& uniqueIdentifier) + static PassRefPtr<IDBDatabaseBackendImpl> create(const String& name, IDBSQLiteDatabase* database, IDBTransactionCoordinator* coordinator, IDBFactoryBackendImpl* factory, const String& uniqueIdentifier) { - return adoptRef(new IDBDatabaseBackendImpl(name, description, database, coordinator, factory, uniqueIdentifier)); + return adoptRef(new IDBDatabaseBackendImpl(name, database, coordinator, factory, uniqueIdentifier)); } virtual ~IDBDatabaseBackendImpl(); - void setDescription(const String& description); SQLiteDatabase& sqliteDatabase() const; static const int64_t InvalidId = 0; int64_t id() const { return m_id; } virtual String name() const { return m_name; } - virtual String description() const { return m_description; } virtual String version() const { return m_version; } - virtual PassRefPtr<DOMStringList> objectStores() const; + virtual PassRefPtr<DOMStringList> objectStoreNames() const; virtual PassRefPtr<IDBObjectStoreBackendInterface> createObjectStore(const String& name, const String& keyPath, bool autoIncrement, IDBTransactionBackendInterface*, ExceptionCode&); - virtual void removeObjectStore(const String& name, IDBTransactionBackendInterface*, ExceptionCode&); + virtual void deleteObjectStore(const String& name, IDBTransactionBackendInterface*, ExceptionCode&); virtual void setVersion(const String& version, PassRefPtr<IDBCallbacks>, ExceptionCode&); - virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* storeNames, unsigned short mode, unsigned long timeout, ExceptionCode&); + virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* objectStoreNames, unsigned short mode, unsigned long timeout, ExceptionCode&); virtual void close(); PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name); IDBTransactionCoordinator* transactionCoordinator() const { return m_transactionCoordinator.get(); } private: - IDBDatabaseBackendImpl(const String& name, const String& description, IDBSQLiteDatabase* database, IDBTransactionCoordinator*, IDBFactoryBackendImpl*, const String& uniqueIdentifier); + IDBDatabaseBackendImpl(const String& name, IDBSQLiteDatabase* database, IDBTransactionCoordinator*, IDBFactoryBackendImpl*, const String& uniqueIdentifier); void loadObjectStores(); static void createObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBTransactionBackendInterface>); - static void removeObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBTransactionBackendInterface>); + static void deleteObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBTransactionBackendInterface>); static void setVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, const String& version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>); // These are used as setVersion transaction abort tasks. @@ -86,7 +84,6 @@ private: RefPtr<IDBSQLiteDatabase> m_sqliteDatabase; int64 m_id; String m_name; - String m_description; String m_version; String m_identifier; diff --git a/WebCore/storage/IDBDatabaseBackendInterface.h b/WebCore/storage/IDBDatabaseBackendInterface.h index 4b0255d..0dc59b1 100644 --- a/WebCore/storage/IDBDatabaseBackendInterface.h +++ b/WebCore/storage/IDBDatabaseBackendInterface.h @@ -51,12 +51,11 @@ public: virtual ~IDBDatabaseBackendInterface() { } virtual String name() const = 0; - virtual String description() const = 0; virtual String version() const = 0; - virtual PassRefPtr<DOMStringList> objectStores() const = 0; + virtual PassRefPtr<DOMStringList> objectStoreNames() const = 0; virtual PassRefPtr<IDBObjectStoreBackendInterface> createObjectStore(const String& name, const String& keyPath, bool autoIncrement, IDBTransactionBackendInterface*, ExceptionCode&) = 0; - virtual void removeObjectStore(const String& name, IDBTransactionBackendInterface*, ExceptionCode&) = 0; + virtual void deleteObjectStore(const String& name, IDBTransactionBackendInterface*, ExceptionCode&) = 0; virtual void setVersion(const String& version, PassRefPtr<IDBCallbacks>, ExceptionCode&) = 0; virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* storeNames, unsigned short mode, unsigned long timeout, ExceptionCode&) = 0; virtual void close() = 0; diff --git a/WebCore/storage/IDBFactory.cpp b/WebCore/storage/IDBFactory.cpp index 649eb37..85e976c 100644 --- a/WebCore/storage/IDBFactory.cpp +++ b/WebCore/storage/IDBFactory.cpp @@ -57,7 +57,7 @@ IDBFactory::~IDBFactory() { } -PassRefPtr<IDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, const String& description, ExceptionCode& ec) +PassRefPtr<IDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, ExceptionCode& ec) { if (!context->isDocument()) { // FIXME: make this work with workers. @@ -71,14 +71,10 @@ PassRefPtr<IDBRequest> IDBFactory::open(ScriptExecutionContext* context, const S // FIXME: Raise a NON_TRANSIENT_ERR if the name is invalid. - if (description.isNull()) { - ec = IDBDatabaseException::NON_TRANSIENT_ERR; - return 0; - } RefPtr<IDBRequest> request = IDBRequest::create(document, IDBAny::create(this), 0); GroupSettings* groupSettings = document->page()->group().groupSettings(); - m_factoryBackend->open(name, description, request, document->securityOrigin(), document->frame(), groupSettings->indexedDBDatabasePath(), groupSettings->indexedDBQuotaBytes()); + m_factoryBackend->open(name, request, document->securityOrigin(), document->frame(), groupSettings->indexedDBDatabasePath(), groupSettings->indexedDBQuotaBytes()); return request; } diff --git a/WebCore/storage/IDBFactory.h b/WebCore/storage/IDBFactory.h index 8953245..cd0d64f 100644 --- a/WebCore/storage/IDBFactory.h +++ b/WebCore/storage/IDBFactory.h @@ -54,7 +54,7 @@ public: } ~IDBFactory(); - PassRefPtr<IDBRequest> open(ScriptExecutionContext*, const String& name, const String& description, ExceptionCode&); + PassRefPtr<IDBRequest> open(ScriptExecutionContext*, const String& name, ExceptionCode&); private: IDBFactory(IDBFactoryBackendInterface*); diff --git a/WebCore/storage/IDBFactory.idl b/WebCore/storage/IDBFactory.idl index 646df41..02eed0e 100644 --- a/WebCore/storage/IDBFactory.idl +++ b/WebCore/storage/IDBFactory.idl @@ -28,7 +28,7 @@ module storage { interface [ Conditional=INDEXED_DATABASE ] IDBFactory { - [CallWith=ScriptExecutionContext] IDBRequest open(in DOMString name, in [ConvertUndefinedOrNullToNullString] DOMString description) + [CallWith=ScriptExecutionContext] IDBRequest open(in DOMString name) raises (IDBDatabaseException); }; diff --git a/WebCore/storage/IDBFactoryBackendImpl.cpp b/WebCore/storage/IDBFactoryBackendImpl.cpp index e4d0ee8..1f6b22e 100644 --- a/WebCore/storage/IDBFactoryBackendImpl.cpp +++ b/WebCore/storage/IDBFactoryBackendImpl.cpp @@ -74,7 +74,7 @@ static PassRefPtr<IDBSQLiteDatabase> openSQLiteDatabase(SecurityOrigin* security return 0; } - path = pathByAppendingComponent(pathBase, IDBFactoryBackendImpl::databaseFileName(securityOrigin)); + path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb"); } RefPtr<IDBSQLiteDatabase> sqliteDatabase = IDBSQLiteDatabase::create(fileIdentifier, factory); @@ -122,14 +122,12 @@ static bool createTables(SQLiteDatabase& sqliteDatabase) return true; } -void IDBFactoryBackendImpl::open(const String& name, const String& description, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> securityOrigin, Frame*, const String& dataDir, int64_t maximumSize) +void IDBFactoryBackendImpl::open(const String& name, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> securityOrigin, Frame*, const String& dataDir, int64_t maximumSize) { String fileIdentifier = securityOrigin->databaseIdentifier(); String uniqueIdentifier = fileIdentifier + "@" + name; IDBDatabaseBackendMap::iterator it = m_databaseBackendMap.find(uniqueIdentifier); if (it != m_databaseBackendMap.end()) { - if (!description.isNull()) - it->second->setDescription(description); // The description may have changed. callbacks->onSuccess(it->second); return; } @@ -150,17 +148,11 @@ void IDBFactoryBackendImpl::open(const String& name, const String& description, m_sqliteDatabaseMap.set(fileIdentifier, sqliteDatabase.get()); } - RefPtr<IDBDatabaseBackendImpl> databaseBackend = IDBDatabaseBackendImpl::create(name, description, sqliteDatabase.get(), m_transactionCoordinator.get(), this, uniqueIdentifier); + RefPtr<IDBDatabaseBackendImpl> databaseBackend = IDBDatabaseBackendImpl::create(name, sqliteDatabase.get(), m_transactionCoordinator.get(), this, uniqueIdentifier); callbacks->onSuccess(databaseBackend.get()); m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.get()); } -String IDBFactoryBackendImpl::databaseFileName(SecurityOrigin* securityOrigin) -{ - String databaseIdentifier = securityOrigin->databaseIdentifier(); - return databaseIdentifier + ".indexeddb"; -} - } // namespace WebCore #endif // ENABLE(INDEXED_DATABASE) diff --git a/WebCore/storage/IDBFactoryBackendImpl.h b/WebCore/storage/IDBFactoryBackendImpl.h index d618fe2..dcaf848 100644 --- a/WebCore/storage/IDBFactoryBackendImpl.h +++ b/WebCore/storage/IDBFactoryBackendImpl.h @@ -54,9 +54,7 @@ public: void removeIDBDatabaseBackend(const String& uniqueIdentifier); void removeSQLiteDatabase(const String& uniqueIdentifier); - virtual void open(const String& name, const String& description, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize); - - static String databaseFileName(SecurityOrigin*); + virtual void open(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize); private: IDBFactoryBackendImpl(); diff --git a/WebCore/storage/IDBFactoryBackendInterface.h b/WebCore/storage/IDBFactoryBackendInterface.h index 445f9e9..166d517 100644 --- a/WebCore/storage/IDBFactoryBackendInterface.h +++ b/WebCore/storage/IDBFactoryBackendInterface.h @@ -51,7 +51,7 @@ public: static PassRefPtr<IDBFactoryBackendInterface> create(); virtual ~IDBFactoryBackendInterface(); - virtual void open(const String& name, const String& description, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize) = 0; + virtual void open(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize) = 0; }; } // namespace WebCore diff --git a/WebCore/storage/IDBIndex.cpp b/WebCore/storage/IDBIndex.cpp index a008470..8a38a27 100644 --- a/WebCore/storage/IDBIndex.cpp +++ b/WebCore/storage/IDBIndex.cpp @@ -29,6 +29,7 @@ #if ENABLE(INDEXED_DATABASE) #include "IDBCursorBackendInterface.h" +#include "IDBDatabaseException.h" #include "IDBIndexBackendInterface.h" #include "IDBKey.h" #include "IDBKeyRange.h" @@ -37,6 +38,8 @@ namespace WebCore { +static const unsigned short defaultDirection = IDBCursor::NEXT; + IDBIndex::IDBIndex(PassRefPtr<IDBIndexBackendInterface> backend, IDBTransactionBackendInterface* transaction) : m_backend(backend) , m_transaction(transaction) @@ -49,8 +52,19 @@ IDBIndex::~IDBIndex() { } -PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, ExceptionCode& ec) +PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, const OptionsObject& options, ExceptionCode& ec) { + RefPtr<IDBKeyRange> keyRange = options.getKeyKeyRange("range"); + + // Converted to an unsigned short. + int32_t direction = defaultDirection; + options.getKeyInt32("direction", direction); + if (direction != IDBCursor::NEXT && direction != IDBCursor::NEXT_NO_DUPLICATE && direction != IDBCursor::PREV && direction != IDBCursor::PREV_NO_DUPLICATE) { + // FIXME: May need to change when specced: http://www.w3.org/Bugs/Public/show_bug.cgi?id=11406 + ec = IDBDatabaseException::CONSTRAINT_ERR; + return 0; + } + RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); m_backend->openCursor(keyRange, direction, request, m_transaction.get(), ec); if (ec) @@ -58,8 +72,19 @@ PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, Pas return request; } -PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, ExceptionCode& ec) +PassRefPtr<IDBRequest> IDBIndex::openKeyCursor(ScriptExecutionContext* context, const OptionsObject& options, ExceptionCode& ec) { + RefPtr<IDBKeyRange> keyRange = options.getKeyKeyRange("range"); + + // Converted to an unsigned short. + int32_t direction = defaultDirection; + options.getKeyInt32("direction", direction); + if (direction != IDBCursor::NEXT && direction != IDBCursor::NEXT_NO_DUPLICATE && direction != IDBCursor::PREV && direction != IDBCursor::PREV_NO_DUPLICATE) { + // FIXME: May need to change when specced: http://www.w3.org/Bugs/Public/show_bug.cgi?id=11406 + ec = IDBDatabaseException::CONSTRAINT_ERR; + return 0; + } + RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); m_backend->openKeyCursor(keyRange, direction, request, m_transaction.get(), ec); if (ec) diff --git a/WebCore/storage/IDBIndex.h b/WebCore/storage/IDBIndex.h index 4a1a666..7f1aae3 100644 --- a/WebCore/storage/IDBIndex.h +++ b/WebCore/storage/IDBIndex.h @@ -30,6 +30,7 @@ #include "IDBIndexBackendInterface.h" #include "IDBKeyRange.h" #include "IDBRequest.h" +#include "OptionsObject.h" #include "PlatformString.h" #include <wtf/Forward.h> @@ -52,13 +53,11 @@ public: bool unique() const { return m_backend->unique(); } // FIXME: Try to modify the code generator so this is unneeded. - PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openCursor(context, 0, ec); } - PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) { return openCursor(context, keyRange, IDBCursor::NEXT, ec); } - PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openKeyCursor(context, 0, ec); } - PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) { return openKeyCursor(context, keyRange, IDBCursor::NEXT, ec); } + PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openCursor(context, OptionsObject(), ec); } + PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openKeyCursor(context, OptionsObject(), ec); } - PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, unsigned short direction, ExceptionCode&); - PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, unsigned short direction, ExceptionCode&); + PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, const OptionsObject&, ExceptionCode&); + PassRefPtr<IDBRequest> openKeyCursor(ScriptExecutionContext*, const OptionsObject&, ExceptionCode&); PassRefPtr<IDBRequest> get(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&); PassRefPtr<IDBRequest> getKey(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&); diff --git a/WebCore/storage/IDBIndex.idl b/WebCore/storage/IDBIndex.idl index 7c2c962..e6ba1e6 100644 --- a/WebCore/storage/IDBIndex.idl +++ b/WebCore/storage/IDBIndex.idl @@ -33,9 +33,9 @@ module storage { readonly attribute DOMString keyPath; readonly attribute boolean unique; - [CallWith=ScriptExecutionContext] IDBRequest openCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction) + [CallWith=ScriptExecutionContext] IDBRequest openCursor(in [Optional] OptionsObject options) raises (IDBDatabaseException); - [CallWith=ScriptExecutionContext] IDBRequest openKeyCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction) + [CallWith=ScriptExecutionContext] IDBRequest openKeyCursor(in [Optional] OptionsObject options) raises (IDBDatabaseException); [CallWith=ScriptExecutionContext] IDBRequest get(in IDBKey key) raises (IDBDatabaseException); diff --git a/WebCore/storage/IDBIndexBackendImpl.cpp b/WebCore/storage/IDBIndexBackendImpl.cpp index 84af234..597a8c2 100644 --- a/WebCore/storage/IDBIndexBackendImpl.cpp +++ b/WebCore/storage/IDBIndexBackendImpl.cpp @@ -73,13 +73,13 @@ void IDBIndexBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr + (objectCursor ? "ObjectStoreData.value " : "ObjectStoreData.keyString, ObjectStoreData.keyDate, ObjectStoreData.keyNumber ") + "FROM IndexData INNER JOIN ObjectStoreData ON IndexData.objectStoreDataId = ObjectStoreData.id WHERE "; - bool leftBound = range && (range->flags() & IDBKeyRange::LEFT_BOUND || range->flags() == IDBKeyRange::SINGLE); - bool rightBound = range && (range->flags() & IDBKeyRange::RIGHT_BOUND || range->flags() == IDBKeyRange::SINGLE); + bool lowerBound = range && range->lower(); + bool upperBound = range && range->upper(); - if (leftBound) - sql += range->left()->leftCursorWhereFragment(range->leftWhereClauseComparisonOperator(), "IndexData."); - if (rightBound) - sql += range->right()->rightCursorWhereFragment(range->rightWhereClauseComparisonOperator(), "IndexData."); + if (lowerBound) + sql += range->lower()->lowerCursorWhereFragment(range->lowerWhereClauseComparisonOperator(), "IndexData."); + if (upperBound) + sql += range->upper()->upperCursorWhereFragment(range->upperWhereClauseComparisonOperator(), "IndexData."); sql += "IndexData.indexId = ? ORDER BY "; IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(untypedDirection); @@ -93,10 +93,10 @@ void IDBIndexBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? int indexColumn = 1; - if (leftBound) - indexColumn += range->left()->bind(*query, indexColumn); - if (rightBound) - indexColumn += range->right()->bind(*query, indexColumn); + if (lowerBound) + indexColumn += range->lower()->bind(*query, indexColumn); + if (upperBound) + indexColumn += range->upper()->bind(*query, indexColumn); query->bindInt64(indexColumn, index->id()); if (query->step() != SQLResultRow) { diff --git a/WebCore/storage/IDBKey.cpp b/WebCore/storage/IDBKey.cpp index 8e411b7..4f8287a 100644 --- a/WebCore/storage/IDBKey.cpp +++ b/WebCore/storage/IDBKey.cpp @@ -105,7 +105,7 @@ String IDBKey::whereSyntax(String qualifiedTableName) const return ""; } -String IDBKey::leftCursorWhereFragment(String comparisonOperator, String qualifiedTableName) +String IDBKey::lowerCursorWhereFragment(String comparisonOperator, String qualifiedTableName) { switch (m_type) { case StringType: @@ -122,7 +122,7 @@ String IDBKey::leftCursorWhereFragment(String comparisonOperator, String qualifi return ""; } -String IDBKey::rightCursorWhereFragment(String comparisonOperator, String qualifiedTableName) +String IDBKey::upperCursorWhereFragment(String comparisonOperator, String qualifiedTableName) { switch (m_type) { case StringType: diff --git a/WebCore/storage/IDBKey.h b/WebCore/storage/IDBKey.h index 0303a38..9a27742 100644 --- a/WebCore/storage/IDBKey.h +++ b/WebCore/storage/IDBKey.h @@ -55,7 +55,7 @@ public: // In order of the least to the highest precedent in terms of sort order. enum Type { - NullType = 0, + NullType = 0, // FIXME: Phase out support for null keys. StringType, NumberType }; @@ -78,8 +78,8 @@ public: bool isEqual(IDBKey* other); String whereSyntax(String qualifiedTableName = "") const; - String leftCursorWhereFragment(String comparisonOperator, String qualifiedTableName = ""); - String rightCursorWhereFragment(String comparisonOperator, String qualifiedTableName = ""); + String lowerCursorWhereFragment(String comparisonOperator, String qualifiedTableName = ""); + String upperCursorWhereFragment(String comparisonOperator, String qualifiedTableName = ""); int bind(SQLiteStatement& query, int column) const; void bindWithNulls(SQLiteStatement& query, int baseColumn) const; diff --git a/WebCore/storage/IDBKeyRange.cpp b/WebCore/storage/IDBKeyRange.cpp index 6c612cc..142b3bd 100644 --- a/WebCore/storage/IDBKeyRange.cpp +++ b/WebCore/storage/IDBKeyRange.cpp @@ -32,73 +32,53 @@ namespace WebCore { -IDBKeyRange::IDBKeyRange(PassRefPtr<IDBKey> left, PassRefPtr<IDBKey> right, unsigned short flags) - : m_left(left) - , m_right(right) - , m_flags(flags) +IDBKeyRange::IDBKeyRange(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, bool lowerOpen, bool upperOpen) + : m_lower(lower) + , m_upper(upper) + , m_lowerOpen(lowerOpen) + , m_upperOpen(upperOpen) { } PassRefPtr<IDBKeyRange> IDBKeyRange::only(PassRefPtr<IDBKey> prpValue) { RefPtr<IDBKey> value = prpValue; - return IDBKeyRange::create(value, value, IDBKeyRange::SINGLE); + return IDBKeyRange::create(value, value, false, false); } -PassRefPtr<IDBKeyRange> IDBKeyRange::leftBound(PassRefPtr<IDBKey> bound, bool open) +PassRefPtr<IDBKeyRange> IDBKeyRange::lowerBound(PassRefPtr<IDBKey> bound, bool open) { - unsigned short flags = IDBKeyRange::LEFT_BOUND; - if (open) - flags |= IDBKeyRange::LEFT_OPEN; - return IDBKeyRange::create(bound, IDBKey::create(), flags); + return IDBKeyRange::create(bound, 0, open, false); } -PassRefPtr<IDBKeyRange> IDBKeyRange::rightBound(PassRefPtr<IDBKey> bound, bool open) +PassRefPtr<IDBKeyRange> IDBKeyRange::upperBound(PassRefPtr<IDBKey> bound, bool open) { - unsigned short flags = IDBKeyRange::RIGHT_BOUND; - if (open) - flags |= IDBKeyRange::RIGHT_OPEN; - return IDBKeyRange::create(IDBKey::create(), bound, flags); + return IDBKeyRange::create(0, bound, false, open); } -PassRefPtr<IDBKeyRange> IDBKeyRange::bound(PassRefPtr<IDBKey> left, PassRefPtr<IDBKey> right, bool openLeft, bool openRight) +PassRefPtr<IDBKeyRange> IDBKeyRange::bound(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, const OptionsObject& options) { - unsigned short flags = IDBKeyRange::LEFT_BOUND | IDBKeyRange::RIGHT_BOUND; - if (openLeft) - flags |= IDBKeyRange::LEFT_OPEN; - if (openRight) - flags |= IDBKeyRange::RIGHT_OPEN; - return IDBKeyRange::create(left, right, flags); + bool lowerOpen = false; + bool upperOpen = false; + options.getKeyBool("lowerOpen", lowerOpen); + options.getKeyBool("upperOpen", upperOpen); + return IDBKeyRange::create(lower, upper, lowerOpen, upperOpen); } -String IDBKeyRange::leftWhereClauseComparisonOperator() const +String IDBKeyRange::lowerWhereClauseComparisonOperator() const { - if (m_flags & LEFT_OPEN) + ASSERT(m_lower); + if (m_lowerOpen) return "<"; - - if (m_flags & LEFT_BOUND) - return "<="; - - if (m_flags == SINGLE) - return "="; - - ASSERT_NOT_REACHED(); - return ""; + return "<="; } -String IDBKeyRange::rightWhereClauseComparisonOperator() const +String IDBKeyRange::upperWhereClauseComparisonOperator() const { - if (m_flags & RIGHT_OPEN) + ASSERT(m_upper); + if (m_upperOpen) return "<"; - - if (m_flags & RIGHT_BOUND) - return "<="; - - if (m_flags == SINGLE) - return "="; - - ASSERT_NOT_REACHED(); - return ""; + return "<="; } } // namespace WebCore diff --git a/WebCore/storage/IDBKeyRange.h b/WebCore/storage/IDBKeyRange.h index d246ebc..8af48fe 100644 --- a/WebCore/storage/IDBKeyRange.h +++ b/WebCore/storage/IDBKeyRange.h @@ -29,6 +29,7 @@ #if ENABLE(INDEXED_DATABASE) #include "IDBKey.h" +#include "OptionsObject.h" #include <wtf/PassRefPtr.h> #include <wtf/Threading.h> @@ -36,41 +37,33 @@ namespace WebCore { class IDBKeyRange : public ThreadSafeShared<IDBKeyRange> { public: - // Keep in sync with what's in the .idl file. - enum Flags { - SINGLE = 0, - LEFT_OPEN = 1, - RIGHT_OPEN = 2, - LEFT_BOUND = 4, - RIGHT_BOUND = 8, - }; - - static PassRefPtr<IDBKeyRange> create(PassRefPtr<IDBKey> left, PassRefPtr<IDBKey> right, unsigned short flags) + static PassRefPtr<IDBKeyRange> create(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, bool lowerOpen, bool upperOpen) { - return adoptRef(new IDBKeyRange(left, right, flags)); + return adoptRef(new IDBKeyRange(lower, upper, lowerOpen, upperOpen)); } - ~IDBKeyRange() { } - PassRefPtr<IDBKey> left() const { return m_left; } - PassRefPtr<IDBKey> right() const { return m_right; } - unsigned short flags() const { return m_flags; } + PassRefPtr<IDBKey> lower() const { return m_lower; } + PassRefPtr<IDBKey> upper() const { return m_upper; } + bool lowerOpen() const { return m_lowerOpen; } + bool upperOpen() const { return m_upperOpen; } - String leftWhereClauseComparisonOperator() const; - String rightWhereClauseComparisonOperator() const; + String lowerWhereClauseComparisonOperator() const; + String upperWhereClauseComparisonOperator() const; static PassRefPtr<IDBKeyRange> only(PassRefPtr<IDBKey> value); - static PassRefPtr<IDBKeyRange> leftBound(PassRefPtr<IDBKey> bound, bool open = false); - static PassRefPtr<IDBKeyRange> rightBound(PassRefPtr<IDBKey> bound, bool open = false); - static PassRefPtr<IDBKeyRange> bound(PassRefPtr<IDBKey> left, PassRefPtr<IDBKey> right, bool openLeft = false, bool openRight = false); + static PassRefPtr<IDBKeyRange> lowerBound(PassRefPtr<IDBKey> bound, bool open = false); + static PassRefPtr<IDBKeyRange> upperBound(PassRefPtr<IDBKey> bound, bool open = false); + static PassRefPtr<IDBKeyRange> bound(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, const OptionsObject& = OptionsObject()); private: - IDBKeyRange(PassRefPtr<IDBKey> left, PassRefPtr<IDBKey> right, unsigned short flags); + IDBKeyRange(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, bool lowerOpen, bool upperOpen); - RefPtr<IDBKey> m_left; - RefPtr<IDBKey> m_right; - unsigned short m_flags; + RefPtr<IDBKey> m_lower; + RefPtr<IDBKey> m_upper; + bool m_lowerOpen; + bool m_upperOpen; }; } // namespace WebCore diff --git a/WebCore/storage/IDBKeyRange.idl b/WebCore/storage/IDBKeyRange.idl index 8e4d61f..d7fa075 100644 --- a/WebCore/storage/IDBKeyRange.idl +++ b/WebCore/storage/IDBKeyRange.idl @@ -28,22 +28,16 @@ module storage { interface [ Conditional=INDEXED_DATABASE ] IDBKeyRange { - // Keep in sync with what's in the .h file. - const unsigned short SINGLE = 0; - const unsigned short LEFT_OPEN = 1; - const unsigned short RIGHT_OPEN = 2; - const unsigned short LEFT_BOUND = 4; - const unsigned short RIGHT_BOUND = 8; - - readonly attribute IDBKey left; - readonly attribute IDBKey right; - readonly attribute unsigned short flags; + readonly attribute IDBKey lower; + readonly attribute IDBKey upper; + readonly attribute boolean lowerOpen; + readonly attribute boolean upperOpen; // FIXME: Make ClassMethod work for JSC as well. [ClassMethod] IDBKeyRange only(in IDBKey value); - [ClassMethod] IDBKeyRange leftBound(in IDBKey bound, in [Optional] boolean open); - [ClassMethod] IDBKeyRange rightBound(in IDBKey bound, in [Optional] boolean open); - [ClassMethod] IDBKeyRange bound(in IDBKey left, in IDBKey right, in [Optional] boolean openLeft, in [Optional] boolean openRight); + [ClassMethod] IDBKeyRange lowerBound(in IDBKey bound, in [Optional] boolean open); + [ClassMethod] IDBKeyRange upperBound(in IDBKey bound, in [Optional] boolean open); + [ClassMethod] IDBKeyRange bound(in IDBKey lower, in IDBKey upper, in [Optional] OptionsObject options); }; } diff --git a/WebCore/storage/IDBObjectStore.cpp b/WebCore/storage/IDBObjectStore.cpp index c30243e..ed5c96a 100644 --- a/WebCore/storage/IDBObjectStore.cpp +++ b/WebCore/storage/IDBObjectStore.cpp @@ -26,8 +26,11 @@ #include "config.h" #include "IDBObjectStore.h" +#if ENABLE(INDEXED_DATABASE) + #include "DOMStringList.h" #include "IDBAny.h" +#include "IDBDatabaseException.h" #include "IDBIndex.h" #include "IDBKey.h" #include "IDBKeyRange.h" @@ -35,10 +38,10 @@ #include "SerializedScriptValue.h" #include <wtf/UnusedParam.h> -#if ENABLE(INDEXED_DATABASE) - namespace WebCore { +static const unsigned short defaultDirection = IDBCursor::NEXT; + IDBObjectStore::IDBObjectStore(PassRefPtr<IDBObjectStoreBackendInterface> idbObjectStore, IDBTransactionBackendInterface* transaction) : m_objectStore(idbObjectStore) , m_transaction(transaction) @@ -91,17 +94,20 @@ PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, Pass return request; } -PassRefPtr<IDBRequest> IDBObjectStore::remove(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec) +PassRefPtr<IDBRequest> IDBObjectStore::deleteFunction(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec) { RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); - m_objectStore->remove(key, request, m_transaction.get(), ec); + m_objectStore->deleteFunction(key, request, m_transaction.get(), ec); if (ec) return 0; return request; } -PassRefPtr<IDBIndex> IDBObjectStore::createIndex(const String& name, const String& keyPath, bool unique, ExceptionCode& ec) +PassRefPtr<IDBIndex> IDBObjectStore::createIndex(const String& name, const String& keyPath, const OptionsObject& options, ExceptionCode& ec) { + bool unique = false; + options.getKeyBool("unique", unique); + RefPtr<IDBIndexBackendInterface> index = m_objectStore->createIndex(name, keyPath, unique, m_transaction.get(), ec); ASSERT(!index != !ec); // If we didn't get an index, we should have gotten an exception code. And vice versa. if (!index) @@ -118,13 +124,24 @@ PassRefPtr<IDBIndex> IDBObjectStore::index(const String& name, ExceptionCode& ec return IDBIndex::create(index.release(), m_transaction.get()); } -void IDBObjectStore::removeIndex(const String& name, ExceptionCode& ec) +void IDBObjectStore::deleteIndex(const String& name, ExceptionCode& ec) { - m_objectStore->removeIndex(name, m_transaction.get(), ec); + m_objectStore->deleteIndex(name, m_transaction.get(), ec); } -PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, unsigned short direction, ExceptionCode& ec) +PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, const OptionsObject& options, ExceptionCode& ec) { + RefPtr<IDBKeyRange> range = options.getKeyKeyRange("range"); + + // Converted to an unsigned short. + int32_t direction = defaultDirection; + options.getKeyInt32("direction", direction); + if (direction != IDBCursor::NEXT && direction != IDBCursor::NEXT_NO_DUPLICATE && direction != IDBCursor::PREV && direction != IDBCursor::PREV_NO_DUPLICATE) { + // FIXME: May need to change when specced: http://www.w3.org/Bugs/Public/show_bug.cgi?id=11406 + ec = IDBDatabaseException::CONSTRAINT_ERR; + return 0; + } + RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); m_objectStore->openCursor(range, direction, request, m_transaction.get(), ec); if (ec) diff --git a/WebCore/storage/IDBObjectStore.h b/WebCore/storage/IDBObjectStore.h index dc92233..0e9a4a9 100644 --- a/WebCore/storage/IDBObjectStore.h +++ b/WebCore/storage/IDBObjectStore.h @@ -32,6 +32,7 @@ #include "IDBKeyRange.h" #include "IDBObjectStoreBackendInterface.h" #include "IDBRequest.h" +#include "OptionsObject.h" #include "PlatformString.h" #include "SerializedScriptValue.h" #include <wtf/PassRefPtr.h> @@ -61,20 +62,19 @@ public: // FIXME: Try to modify the code generator so this is unneeded. PassRefPtr<IDBRequest> add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, ExceptionCode& ec) { return add(context, value, 0, ec); } PassRefPtr<IDBRequest> put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, ExceptionCode& ec) { return put(context, value, 0, ec); } - PassRefPtr<IDBIndex> createIndex(const String& name, const String& keyPath, ExceptionCode& ec) { return createIndex(name, keyPath, false, ec); } - PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openCursor(context, 0, ec); } - PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) { return openCursor(context, keyRange, IDBCursor::NEXT, ec); } + PassRefPtr<IDBIndex> createIndex(const String& name, const String& keyPath, ExceptionCode& ec) { return createIndex(name, keyPath, OptionsObject(), ec); } + PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openCursor(context, OptionsObject(), ec); } PassRefPtr<IDBRequest> get(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&); PassRefPtr<IDBRequest> add(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, ExceptionCode&); PassRefPtr<IDBRequest> put(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, ExceptionCode&); - PassRefPtr<IDBRequest> remove(ScriptExecutionContext*, PassRefPtr<IDBKey> key, ExceptionCode&); + PassRefPtr<IDBRequest> deleteFunction(ScriptExecutionContext*, PassRefPtr<IDBKey> key, ExceptionCode&); - PassRefPtr<IDBIndex> createIndex(const String& name, const String& keyPath, bool unique, ExceptionCode&); + PassRefPtr<IDBIndex> createIndex(const String& name, const String& keyPath, const OptionsObject&, ExceptionCode&); PassRefPtr<IDBIndex> index(const String& name, ExceptionCode&); - void removeIndex(const String& name, ExceptionCode&); + void deleteIndex(const String& name, ExceptionCode&); - PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, unsigned short direction, ExceptionCode&); + PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, const OptionsObject&, ExceptionCode&); private: IDBObjectStore(PassRefPtr<IDBObjectStoreBackendInterface>, IDBTransactionBackendInterface* transaction); diff --git a/WebCore/storage/IDBObjectStore.idl b/WebCore/storage/IDBObjectStore.idl index 31eb865..f023dbe 100644 --- a/WebCore/storage/IDBObjectStore.idl +++ b/WebCore/storage/IDBObjectStore.idl @@ -36,17 +36,17 @@ module storage { raises (IDBDatabaseException); [CallWith=ScriptExecutionContext] IDBRequest add(in SerializedScriptValue value, in [Optional] IDBKey key) raises (IDBDatabaseException); - [CallWith=ScriptExecutionContext] IDBRequest remove(in IDBKey key) + [CallWith=ScriptExecutionContext, ImplementationFunction=deleteFunction] IDBRequest delete(in IDBKey key) raises (IDBDatabaseException); [CallWith=ScriptExecutionContext] IDBRequest get(in IDBKey key) raises (IDBDatabaseException); - [CallWith=ScriptExecutionContext] IDBRequest openCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction) + [CallWith=ScriptExecutionContext] IDBRequest openCursor(in [Optional] OptionsObject options) raises (IDBDatabaseException); - IDBIndex createIndex(in DOMString name, in [ConvertNullToNullString] DOMString keyPath, in [Optional] boolean unique) + IDBIndex createIndex(in DOMString name, in [ConvertNullToNullString] DOMString keyPath, in [Optional] OptionsObject options) raises (IDBDatabaseException); IDBIndex index(in DOMString name) raises (IDBDatabaseException); - void removeIndex(in DOMString name) + void deleteIndex(in DOMString name) raises (IDBDatabaseException); }; } diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.cpp b/WebCore/storage/IDBObjectStoreBackendImpl.cpp index 653fb4e..fb08e37 100644 --- a/WebCore/storage/IDBObjectStoreBackendImpl.cpp +++ b/WebCore/storage/IDBObjectStoreBackendImpl.cpp @@ -211,6 +211,10 @@ void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr< callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied.")); return; } + if (key->type() == IDBKey::NullType) { + callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "NULL key is not allowed.")); + return; + } Vector<RefPtr<IDBKey> > indexKeys; for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) { @@ -219,6 +223,10 @@ void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr< callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from an index's keyPath.")); return; } + if (key->type() == IDBKey::NullType) { + callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "One of the derived (from a keyPath) keys for an index is NULL.")); + return; + } if (!it->second->addingKeyAllowed(key.get())) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "One of the derived (from a keyPath) keys for an index does not satisfy its uniqueness requirements.")); return; @@ -267,16 +275,16 @@ void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr< callbacks->onSuccess(key.get()); } -void IDBObjectStoreBackendImpl::remove(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec) +void IDBObjectStoreBackendImpl::deleteFunction(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec) { RefPtr<IDBObjectStoreBackendImpl> objectStore = this; RefPtr<IDBKey> key = prpKey; RefPtr<IDBCallbacks> callbacks = prpCallbacks; - if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::removeInternal, objectStore, key, callbacks))) + if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::deleteInternal, objectStore, key, callbacks))) ec = IDBDatabaseException::NOT_ALLOWED_ERR; } -void IDBObjectStoreBackendImpl::removeInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks) +void IDBObjectStoreBackendImpl::deleteInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks) { SQLiteStatement query(objectStore->sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key.get())); bool ok = query.prepare() == SQLResultOk; @@ -357,7 +365,7 @@ static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id) ASSERT_UNUSED(ok, ok); // FIXME: Better error handling. } -void IDBObjectStoreBackendImpl::removeIndex(const String& name, IDBTransactionBackendInterface* transaction, ExceptionCode& ec) +void IDBObjectStoreBackendImpl::deleteIndex(const String& name, IDBTransactionBackendInterface* transaction, ExceptionCode& ec) { RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name); if (!index) { @@ -367,7 +375,7 @@ void IDBObjectStoreBackendImpl::removeIndex(const String& name, IDBTransactionBa RefPtr<IDBObjectStoreBackendImpl> objectStore = this; RefPtr<IDBTransactionBackendInterface> transactionPtr = transaction; - if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::removeIndexInternal, objectStore, index, transactionPtr), + if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::deleteIndexInternal, objectStore, index, transactionPtr), createCallbackTask(&IDBObjectStoreBackendImpl::addIndexToMap, objectStore, index))) { ec = IDBDatabaseException::NOT_ALLOWED_ERR; return; @@ -375,7 +383,7 @@ void IDBObjectStoreBackendImpl::removeIndex(const String& name, IDBTransactionBa m_indexes.remove(name); } -void IDBObjectStoreBackendImpl::removeIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction) +void IDBObjectStoreBackendImpl::deleteIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBTransactionBackendInterface> transaction) { doDelete(objectStore->sqliteDatabase(), "DELETE FROM Indexes WHERE id = ?", index->id()); doDelete(objectStore->sqliteDatabase(), "DELETE FROM IndexData WHERE indexId = ?", index->id()); @@ -395,15 +403,15 @@ void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, uns void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> range, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction) { - bool leftBound = range && (range->flags() & IDBKeyRange::LEFT_BOUND || range->flags() == IDBKeyRange::SINGLE); - bool rightBound = range && (range->flags() & IDBKeyRange::RIGHT_BOUND || range->flags() == IDBKeyRange::SINGLE); + bool lowerBound = range && range->lower(); + bool upperBound = range && range->upper(); // Several files depend on this order of selects. String sql = "SELECT id, keyString, keyDate, keyNumber, value FROM ObjectStoreData WHERE "; - if (leftBound) - sql += range->left()->leftCursorWhereFragment(range->leftWhereClauseComparisonOperator()); - if (rightBound) - sql += range->right()->rightCursorWhereFragment(range->rightWhereClauseComparisonOperator()); + if (lowerBound) + sql += range->lower()->lowerCursorWhereFragment(range->lowerWhereClauseComparisonOperator()); + if (upperBound) + sql += range->upper()->upperCursorWhereFragment(range->upperWhereClauseComparisonOperator()); sql += "objectStoreId = ? ORDER BY "; IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(tmpDirection); @@ -417,10 +425,10 @@ void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, Pass ASSERT_UNUSED(ok, ok); // FIXME: Better error handling? int currentColumn = 1; - if (leftBound) - currentColumn += range->left()->bind(*query, currentColumn); - if (rightBound) - currentColumn += range->right()->bind(*query, currentColumn); + if (lowerBound) + currentColumn += range->lower()->bind(*query, currentColumn); + if (upperBound) + currentColumn += range->upper()->bind(*query, currentColumn); query->bindInt64(currentColumn, objectStore->id()); if (query->step() != SQLResultRow) { diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.h b/WebCore/storage/IDBObjectStoreBackendImpl.h index add849b..2ab42f2 100644 --- a/WebCore/storage/IDBObjectStoreBackendImpl.h +++ b/WebCore/storage/IDBObjectStoreBackendImpl.h @@ -68,11 +68,11 @@ public: virtual void get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&); virtual void put(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&); - virtual void remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&); + virtual void deleteFunction(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&); virtual PassRefPtr<IDBIndexBackendInterface> createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface*, ExceptionCode&); virtual PassRefPtr<IDBIndexBackendInterface> index(const String& name, ExceptionCode&); - virtual void removeIndex(const String& name, IDBTransactionBackendInterface*, ExceptionCode&); + virtual void deleteIndex(const String& name, IDBTransactionBackendInterface*, ExceptionCode&); virtual void openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&); @@ -85,9 +85,9 @@ private: static void getInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>); static void putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>); - static void removeInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>); + static void deleteInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>); static void createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBTransactionBackendInterface>); - static void removeIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBTransactionBackendInterface>); + static void deleteIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBTransactionBackendInterface>); static void openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>); // These are used as setVersion transaction abort tasks. diff --git a/WebCore/storage/IDBObjectStoreBackendInterface.h b/WebCore/storage/IDBObjectStoreBackendInterface.h index 8763d90..02ceb27 100644 --- a/WebCore/storage/IDBObjectStoreBackendInterface.h +++ b/WebCore/storage/IDBObjectStoreBackendInterface.h @@ -52,11 +52,11 @@ public: virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0; virtual void put(PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, bool addOnly, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0; - virtual void remove(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0; + virtual void deleteFunction(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0; virtual PassRefPtr<IDBIndexBackendInterface> createIndex(const String& name, const String& keyPath, bool unique, IDBTransactionBackendInterface*, ExceptionCode&) = 0; virtual PassRefPtr<IDBIndexBackendInterface> index(const String& name, ExceptionCode&) = 0; - virtual void removeIndex(const String& name, IDBTransactionBackendInterface*, ExceptionCode&) = 0; + virtual void deleteIndex(const String& name, IDBTransactionBackendInterface*, ExceptionCode&) = 0; virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0; }; diff --git a/WebCore/storage/IDBTransaction.cpp b/WebCore/storage/IDBTransaction.cpp index 334c001..e3625d4 100644 --- a/WebCore/storage/IDBTransaction.cpp +++ b/WebCore/storage/IDBTransaction.cpp @@ -75,9 +75,9 @@ PassRefPtr<IDBObjectStore> IDBTransaction::objectStore(const String& name, Excep ec = IDBDatabaseException::NOT_ALLOWED_ERR; return 0; } - RefPtr<IDBObjectStoreBackendInterface> objectStoreBackend = m_backend->objectStore(name); + RefPtr<IDBObjectStoreBackendInterface> objectStoreBackend = m_backend->objectStore(name, ec); if (!objectStoreBackend) { - ec = IDBDatabaseException::NOT_ALLOWED_ERR; + ASSERT(ec); return 0; } RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(objectStoreBackend, m_backend.get()); diff --git a/WebCore/storage/IDBTransaction.h b/WebCore/storage/IDBTransaction.h index 8db5205..d0a9f0f 100644 --- a/WebCore/storage/IDBTransaction.h +++ b/WebCore/storage/IDBTransaction.h @@ -54,8 +54,7 @@ public: enum Mode { READ_WRITE = 0, READ_ONLY = 1, - SNAPSHOT_READ = 2, - VERSION_CHANGE = 3 + VERSION_CHANGE = 2 }; unsigned short mode() const; diff --git a/WebCore/storage/IDBTransaction.idl b/WebCore/storage/IDBTransaction.idl index cdf9f63..b57ac4a 100644 --- a/WebCore/storage/IDBTransaction.idl +++ b/WebCore/storage/IDBTransaction.idl @@ -32,8 +32,7 @@ module storage { // Modes const unsigned short READ_WRITE = 0; const unsigned short READ_ONLY = 1; - const unsigned short SNAPSHOT_READ = 2; - const unsigned short VERSION_CHANGE = 3; + const unsigned short VERSION_CHANGE = 2; // Properties readonly attribute unsigned short mode; diff --git a/WebCore/storage/IDBTransactionBackendImpl.cpp b/WebCore/storage/IDBTransactionBackendImpl.cpp index e8d864d..336724a 100644 --- a/WebCore/storage/IDBTransactionBackendImpl.cpp +++ b/WebCore/storage/IDBTransactionBackendImpl.cpp @@ -29,6 +29,7 @@ #if ENABLE(INDEXED_DATABASE) #include "IDBDatabaseBackendImpl.h" +#include "IDBDatabaseException.h" #include "IDBTransactionCoordinator.h" #include "SQLiteDatabase.h" @@ -50,6 +51,7 @@ IDBTransactionBackendImpl::IDBTransactionBackendImpl(DOMStringList* objectStores , m_taskEventTimer(this, &IDBTransactionBackendImpl::taskEventTimerFired) , m_pendingEvents(0) { + ASSERT(m_objectStoreNames); m_database->transactionCoordinator()->didCreateTransaction(this); } @@ -59,11 +61,29 @@ IDBTransactionBackendImpl::~IDBTransactionBackendImpl() ASSERT(m_state == Finished); } -PassRefPtr<IDBObjectStoreBackendInterface> IDBTransactionBackendImpl::objectStore(const String& name) +PassRefPtr<IDBObjectStoreBackendInterface> IDBTransactionBackendImpl::objectStore(const String& name, ExceptionCode& ec) { - if (m_state == Finished) + if (m_state == Finished) { + ec = IDBDatabaseException::NOT_ALLOWED_ERR; + return 0; + } + + // Does a linear search, but it really shouldn't be that slow in practice. + if (!m_objectStoreNames->isEmpty() && !m_objectStoreNames->contains(name)) { + ec = IDBDatabaseException::NOT_FOUND_ERR; return 0; - return m_database->objectStore(name); + } + + RefPtr<IDBObjectStoreBackendInterface> objectStore = m_database->objectStore(name); + // FIXME: This is only necessary right now beacuse a setVersion transaction could modify things + // between its creation (where another check occurs) and the .objectStore call. + // There's a bug to make this impossible in the spec. When we make it impossible here, we + // can remove this check. + if (!objectStore) { + ec = IDBDatabaseException::NOT_FOUND_ERR; + return 0; + } + return objectStore.release(); } bool IDBTransactionBackendImpl::scheduleTask(PassOwnPtr<ScriptExecutionContext::Task> task, PassOwnPtr<ScriptExecutionContext::Task> abortTask) diff --git a/WebCore/storage/IDBTransactionBackendImpl.h b/WebCore/storage/IDBTransactionBackendImpl.h index 88542f4..f4dfaa8 100644 --- a/WebCore/storage/IDBTransactionBackendImpl.h +++ b/WebCore/storage/IDBTransactionBackendImpl.h @@ -45,7 +45,7 @@ public: static PassRefPtr<IDBTransactionBackendImpl> create(DOMStringList* objectStores, unsigned short mode, unsigned long timeout, IDBDatabaseBackendImpl*); virtual ~IDBTransactionBackendImpl(); - virtual PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name); + virtual PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name, ExceptionCode&); virtual unsigned short mode() const { return m_mode; } virtual bool scheduleTask(PassOwnPtr<ScriptExecutionContext::Task> task, PassOwnPtr<ScriptExecutionContext::Task> abortTask); virtual void didCompleteTaskEvents(); diff --git a/WebCore/storage/IDBTransactionBackendInterface.h b/WebCore/storage/IDBTransactionBackendInterface.h index 80135f0..9b1fce6 100644 --- a/WebCore/storage/IDBTransactionBackendInterface.h +++ b/WebCore/storage/IDBTransactionBackendInterface.h @@ -48,7 +48,7 @@ class IDBTransactionBackendInterface : public ThreadSafeShared<IDBTransactionBac public: virtual ~IDBTransactionBackendInterface() { } - virtual PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name) = 0; + virtual PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name, ExceptionCode&) = 0; virtual unsigned short mode() const = 0; virtual bool scheduleTask(PassOwnPtr<ScriptExecutionContext::Task> task, PassOwnPtr<ScriptExecutionContext::Task> abortTask = 0) = 0; virtual void didCompleteTaskEvents() = 0; diff --git a/WebCore/storage/Storage.cpp b/WebCore/storage/Storage.cpp index 0a8eed7..0259ca4 100644 --- a/WebCore/storage/Storage.cpp +++ b/WebCore/storage/Storage.cpp @@ -28,6 +28,9 @@ #if ENABLE(DOM_STORAGE) +#include "Frame.h" +#include "Page.h" +#include "Settings.h" #include "StorageArea.h" #include "PlatformString.h" #include <wtf/PassRefPtr.h> @@ -53,7 +56,7 @@ Storage::~Storage() unsigned Storage::length() const { - if (!m_frame) + if (!m_frame || !m_frame->page() || m_frame->page()->settings()->privateBrowsingEnabled()) return 0; return m_storageArea->length(); @@ -61,7 +64,7 @@ unsigned Storage::length() const String Storage::key(unsigned index) const { - if (!m_frame) + if (!m_frame || !m_frame->page() || m_frame->page()->settings()->privateBrowsingEnabled()) return String(); return m_storageArea->key(index); @@ -69,7 +72,7 @@ String Storage::key(unsigned index) const String Storage::getItem(const String& key) const { - if (!m_frame) + if (!m_frame || !m_frame->page() || m_frame->page()->settings()->privateBrowsingEnabled()) return String(); return m_storageArea->getItem(key); @@ -102,7 +105,7 @@ void Storage::clear() bool Storage::contains(const String& key) const { - if (!m_frame) + if (!m_frame || !m_frame->page() || m_frame->page()->settings()->privateBrowsingEnabled()) return false; return m_storageArea->contains(key); |