diff options
Diffstat (limited to 'WebCore/storage')
40 files changed, 689 insertions, 255 deletions
diff --git a/WebCore/storage/ChangeVersionWrapper.cpp b/WebCore/storage/ChangeVersionWrapper.cpp index 17a9407..66ca63f 100644 --- a/WebCore/storage/ChangeVersionWrapper.cpp +++ b/WebCore/storage/ChangeVersionWrapper.cpp @@ -30,6 +30,9 @@ #if ENABLE(DATABASE) #include "Database.h" +#include "SQLError.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> namespace WebCore { diff --git a/WebCore/storage/ChangeVersionWrapper.h b/WebCore/storage/ChangeVersionWrapper.h index b14fe55..86cc182 100644 --- a/WebCore/storage/ChangeVersionWrapper.h +++ b/WebCore/storage/ChangeVersionWrapper.h @@ -32,9 +32,12 @@ #include "PlatformString.h" #include "SQLTransaction.h" +#include <wtf/Forward.h> namespace WebCore { +class SQLError; + class ChangeVersionWrapper : public SQLTransactionWrapper { public: static PassRefPtr<ChangeVersionWrapper> create(const String& oldVersion, const String& newVersion) { return adoptRef(new ChangeVersionWrapper(oldVersion, newVersion)); } diff --git a/WebCore/storage/Database.cpp b/WebCore/storage/Database.cpp index 0644df5..c96dfba 100644 --- a/WebCore/storage/Database.cpp +++ b/WebCore/storage/Database.cpp @@ -29,8 +29,6 @@ #include "config.h" #include "Database.h" -#include <wtf/StdLibExtras.h> - #if ENABLE(DATABASE) #include "ChangeVersionWrapper.h" #include "DatabaseAuthorizer.h" @@ -40,21 +38,25 @@ #include "DatabaseTracker.h" #include "Document.h" #include "ExceptionCode.h" -#include "Frame.h" #include "InspectorController.h" #include "Logging.h" #include "NotImplemented.h" #include "Page.h" -#include "OriginQuotaManager.h" -#include "ScriptController.h" -#include "SQLiteDatabase.h" -#include "SQLiteFileSystem.h" -#include "SQLiteStatement.h" -#include "SQLResultSet.h" +#include "SQLTransactionCallback.h" #include "SQLTransactionClient.h" #include "SQLTransactionCoordinator.h" - -#endif // ENABLE(DATABASE) +#include "SQLTransactionErrorCallback.h" +#include "SQLiteStatement.h" +#include "ScriptController.h" +#include "ScriptExecutionContext.h" +#include "SecurityOrigin.h" +#include "StringHash.h" +#include "VoidCallback.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/StdLibExtras.h> #if USE(JSC) #include "JSDOMWindow.h" @@ -71,8 +73,6 @@ const String& Database::databaseInfoTableName() return name; } -#if ENABLE(DATABASE) - static bool isDatabaseAvailable = true; void Database::setIsAvailable(bool available) @@ -213,8 +213,8 @@ Database::Database(ScriptExecutionContext* context, const String& name, const St , m_creationCallback(creationCallback) { ASSERT(m_scriptExecutionContext.get()); - m_mainThreadSecurityOrigin = m_scriptExecutionContext->securityOrigin(); - m_databaseThreadSecurityOrigin = m_mainThreadSecurityOrigin->threadsafeCopy(); + m_contextThreadSecurityOrigin = m_scriptExecutionContext->securityOrigin(); + m_databaseThreadSecurityOrigin = m_contextThreadSecurityOrigin->threadsafeCopy(); if (m_name.isNull()) m_name = ""; @@ -491,6 +491,30 @@ void Database::setAuthorizerReadOnly() m_databaseAuthorizer->setReadOnly(); } +bool Database::lastActionChangedDatabase() +{ + ASSERT(m_databaseAuthorizer); + return m_databaseAuthorizer->lastActionChangedDatabase(); +} + +bool Database::lastActionWasInsert() +{ + ASSERT(m_databaseAuthorizer); + return m_databaseAuthorizer->lastActionWasInsert(); +} + +void Database::resetDeletes() +{ + ASSERT(m_databaseAuthorizer); + m_databaseAuthorizer->resetDeletes(); +} + +bool Database::hadDeletes() +{ + ASSERT(m_databaseAuthorizer); + return m_databaseAuthorizer->hadDeletes(); +} + static int guidForOriginAndName(const String& origin, const String& name) { String stringID; @@ -643,14 +667,20 @@ void Database::transaction(PassRefPtr<SQLTransactionCallback> callback, PassRefP scheduleTransaction(); } +void Database::inProgressTransactionCompleted() +{ + MutexLocker locker(m_transactionInProgressMutex); + m_transactionInProgress = false; + scheduleTransaction(); +} + void Database::scheduleTransaction() { ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller. RefPtr<SQLTransaction> transaction; if (m_isTransactionQueueEnabled && !m_transactionQueue.isEmpty()) { - transaction = m_transactionQueue.first(); - m_transactionQueue.removeFirst(); + transaction = m_transactionQueue.takeFirst(); } if (transaction && m_scriptExecutionContext->databaseThread()) { @@ -780,8 +810,8 @@ void Database::setExpectedVersion(const String& version) SecurityOrigin* Database::securityOrigin() const { - if (scriptExecutionContext()->isContextThread()) - return m_mainThreadSecurityOrigin.get(); + if (m_scriptExecutionContext->isContextThread()) + return m_contextThreadSecurityOrigin.get(); if (currentThread() == m_scriptExecutionContext->databaseThread()->getThreadID()) return m_databaseThreadSecurityOrigin.get(); return 0; @@ -818,6 +848,6 @@ void Database::incrementalVacuumIfNeeded() m_sqliteDatabase.runIncrementalVacuumCommand(); } -#endif // ENABLE(DATABASE) - } // namespace WebCore + +#endif // ENABLE(DATABASE) diff --git a/WebCore/storage/Database.h b/WebCore/storage/Database.h index 890d98c..f9fd3cd 100644 --- a/WebCore/storage/Database.h +++ b/WebCore/storage/Database.h @@ -31,42 +31,31 @@ #if ENABLE(DATABASE) #include "PlatformString.h" -#include "SecurityOrigin.h" #include "SQLiteDatabase.h" -#include "SQLTransaction.h" -#include "StringHash.h" -#include "Timer.h" -#include "VoidCallback.h" +#ifndef NDEBUG +#include "SecurityOrigin.h" +#endif -#include <wtf/Forward.h> -#include <wtf/HashSet.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> #include <wtf/Deque.h> -#else -#include "PlatformString.h" -#endif +#include <wtf/Forward.h> -#if ENABLE(DATABASE) namespace WebCore { class DatabaseAuthorizer; class DatabaseCallback; class DatabaseThread; class ScriptExecutionContext; -class SQLResultSet; +class SecurityOrigin; +class SQLTransaction; class SQLTransactionCallback; class SQLTransactionClient; class SQLTransactionCoordinator; class SQLTransactionErrorCallback; -class SQLValue; +class VoidCallback; typedef int ExceptionCode; class Database : public ThreadSafeShared<Database> { - friend class DatabaseTransactionTask; - friend class SQLStatement; - friend class SQLTransaction; public: static void setIsAvailable(bool); static bool isAvailable(); @@ -74,15 +63,12 @@ public: ~Database(); // Direct support for the DOM API - static PassRefPtr<Database> openDatabase(ScriptExecutionContext* context, const String& name, - const String& expectedVersion, const String& displayName, - unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, - ExceptionCode&); + static PassRefPtr<Database> openDatabase(ScriptExecutionContext*, const String& name, const String& expectedVersion, const String& displayName, + unsigned long estimatedSize, PassRefPtr<DatabaseCallback>, ExceptionCode&); String version() const; - void changeVersion(const String& oldVersion, const String& newVersion, - PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback, - PassRefPtr<VoidCallback> successCallback); - void transaction(PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback, + void changeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<SQLTransactionCallback>, + PassRefPtr<SQLTransactionErrorCallback>, PassRefPtr<VoidCallback> successCallback); + void transaction(PassRefPtr<SQLTransactionCallback>, PassRefPtr<SQLTransactionErrorCallback>, PassRefPtr<VoidCallback> successCallback, bool readOnly); // Internal engine support @@ -91,11 +77,16 @@ public: void disableAuthorizer(); void enableAuthorizer(); void setAuthorizerReadOnly(); + bool lastActionChangedDatabase(); + bool lastActionWasInsert(); + void resetDeletes(); + bool hadDeletes(); Vector<String> tableNames(); ScriptExecutionContext* scriptExecutionContext() const { return m_scriptExecutionContext.get(); } SecurityOrigin* securityOrigin() const; + SQLiteDatabase& sqliteDatabase() { return m_sqliteDatabase; } String stringIdentifier() const; String displayName() const; unsigned long estimatedSize() const; @@ -127,6 +118,10 @@ public: bool performOpenAndVerify(ExceptionCode&); + void inProgressTransactionCompleted(); + void scheduleTransactionCallback(SQLTransaction*); + void scheduleTransactionStep(SQLTransaction*, bool immediately = false); + Vector<String> performGetTableNames(); void performCreationCallback(); @@ -136,15 +131,12 @@ public: void incrementalVacuumIfNeeded(); private: - Database(ScriptExecutionContext* context, const String& name, - const String& expectedVersion, const String& displayName, - unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback); + Database(ScriptExecutionContext*, const String& name, const String& expectedVersion, + const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback>); bool openAndVerifyVersion(ExceptionCode&); void scheduleTransaction(); - void scheduleTransactionCallback(SQLTransaction*); - void scheduleTransactionStep(SQLTransaction* transaction, bool immediately = false); Deque<RefPtr<SQLTransaction> > m_transactionQueue; Mutex m_transactionInProgressMutex; @@ -154,7 +146,7 @@ private: static void deliverPendingCallback(void*); RefPtr<ScriptExecutionContext> m_scriptExecutionContext; - RefPtr<SecurityOrigin> m_mainThreadSecurityOrigin; + RefPtr<SecurityOrigin> m_contextThreadSecurityOrigin; RefPtr<SecurityOrigin> m_databaseThreadSecurityOrigin; String m_name; int m_guid; @@ -177,21 +169,12 @@ private: RefPtr<DatabaseCallback> m_creationCallback; #ifndef NDEBUG - String databaseDebugName() const { return m_mainThreadSecurityOrigin->toString() + "::" + m_name; } + String databaseDebugName() const { return m_contextThreadSecurityOrigin->toString() + "::" + m_name; } #endif }; } // namespace WebCore -#else - -namespace WebCore { -class Database : public ThreadSafeShared<Database> { -public: - static const String& databaseInfoTableName(); -}; -} // namespace WebCore - #endif // ENABLE(DATABASE) #endif // Database_h diff --git a/WebCore/storage/DatabaseAuthorizer.cpp b/WebCore/storage/DatabaseAuthorizer.cpp index 05d9a66..1ea99d9 100644 --- a/WebCore/storage/DatabaseAuthorizer.cpp +++ b/WebCore/storage/DatabaseAuthorizer.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "DatabaseAuthorizer.h" +#if ENABLE(DATABASE) #include "Database.h" #include "PlatformString.h" @@ -48,6 +49,11 @@ void DatabaseAuthorizer::reset() m_readOnly = false; } +void DatabaseAuthorizer::resetDeletes() +{ + m_hadDeletes = false; +} + void DatabaseAuthorizer::addWhitelistedFunctions() { // SQLite functions used to help implement some operations @@ -137,7 +143,7 @@ int DatabaseAuthorizer::dropTable(const String& tableName) if (m_readOnly && m_securityEnabled) return SQLAuthDeny; - return denyBasedOnTableName(tableName); + return updateDeletesBasedOnTableName(tableName); } int DatabaseAuthorizer::dropTempTable(const String& tableName) @@ -148,7 +154,7 @@ int DatabaseAuthorizer::dropTempTable(const String& tableName) if (m_readOnly && m_securityEnabled) return SQLAuthDeny; - return denyBasedOnTableName(tableName); + return updateDeletesBasedOnTableName(tableName); } int DatabaseAuthorizer::allowAlterTable(const String&, const String& tableName) @@ -185,7 +191,7 @@ int DatabaseAuthorizer::dropIndex(const String&, const String& tableName) if (m_readOnly && m_securityEnabled) return SQLAuthDeny; - return denyBasedOnTableName(tableName); + return updateDeletesBasedOnTableName(tableName); } int DatabaseAuthorizer::dropTempIndex(const String&, const String& tableName) @@ -196,7 +202,7 @@ int DatabaseAuthorizer::dropTempIndex(const String&, const String& tableName) if (m_readOnly && m_securityEnabled) return SQLAuthDeny; - return denyBasedOnTableName(tableName); + return updateDeletesBasedOnTableName(tableName); } int DatabaseAuthorizer::createTrigger(const String&, const String& tableName) @@ -224,7 +230,7 @@ int DatabaseAuthorizer::dropTrigger(const String&, const String& tableName) if (m_readOnly && m_securityEnabled) return SQLAuthDeny; - return denyBasedOnTableName(tableName); + return updateDeletesBasedOnTableName(tableName); } int DatabaseAuthorizer::dropTempTrigger(const String&, const String& tableName) @@ -235,7 +241,7 @@ int DatabaseAuthorizer::dropTempTrigger(const String&, const String& tableName) if (m_readOnly && m_securityEnabled) return SQLAuthDeny; - return denyBasedOnTableName(tableName); + return updateDeletesBasedOnTableName(tableName); } int DatabaseAuthorizer::createView(const String&) @@ -253,7 +259,11 @@ int DatabaseAuthorizer::createTempView(const String&) int DatabaseAuthorizer::dropView(const String&) { - return (m_readOnly && m_securityEnabled ? SQLAuthDeny : SQLAuthAllow); + if (m_readOnly && m_securityEnabled) + return SQLAuthDeny; + + m_hadDeletes = true; + return SQLAuthAllow; } int DatabaseAuthorizer::dropTempView(const String&) @@ -261,7 +271,11 @@ int DatabaseAuthorizer::dropTempView(const String&) // SQLITE_DROP_TEMP_VIEW results in a DELETE operation, which is not // allowed in read-only transactions or private browsing, so we might as // well disallow SQLITE_DROP_TEMP_VIEW in these cases - return (m_readOnly && m_securityEnabled ? SQLAuthDeny : SQLAuthAllow); + if (m_readOnly && m_securityEnabled) + return SQLAuthDeny; + + m_hadDeletes = true; + return SQLAuthAllow; } int DatabaseAuthorizer::createVTable(const String& tableName, const String& moduleName) @@ -286,7 +300,7 @@ int DatabaseAuthorizer::dropVTable(const String& tableName, const String& module if (moduleName != "fts3") return SQLAuthDeny; - return denyBasedOnTableName(tableName); + return updateDeletesBasedOnTableName(tableName); } int DatabaseAuthorizer::allowDelete(const String& tableName) @@ -294,7 +308,7 @@ int DatabaseAuthorizer::allowDelete(const String& tableName) if (m_readOnly && m_securityEnabled) return SQLAuthDeny; - return denyBasedOnTableName(tableName); + return updateDeletesBasedOnTableName(tableName); } int DatabaseAuthorizer::allowInsert(const String& tableName) @@ -391,4 +405,14 @@ int DatabaseAuthorizer::denyBasedOnTableName(const String& tableName) return SQLAuthAllow; } +int DatabaseAuthorizer::updateDeletesBasedOnTableName(const String& tableName) +{ + int allow = denyBasedOnTableName(tableName); + if (allow) + m_hadDeletes = true; + return allow; +} + } // namespace WebCore + +#endif // ENABLE(DATABASE) diff --git a/WebCore/storage/DatabaseAuthorizer.h b/WebCore/storage/DatabaseAuthorizer.h index 037409e..7da0143 100644 --- a/WebCore/storage/DatabaseAuthorizer.h +++ b/WebCore/storage/DatabaseAuthorizer.h @@ -90,19 +90,23 @@ public: void setReadOnly(); void reset(); + void resetDeletes(); bool lastActionWasInsert() const { return m_lastActionWasInsert; } bool lastActionChangedDatabase() const { return m_lastActionChangedDatabase; } + bool hadDeletes() const { return m_hadDeletes; } private: DatabaseAuthorizer(); void addWhitelistedFunctions(); int denyBasedOnTableName(const String&); + int updateDeletesBasedOnTableName(const String&); bool m_securityEnabled : 1; bool m_lastActionWasInsert : 1; bool m_lastActionChangedDatabase : 1; bool m_readOnly : 1; + bool m_hadDeletes : 1; HashSet<String, CaseFoldingHash> m_whitelistedFunctions; }; diff --git a/WebCore/storage/DatabaseTask.cpp b/WebCore/storage/DatabaseTask.cpp index a8038c3..8d5f0a8 100644 --- a/WebCore/storage/DatabaseTask.cpp +++ b/WebCore/storage/DatabaseTask.cpp @@ -143,11 +143,8 @@ DatabaseTransactionTask::~DatabaseTransactionTask() void DatabaseTransactionTask::doPerformTask() { - if (m_transaction->performNextStep()) { - // The transaction is complete, we can move on to the next one. - MutexLocker locker(m_transaction->database()->m_transactionInProgressMutex); - m_transaction->database()->scheduleTransaction(); - } + if (m_transaction->performNextStep()) + m_transaction->database()->inProgressTransactionCompleted(); } #ifndef NDEBUG diff --git a/WebCore/storage/DatabaseTask.h b/WebCore/storage/DatabaseTask.h index b473f8f..1a820a5 100644 --- a/WebCore/storage/DatabaseTask.h +++ b/WebCore/storage/DatabaseTask.h @@ -32,6 +32,7 @@ #include "Database.h" #include "ExceptionCode.h" #include "PlatformString.h" +#include "SQLTransaction.h" #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> #include <wtf/PassRefPtr.h> @@ -40,13 +41,6 @@ namespace WebCore { -class DatabaseTask; -class DatabaseThread; -class SQLValue; -class SQLCallback; -class SQLTransaction; -class VersionChangeCallback; - // Can be used to wait until DatabaseTask is completed. // Has to be passed into DatabaseTask::create to be associated with the task. class DatabaseTaskSynchronizer : public Noncopyable { diff --git a/WebCore/storage/IDBCallbacks.h b/WebCore/storage/IDBCallbacks.h index ff6272a..c90acc5 100644 --- a/WebCore/storage/IDBCallbacks.h +++ b/WebCore/storage/IDBCallbacks.h @@ -32,6 +32,7 @@ #include "IDBDatabase.h" #include "IDBDatabaseError.h" #include "IDBIndex.h" +#include "IDBObjectStore.h" #include "SerializedScriptValue.h" #include <wtf/RefCounted.h> @@ -47,6 +48,7 @@ public: virtual void onSuccess() = 0; // For "null". virtual void onSuccess(PassRefPtr<IDBDatabase>) = 0; virtual void onSuccess(PassRefPtr<IDBIndex>) = 0; + virtual void onSuccess(PassRefPtr<IDBObjectStore>) = 0; virtual void onSuccess(PassRefPtr<SerializedScriptValue>) = 0; }; diff --git a/WebCore/storage/IDBDatabase.h b/WebCore/storage/IDBDatabase.h index 5bfb3c7..0055ad1 100644 --- a/WebCore/storage/IDBDatabase.h +++ b/WebCore/storage/IDBDatabase.h @@ -35,6 +35,9 @@ namespace WebCore { class DOMStringList; +class Frame; +class IDBCallbacks; +class IDBObjectStore; // This class is shared by IDBDatabaseRequest (async) and IDBDatabaseSync (sync). // This is implemented by IDBDatabaseImpl and optionally others (in order to proxy @@ -44,10 +47,16 @@ class IDBDatabase : public ThreadSafeShared<IDBDatabase> { public: virtual ~IDBDatabase() { } - virtual String name() = 0; - virtual String description() = 0; - virtual String version() = 0; - virtual PassRefPtr<DOMStringList> objectStores() = 0; + virtual String name() const = 0; + virtual String description() const = 0; + virtual String version() const = 0; + virtual PassRefPtr<DOMStringList> objectStores() const = 0; + + // FIXME: Add transaction and setVersion. + + virtual void createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks>) = 0; + virtual PassRefPtr<IDBObjectStore> objectStore(const String& name, unsigned short mode) = 0; + virtual void removeObjectStore(const String& name, PassRefPtr<IDBCallbacks>) = 0; }; } // namespace WebCore diff --git a/WebCore/storage/IDBDatabaseImpl.cpp b/WebCore/storage/IDBDatabaseImpl.cpp index 655bd59..712830a 100644 --- a/WebCore/storage/IDBDatabaseImpl.cpp +++ b/WebCore/storage/IDBDatabaseImpl.cpp @@ -27,6 +27,8 @@ #include "IDBDatabaseImpl.h" #include "DOMStringList.h" +#include "IDBDatabaseException.h" +#include "IDBObjectStoreImpl.h" #if ENABLE(INDEXED_DATABASE) @@ -43,10 +45,42 @@ IDBDatabaseImpl::~IDBDatabaseImpl() { } -PassRefPtr<DOMStringList> IDBDatabaseImpl::objectStores() +PassRefPtr<DOMStringList> IDBDatabaseImpl::objectStores() const { - // FIXME: This should return the actual list. - return DOMStringList::create(); + RefPtr<DOMStringList> objectStoreNames = DOMStringList::create(); + for (ObjectStoreMap::const_iterator it = m_objectStores.begin(); it != m_objectStores.end(); ++it) + objectStoreNames->append(it->first); + return objectStoreNames.release(); +} + +void IDBDatabaseImpl::createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks> callbacks) +{ + if (m_objectStores.contains(name)) { + callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "An objectStore with that name already exists.")); + return; + } + + RefPtr<IDBObjectStore> objectStore = IDBObjectStoreImpl::create(name, keyPath, autoIncrement); + m_objectStores.set(name, objectStore); + callbacks->onSuccess(objectStore.release()); +} + +PassRefPtr<IDBObjectStore> IDBDatabaseImpl::objectStore(const String& name, unsigned short mode) +{ + // FIXME: If no transaction is running, this should implicitly start one. + ASSERT(!mode); // FIXME: Handle non-standard modes. + return m_objectStores.get(name); +} + +void IDBDatabaseImpl::removeObjectStore(const String& name, PassRefPtr<IDBCallbacks> callbacks) +{ + if (!m_objectStores.contains(name)) { + callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "No objectStore with that name exists.")); + return; + } + + m_objectStores.remove(name); + callbacks->onSuccess(); } } // namespace WebCore diff --git a/WebCore/storage/IDBDatabaseImpl.h b/WebCore/storage/IDBDatabaseImpl.h index 679017d..7203c5a 100644 --- a/WebCore/storage/IDBDatabaseImpl.h +++ b/WebCore/storage/IDBDatabaseImpl.h @@ -26,7 +26,10 @@ #ifndef IDBDatabaseImpl_h #define IDBDatabaseImpl_h +#include "IDBCallbacks.h" #include "IDBDatabase.h" +#include "StringHash.h" +#include <wtf/HashMap.h> #if ENABLE(INDEXED_DATABASE) @@ -41,10 +44,14 @@ public: virtual ~IDBDatabaseImpl(); // Implements IDBDatabase - virtual String name() { return m_name; } - virtual String description() { return m_description; } - virtual String version() { return m_version; } - virtual PassRefPtr<DOMStringList> objectStores(); + 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 void createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks>); + virtual PassRefPtr<IDBObjectStore> objectStore(const String& name, unsigned short mode); + virtual void removeObjectStore(const String& name, PassRefPtr<IDBCallbacks>); private: IDBDatabaseImpl(const String& name, const String& description, const String& version); @@ -52,6 +59,9 @@ private: String m_name; String m_description; String m_version; + + typedef HashMap<String, RefPtr<IDBObjectStore> > ObjectStoreMap; + ObjectStoreMap m_objectStores; }; } // namespace WebCore diff --git a/WebCore/storage/IDBDatabaseRequest.cpp b/WebCore/storage/IDBDatabaseRequest.cpp index 311fb25..c620279 100644 --- a/WebCore/storage/IDBDatabaseRequest.cpp +++ b/WebCore/storage/IDBDatabaseRequest.cpp @@ -26,21 +26,48 @@ #include "config.h" #include "IDBDatabaseRequest.h" +#include "IDBAny.h" +#include "IDBObjectStoreRequest.h" +#include "IDBRequest.h" #include "IndexedDatabase.h" +#include "ScriptExecutionContext.h" #if ENABLE(INDEXED_DATABASE) namespace WebCore { -IDBDatabaseRequest::IDBDatabaseRequest(PassRefPtr<IDBDatabase> idbDatabase) - : m_idbDatabase(idbDatabase) +IDBDatabaseRequest::IDBDatabaseRequest(PassRefPtr<IDBDatabase> database) + : m_database(database) { + m_this = IDBAny::create(); + m_this->set(this); } IDBDatabaseRequest::~IDBDatabaseRequest() { } +PassRefPtr<IDBRequest> IDBDatabaseRequest::createObjectStore(ScriptExecutionContext* context, const String& name, const String& keyPath, bool autoIncrement) +{ + RefPtr<IDBRequest> request = IDBRequest::create(context, m_this); + m_database->createObjectStore(name, keyPath, autoIncrement, request); + return request; +} + +PassRefPtr<IDBObjectStoreRequest> IDBDatabaseRequest::objectStore(const String& name, unsigned short mode) +{ + RefPtr<IDBObjectStore> objectStore = m_database->objectStore(name, mode); + ASSERT(objectStore); // FIXME: If this is null, we should raise a NOT_FOUND_ERR. + return IDBObjectStoreRequest::create(objectStore.release()); +} + +PassRefPtr<IDBRequest> IDBDatabaseRequest::removeObjectStore(ScriptExecutionContext* context, const String& name) +{ + RefPtr<IDBRequest> request = IDBRequest::create(context, m_this); + m_database->removeObjectStore(name, request); + return request; +} + } // namespace WebCore #endif // ENABLE(INDEXED_DATABASE) diff --git a/WebCore/storage/IDBDatabaseRequest.h b/WebCore/storage/IDBDatabaseRequest.h index 26f6a86..6b9e107 100644 --- a/WebCore/storage/IDBDatabaseRequest.h +++ b/WebCore/storage/IDBDatabaseRequest.h @@ -36,24 +36,34 @@ namespace WebCore { +class IDBAny; +class IDBObjectStoreRequest; +class IDBRequest; +class ScriptExecutionContext; + class IDBDatabaseRequest : public RefCounted<IDBDatabaseRequest> { public: - static PassRefPtr<IDBDatabaseRequest> create(PassRefPtr<IDBDatabase> idbDatabase) + static PassRefPtr<IDBDatabaseRequest> create(PassRefPtr<IDBDatabase> database) { - return adoptRef(new IDBDatabaseRequest(idbDatabase)); + return adoptRef(new IDBDatabaseRequest(database)); } ~IDBDatabaseRequest(); // Implement the IDL - String name() const { return m_idbDatabase->name(); } - String description() const { return m_idbDatabase->description(); } - String version() const { return m_idbDatabase->version(); } - PassRefPtr<DOMStringList> objectStores() const { return m_idbDatabase->objectStores(); } + String name() const { return m_database->name(); } + String description() const { return m_database->description(); } + String version() const { return m_database->version(); } + PassRefPtr<DOMStringList> objectStores() const { return m_database->objectStores(); } + + PassRefPtr<IDBRequest> createObjectStore(ScriptExecutionContext*, const String& name, const String& keyPath = "", bool autoIncrement = false); + PassRefPtr<IDBObjectStoreRequest> objectStore(const String& name, unsigned short mode = 0); // FIXME: Use constant rather than 0. + PassRefPtr<IDBRequest> removeObjectStore(ScriptExecutionContext*, const String& name); private: IDBDatabaseRequest(PassRefPtr<IDBDatabase>); - RefPtr<IDBDatabase> m_idbDatabase; + RefPtr<IDBDatabase> m_database; + RefPtr<IDBAny> m_this; }; } // namespace WebCore diff --git a/WebCore/storage/IDBDatabaseRequest.idl b/WebCore/storage/IDBDatabaseRequest.idl index b835ace..c018bbf 100644 --- a/WebCore/storage/IDBDatabaseRequest.idl +++ b/WebCore/storage/IDBDatabaseRequest.idl @@ -28,12 +28,18 @@ module storage { interface [ Conditional=INDEXED_DATABASE ] IDBDatabaseRequest { - // FIXME: Complete this file. - readonly attribute DOMString name; - // readonly attribute DOMString description; + readonly attribute DOMString description; readonly attribute DOMString version; readonly attribute DOMStringList objectStores; + + // FIXME: Add transaction. + // FIXME: Add setVersion. + + [CallWith=ScriptExecutionContext] IDBRequest createObjectStore(in DOMString name, in [Optional] DOMString path, in [Optional] boolean autoIncrement); + // FIXME: objectStore needs to be able to raise an IDBDatabaseException. + IDBObjectStoreRequest objectStore(in DOMString name, in [Optional] unsigned short mode); + [CallWith=ScriptExecutionContext] IDBRequest removeObjectStore(in DOMString name); }; } diff --git a/WebCore/storage/IDBKeyRange.cpp b/WebCore/storage/IDBKeyRange.cpp new file mode 100644 index 0000000..34c11fe --- /dev/null +++ b/WebCore/storage/IDBKeyRange.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "IDBKeyRange.h" + +#include "IDBAny.h" +#include "SerializedScriptValue.h" + +#if ENABLE(INDEXED_DATABASE) + +namespace WebCore { + +IDBKeyRange::IDBKeyRange(PassRefPtr<SerializedScriptValue> left, PassRefPtr<SerializedScriptValue> right, unsigned short flags) + : m_left(IDBAny::create()) + , m_right(IDBAny::create()) + , m_flags(flags) +{ + m_left->set(left); + m_right->set(right); +} + +} // namespace WebCore + +#endif // ENABLE(INDEXED_DATABASE) diff --git a/WebCore/storage/IDBKeyRange.h b/WebCore/storage/IDBKeyRange.h new file mode 100644 index 0000000..58c1399 --- /dev/null +++ b/WebCore/storage/IDBKeyRange.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IDBKeyRange_h +#define IDBKeyRange_h + +#if ENABLE(INDEXED_DATABASE) + +#include "IDBAny.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +class SerializedScriptValue; + +class IDBKeyRange : public RefCounted<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<SerializedScriptValue> left, PassRefPtr<SerializedScriptValue> right, unsigned short flags) + { + return adoptRef(new IDBKeyRange(left, right, flags)); + } + ~IDBKeyRange() { } + + + PassRefPtr<IDBAny> left() const { return m_left; } + PassRefPtr<IDBAny> right() const { return m_right; } + unsigned short flags() const { return m_flags; } + +private: + IDBKeyRange(PassRefPtr<SerializedScriptValue> left, PassRefPtr<SerializedScriptValue> right, unsigned short flags); + + RefPtr<IDBAny> m_left; + RefPtr<IDBAny> m_right; + unsigned short m_flags; +}; + +} // namespace WebCore + +#endif + +#endif // IDBKeyRange_h diff --git a/WebCore/storage/IDBKeyRange.idl b/WebCore/storage/IDBKeyRange.idl new file mode 100644 index 0000000..05f6505 --- /dev/null +++ b/WebCore/storage/IDBKeyRange.idl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +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 IDBAny left; + readonly attribute IDBAny right; + readonly attribute unsigned short flags; + }; + +} diff --git a/WebCore/storage/IDBObjectStore.h b/WebCore/storage/IDBObjectStore.h index c1ce129..837b65a 100644 --- a/WebCore/storage/IDBObjectStore.h +++ b/WebCore/storage/IDBObjectStore.h @@ -27,8 +27,6 @@ #define IDBObjectStore_h #include "PlatformString.h" -#include "StringHash.h" -#include <wtf/HashMap.h> #include <wtf/Threading.h> #if ENABLE(INDEXED_DATABASE) @@ -36,33 +34,20 @@ namespace WebCore { class DOMStringList; -class IDBIndex; class IDBCallbacks; +class IDBIndex; -// FIXME: This needs to be split into an interface and Impl classes. class IDBObjectStore : public ThreadSafeShared<IDBObjectStore> { public: - static PassRefPtr<IDBObjectStore> create() - { - return adoptRef(new IDBObjectStore()); - } - virtual ~IDBObjectStore(); - - String name() const { return m_name; } - String keyPath() const { return m_keyPath; } - PassRefPtr<DOMStringList> indexNames() const; - - void createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>); - PassRefPtr<IDBIndex> index(const String& name); - void removeIndex(const String& name, PassRefPtr<IDBCallbacks>); + virtual ~IDBObjectStore() { } -private: - IDBObjectStore(); + virtual String name() const = 0; + virtual String keyPath() const = 0; + virtual PassRefPtr<DOMStringList> indexNames() const = 0; - String m_name; - String m_keyPath; - typedef HashMap<String, RefPtr<IDBIndex> > IndexMap; - IndexMap m_indexes; + virtual void createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>) = 0; + virtual PassRefPtr<IDBIndex> index(const String& name) = 0; + virtual void removeIndex(const String& name, PassRefPtr<IDBCallbacks>) = 0; }; } // namespace WebCore diff --git a/WebCore/storage/IDBObjectStore.cpp b/WebCore/storage/IDBObjectStoreImpl.cpp index 4aef460..b84ceb2 100644..100755 --- a/WebCore/storage/IDBObjectStore.cpp +++ b/WebCore/storage/IDBObjectStoreImpl.cpp @@ -24,7 +24,7 @@ */ #include "config.h" -#include "IDBObjectStore.h" +#include "IDBObjectStoreImpl.h" #include "DOMStringList.h" #include "IDBCallbacks.h" @@ -35,15 +35,18 @@ namespace WebCore { -IDBObjectStore::IDBObjectStore() +IDBObjectStoreImpl::~IDBObjectStoreImpl() { } -IDBObjectStore::~IDBObjectStore() +IDBObjectStoreImpl::IDBObjectStoreImpl(const String& name, const String& keyPath, bool autoIncrement) + : m_name(name) + , m_keyPath(keyPath) + , m_autoIncrement(autoIncrement) { } -PassRefPtr<DOMStringList> IDBObjectStore::indexNames() const +PassRefPtr<DOMStringList> IDBObjectStoreImpl::indexNames() const { RefPtr<DOMStringList> indexNames = DOMStringList::create(); for (IndexMap::const_iterator it = m_indexes.begin(); it != m_indexes.end(); ++it) @@ -51,7 +54,7 @@ PassRefPtr<DOMStringList> IDBObjectStore::indexNames() const return indexNames.release(); } -void IDBObjectStore::createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks> callbacks) +void IDBObjectStoreImpl::createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks> callbacks) { if (m_indexes.contains(name)) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Index name already exists.")); @@ -64,12 +67,12 @@ void IDBObjectStore::createIndex(const String& name, const String& keyPath, bool callbacks->onSuccess(index.release()); } -PassRefPtr<IDBIndex> IDBObjectStore::index(const String& name) +PassRefPtr<IDBIndex> IDBObjectStoreImpl::index(const String& name) { return m_indexes.get(name); } -void IDBObjectStore::removeIndex(const String& name, PassRefPtr<IDBCallbacks> callbacks) +void IDBObjectStoreImpl::removeIndex(const String& name, PassRefPtr<IDBCallbacks> callbacks) { if (!m_indexes.contains(name)) { callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Index name does not exist.")); @@ -80,7 +83,7 @@ void IDBObjectStore::removeIndex(const String& name, PassRefPtr<IDBCallbacks> ca callbacks->onSuccess(); } -} // namespace WebCore -#endif // ENABLE(INDEXED_DATABASE) +} // namespace WebCore +#endif diff --git a/WebCore/storage/IDBObjectStoreImpl.h b/WebCore/storage/IDBObjectStoreImpl.h new file mode 100755 index 0000000..89a06db --- /dev/null +++ b/WebCore/storage/IDBObjectStoreImpl.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IDBObjectStoreImpl_h +#define IDBObjectStoreImpl_h + +#include "IDBObjectStore.h" +#include "StringHash.h" +#include <wtf/HashMap.h> + +#if ENABLE(INDEXED_DATABASE) + +namespace WebCore { + +class IDBObjectStoreImpl : public IDBObjectStore { +public: + static PassRefPtr<IDBObjectStore> create(const String& name, const String& keyPath, bool autoIncrement) + { + return adoptRef(new IDBObjectStoreImpl(name, keyPath, autoIncrement)); + } + virtual ~IDBObjectStoreImpl(); + + String name() const { return m_name; } + String keyPath() const { return m_keyPath; } + PassRefPtr<DOMStringList> indexNames() const; + + void createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>); + PassRefPtr<IDBIndex> index(const String& name); + void removeIndex(const String& name, PassRefPtr<IDBCallbacks>); + +private: + IDBObjectStoreImpl(const String& name, const String& keyPath, bool autoIncrement); + + String m_name; + String m_keyPath; + bool m_autoIncrement; + + typedef HashMap<String, RefPtr<IDBIndex> > IndexMap; + IndexMap m_indexes; +}; + +} // namespace WebCore + +#endif + +#endif // IDBObjectStoreImpl_h diff --git a/WebCore/storage/IDBObjectStoreRequest.cpp b/WebCore/storage/IDBObjectStoreRequest.cpp index 35763cb..b2c36dc 100644 --- a/WebCore/storage/IDBObjectStoreRequest.cpp +++ b/WebCore/storage/IDBObjectStoreRequest.cpp @@ -29,7 +29,6 @@ #include "DOMStringList.h" #include "IDBAny.h" #include "IDBIndexRequest.h" -#include "ScriptExecutionContext.h" #include "SerializedScriptValue.h" #include <wtf/UnusedParam.h> @@ -37,9 +36,8 @@ namespace WebCore { -IDBObjectStoreRequest::IDBObjectStoreRequest(ScriptExecutionContext* context, PassRefPtr<IDBObjectStore> idbObjectStore) +IDBObjectStoreRequest::IDBObjectStoreRequest(PassRefPtr<IDBObjectStore> idbObjectStore) : m_objectStore(idbObjectStore) - , m_scriptExecutionContext(context) { m_this = IDBAny::create(); m_this->set(this); @@ -60,63 +58,68 @@ PassRefPtr<DOMStringList> IDBObjectStoreRequest::indexNames() const return m_objectStore->indexNames(); } -PassRefPtr<IDBRequest> IDBObjectStoreRequest::get(PassRefPtr<SerializedScriptValue> key) +PassRefPtr<IDBRequest> IDBObjectStoreRequest::get(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> key) { // FIXME: implement + UNUSED_PARAM(context); UNUSED_PARAM(key); return 0; } -PassRefPtr<IDBRequest> IDBObjectStoreRequest::add(PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key) +PassRefPtr<IDBRequest> IDBObjectStoreRequest::add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key) { // FIXME: implement + UNUSED_PARAM(context); UNUSED_PARAM(value); UNUSED_PARAM(key); return 0; } -PassRefPtr<IDBRequest> IDBObjectStoreRequest::modify(PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key) +PassRefPtr<IDBRequest> IDBObjectStoreRequest::modify(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key) { // FIXME: implement + UNUSED_PARAM(context); UNUSED_PARAM(value); UNUSED_PARAM(key); return 0; } -PassRefPtr<IDBRequest> IDBObjectStoreRequest::addOrModify(PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key) +PassRefPtr<IDBRequest> IDBObjectStoreRequest::addOrModify(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key) { // FIXME: implement + UNUSED_PARAM(context); UNUSED_PARAM(value); UNUSED_PARAM(key); return 0; } -PassRefPtr<IDBRequest> IDBObjectStoreRequest::remove(PassRefPtr<SerializedScriptValue> key) +PassRefPtr<IDBRequest> IDBObjectStoreRequest::remove(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> key) { // FIXME: implement + UNUSED_PARAM(context); UNUSED_PARAM(key); return 0; } -PassRefPtr<IDBRequest> IDBObjectStoreRequest::createIndex(const String& name, const String& keyPath, bool unique) const +PassRefPtr<IDBRequest> IDBObjectStoreRequest::createIndex(ScriptExecutionContext* context, const String& name, const String& keyPath, bool unique) { - // FIXME: Implement. - UNUSED_PARAM(name); - UNUSED_PARAM(keyPath); - UNUSED_PARAM(unique); - return 0; + RefPtr<IDBRequest> request = IDBRequest::create(context, m_this); + m_objectStore->createIndex(name, keyPath, unique, request); + return request; } -PassRefPtr<IDBIndexRequest> IDBObjectStoreRequest::index(const String& name) const +PassRefPtr<IDBIndexRequest> IDBObjectStoreRequest::index(const String& name) { - return IDBIndexRequest::create(m_objectStore->index(name)); + RefPtr<IDBIndex> index = m_objectStore->index(name); + ASSERT(index); // FIXME: If this is null, we should raise a NOT_FOUND_ERR. + return IDBIndexRequest::create(index.release()); } -PassRefPtr<IDBRequest> IDBObjectStoreRequest::removeIndex(const String& name) const +PassRefPtr<IDBRequest> IDBObjectStoreRequest::removeIndex(ScriptExecutionContext* context, const String& name) { - // FIXME: Implement. - UNUSED_PARAM(name); - return 0; + RefPtr<IDBRequest> request = IDBRequest::create(context, m_this); + m_objectStore->removeIndex(name, request); + return request; } } // namespace WebCore diff --git a/WebCore/storage/IDBObjectStoreRequest.h b/WebCore/storage/IDBObjectStoreRequest.h index f03b406..f1a9f5b 100644 --- a/WebCore/storage/IDBObjectStoreRequest.h +++ b/WebCore/storage/IDBObjectStoreRequest.h @@ -40,14 +40,13 @@ namespace WebCore { class DOMStringList; class IDBAny; class IDBIndexRequest; -class ScriptExecutionContext; class SerializedScriptValue; class IDBObjectStoreRequest : public RefCounted<IDBObjectStoreRequest> { public: - static PassRefPtr<IDBObjectStoreRequest> create(ScriptExecutionContext* context, PassRefPtr<IDBObjectStore> idbObjectStore) + static PassRefPtr<IDBObjectStoreRequest> create(PassRefPtr<IDBObjectStore> idbObjectStore) { - return adoptRef(new IDBObjectStoreRequest(context, idbObjectStore)); + return adoptRef(new IDBObjectStoreRequest(idbObjectStore)); } ~IDBObjectStoreRequest() { } @@ -55,21 +54,20 @@ public: String keyPath() const; PassRefPtr<DOMStringList> indexNames() const; - PassRefPtr<IDBRequest> get(PassRefPtr<SerializedScriptValue> key); - PassRefPtr<IDBRequest> add(PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key = 0); - PassRefPtr<IDBRequest> modify(PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key = 0); - PassRefPtr<IDBRequest> addOrModify(PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key = 0); - PassRefPtr<IDBRequest> remove(PassRefPtr<SerializedScriptValue> key); + PassRefPtr<IDBRequest> get(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue> key); + PassRefPtr<IDBRequest> add(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key = 0); + PassRefPtr<IDBRequest> modify(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key = 0); + PassRefPtr<IDBRequest> addOrModify(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue> value, PassRefPtr<SerializedScriptValue> key = 0); + PassRefPtr<IDBRequest> remove(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue> key); - PassRefPtr<IDBRequest> createIndex(const String& name, const String& keyPath, bool unique = false) const; - PassRefPtr<IDBIndexRequest> index(const String& name) const; - PassRefPtr<IDBRequest> removeIndex(const String& name) const; + PassRefPtr<IDBRequest> createIndex(ScriptExecutionContext*, const String& name, const String& keyPath, bool unique = false); + PassRefPtr<IDBIndexRequest> index(const String& name); + PassRefPtr<IDBRequest> removeIndex(ScriptExecutionContext*, const String& name); private: - IDBObjectStoreRequest(ScriptExecutionContext*, PassRefPtr<IDBObjectStore>); + IDBObjectStoreRequest(PassRefPtr<IDBObjectStore>); RefPtr<IDBObjectStore> m_objectStore; - RefPtr<ScriptExecutionContext> m_scriptExecutionContext; RefPtr<IDBAny> m_this; }; @@ -77,5 +75,5 @@ private: #endif -#endif // IDBDatabaseRequest_h +#endif // IDBObjectStoreRequest_h diff --git a/WebCore/storage/IDBObjectStoreRequest.idl b/WebCore/storage/IDBObjectStoreRequest.idl index 2d4c8be..873629d 100644 --- a/WebCore/storage/IDBObjectStoreRequest.idl +++ b/WebCore/storage/IDBObjectStoreRequest.idl @@ -28,16 +28,20 @@ module storage { interface [ Conditional=INDEXED_DATABASE ] IDBObjectStoreRequest { - IDBRequest get(in SerializedScriptValue key); + [CallWith=ScriptExecutionContext] IDBRequest get(in SerializedScriptValue key); + // FIXME: Come to concensus re getAll. - IDBRequest add(in SerializedScriptValue value, in [Optional] SerializedScriptValue key); - IDBRequest modify(in SerializedScriptValue value, in [Optional] SerializedScriptValue key); - IDBRequest addOrModify(in SerializedScriptValue value, in [Optional] SerializedScriptValue key); - IDBRequest remove(in SerializedScriptValue key); + // FIXME: SerializedScriptValue raises an exception if you pass in something that can't be serialized. + // We need to instead "raise" this error via an error callback. + [CallWith=ScriptExecutionContext] IDBRequest add(in SerializedScriptValue value, in [Optional] SerializedScriptValue key); + [CallWith=ScriptExecutionContext] IDBRequest modify(in SerializedScriptValue value, in [Optional] SerializedScriptValue key); + [CallWith=ScriptExecutionContext] IDBRequest addOrModify(in SerializedScriptValue value, in [Optional] SerializedScriptValue key); + [CallWith=ScriptExecutionContext] IDBRequest remove(in SerializedScriptValue key); // FIXME: write openCursor - IDBRequest createIndex(in DOMString name, in DOMString keyPath, in [Optional] boolean unique); + [CallWith=ScriptExecutionContext] IDBRequest createIndex(in DOMString name, in DOMString keyPath, in [Optional] boolean unique); + // FIXME: This needs to raise an IDBDatabaseException on errors. IDBIndexRequest index(in DOMString name); - IDBRequest removeIndex(in DOMString name); + [CallWith=ScriptExecutionContext] IDBRequest removeIndex(in DOMString name); readonly attribute DOMString name; readonly attribute DOMString keyPath; diff --git a/WebCore/storage/IDBRequest.cpp b/WebCore/storage/IDBRequest.cpp index f86abcb..f0ba25b 100644 --- a/WebCore/storage/IDBRequest.cpp +++ b/WebCore/storage/IDBRequest.cpp @@ -38,6 +38,7 @@ #include "IDBDatabaseRequest.h" #include "IDBIndexRequest.h" #include "IDBErrorEvent.h" +#include "IDBObjectStoreRequest.h" #include "IDBSuccessEvent.h" #include "ScriptExecutionContext.h" @@ -84,6 +85,12 @@ void IDBRequest::onSuccess(PassRefPtr<IDBIndex> idbIndex) m_result->set(IDBIndexRequest::create(idbIndex)); } +void IDBRequest::onSuccess(PassRefPtr<IDBObjectStore> idbObjectStore) +{ + onEventCommon(); + m_result->set(IDBObjectStoreRequest::create(idbObjectStore)); +} + void IDBRequest::onSuccess(PassRefPtr<SerializedScriptValue> serializedScriptValue) { onEventCommon(); diff --git a/WebCore/storage/IDBRequest.h b/WebCore/storage/IDBRequest.h index 5836f78..4fb4eed 100644 --- a/WebCore/storage/IDBRequest.h +++ b/WebCore/storage/IDBRequest.h @@ -66,8 +66,8 @@ public: virtual void onSuccess(); // For "null". virtual void onSuccess(PassRefPtr<IDBDatabase>); virtual void onSuccess(PassRefPtr<IDBIndex>); + virtual void onSuccess(PassRefPtr<IDBObjectStore>); virtual void onSuccess(PassRefPtr<SerializedScriptValue>); - // FIXME: Have one onSuccess function for each possible result type. // EventTarget virtual IDBRequest* toIDBRequest() { return this; } diff --git a/WebCore/storage/IndexedDatabase.h b/WebCore/storage/IndexedDatabase.h index d47de72..e6abf4a 100644 --- a/WebCore/storage/IndexedDatabase.h +++ b/WebCore/storage/IndexedDatabase.h @@ -50,7 +50,7 @@ public: static PassRefPtr<IndexedDatabase> create(); virtual ~IndexedDatabase() { } - virtual void open(const String& name, const String& description, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, ExceptionCode&) = 0; + virtual void open(const String& name, const String& description, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*) = 0; }; } // namespace WebCore diff --git a/WebCore/storage/IndexedDatabaseImpl.cpp b/WebCore/storage/IndexedDatabaseImpl.cpp index 25502de..793af9e 100644 --- a/WebCore/storage/IndexedDatabaseImpl.cpp +++ b/WebCore/storage/IndexedDatabaseImpl.cpp @@ -51,7 +51,7 @@ IndexedDatabaseImpl::~IndexedDatabaseImpl() { } -void IndexedDatabaseImpl::open(const String& name, const String& description, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin>, Frame*, ExceptionCode&) +void IndexedDatabaseImpl::open(const String& name, const String& description, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin>, Frame*) { RefPtr<IDBDatabase> database; IDBDatabaseMap::iterator it = m_databaseMap.find(name); diff --git a/WebCore/storage/IndexedDatabaseImpl.h b/WebCore/storage/IndexedDatabaseImpl.h index fa95674..b9520ee 100644 --- a/WebCore/storage/IndexedDatabaseImpl.h +++ b/WebCore/storage/IndexedDatabaseImpl.h @@ -41,7 +41,7 @@ public: static PassRefPtr<IndexedDatabaseImpl> create(); virtual ~IndexedDatabaseImpl(); - virtual void open(const String& name, const String& description, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, ExceptionCode&); + virtual void open(const String& name, const String& description, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*); private: IndexedDatabaseImpl(); diff --git a/WebCore/storage/IndexedDatabaseRequest.cpp b/WebCore/storage/IndexedDatabaseRequest.cpp index 196fff7..93e052c 100644 --- a/WebCore/storage/IndexedDatabaseRequest.cpp +++ b/WebCore/storage/IndexedDatabaseRequest.cpp @@ -33,6 +33,7 @@ #include "ExceptionCode.h" #include "Frame.h" #include "IDBDatabase.h" +#include "IDBKeyRange.h" #include "IDBRequest.h" #include "IndexedDatabase.h" @@ -40,9 +41,8 @@ namespace WebCore { -IndexedDatabaseRequest::IndexedDatabaseRequest(IndexedDatabase* indexedDatabase, Frame* frame) +IndexedDatabaseRequest::IndexedDatabaseRequest(IndexedDatabase* indexedDatabase) : m_indexedDatabase(indexedDatabase) - , m_frame(frame) { m_this = IDBAny::create(); m_this->set(this); @@ -52,13 +52,45 @@ IndexedDatabaseRequest::~IndexedDatabaseRequest() { } -PassRefPtr<IDBRequest> IndexedDatabaseRequest::open(const String& name, const String& description, ExceptionCode& exception) +PassRefPtr<IDBRequest> IndexedDatabaseRequest::open(ScriptExecutionContext* context, const String& name, const String& description) { - RefPtr<IDBRequest> request = IDBRequest::create(m_frame->document(), m_this); - m_indexedDatabase->open(name, description, request, m_frame->document()->securityOrigin(), m_frame, exception); + if (!context->isDocument()) { + // FIXME: make this work with workers. + return 0; + } + + Document* document = static_cast<Document*>(context); + if (!document->frame()) + return 0; + + RefPtr<IDBRequest> request = IDBRequest::create(document, m_this); + m_indexedDatabase->open(name, description, request, document->securityOrigin(), document->frame()); return request; } +PassRefPtr<IDBKeyRange> IndexedDatabaseRequest::makeSingleKeyRange(PassRefPtr<SerializedScriptValue> prpValue) +{ + RefPtr<SerializedScriptValue> value = prpValue; + return IDBKeyRange::create(value, value, IDBKeyRange::SINGLE); +} + +PassRefPtr<IDBKeyRange> IndexedDatabaseRequest::makeLeftBoundKeyRange(PassRefPtr<SerializedScriptValue> bound, bool open) +{ + return IDBKeyRange::create(bound, SerializedScriptValue::create(), open ? IDBKeyRange::LEFT_OPEN : IDBKeyRange::LEFT_BOUND); +} + +PassRefPtr<IDBKeyRange> IndexedDatabaseRequest::makeRightBoundKeyRange(PassRefPtr<SerializedScriptValue> bound, bool open) +{ + return IDBKeyRange::create(SerializedScriptValue::create(), bound, open ? IDBKeyRange::RIGHT_OPEN : IDBKeyRange::RIGHT_BOUND); +} + +PassRefPtr<IDBKeyRange> IndexedDatabaseRequest::makeBoundKeyRange(PassRefPtr<SerializedScriptValue> left, PassRefPtr<SerializedScriptValue> right, bool openLeft, bool openRight) +{ + unsigned short flags = openLeft ? IDBKeyRange::LEFT_OPEN : IDBKeyRange::LEFT_BOUND; + flags |= openRight ? IDBKeyRange::RIGHT_OPEN : IDBKeyRange::RIGHT_BOUND; + return IDBKeyRange::create(left, right, flags); +} + } // namespace WebCore #endif // ENABLE(INDEXED_DATABASE) diff --git a/WebCore/storage/IndexedDatabaseRequest.h b/WebCore/storage/IndexedDatabaseRequest.h index 3f89460..9802380 100644 --- a/WebCore/storage/IndexedDatabaseRequest.h +++ b/WebCore/storage/IndexedDatabaseRequest.h @@ -39,28 +39,32 @@ namespace WebCore { -class Frame; class IDBAny; +class IDBKeyRange; +class IDBRequest; class IndexedDatabase; +class ScriptExecutionContext; +class SerializedScriptValue; class IndexedDatabaseRequest : public RefCounted<IndexedDatabaseRequest> { public: - static PassRefPtr<IndexedDatabaseRequest> create(IndexedDatabase* indexedDatabase, Frame* frame) + static PassRefPtr<IndexedDatabaseRequest> create(IndexedDatabase* indexedDatabase) { - return adoptRef(new IndexedDatabaseRequest(indexedDatabase, frame)); + return adoptRef(new IndexedDatabaseRequest(indexedDatabase)); } ~IndexedDatabaseRequest(); - PassRefPtr<IDBRequest> open(const String& name, const String& description, ExceptionCode&); - - void disconnectFrame() { m_frame = 0; } + PassRefPtr<IDBRequest> open(ScriptExecutionContext*, const String& name, const String& description); + PassRefPtr<IDBKeyRange> makeSingleKeyRange(PassRefPtr<SerializedScriptValue> value); + PassRefPtr<IDBKeyRange> makeLeftBoundKeyRange(PassRefPtr<SerializedScriptValue> bound, bool open = false); + PassRefPtr<IDBKeyRange> makeRightBoundKeyRange(PassRefPtr<SerializedScriptValue> bound, bool open = false); + PassRefPtr<IDBKeyRange> makeBoundKeyRange(PassRefPtr<SerializedScriptValue> left, PassRefPtr<SerializedScriptValue> right, bool openLeft = false, bool openRight = false); private: - IndexedDatabaseRequest(IndexedDatabase*, Frame*); + IndexedDatabaseRequest(IndexedDatabase*); RefPtr<IndexedDatabase> m_indexedDatabase; RefPtr<IDBAny> m_this; - Frame* m_frame; }; } // namespace WebCore diff --git a/WebCore/storage/IndexedDatabaseRequest.idl b/WebCore/storage/IndexedDatabaseRequest.idl index a87e033..502e804 100644 --- a/WebCore/storage/IndexedDatabaseRequest.idl +++ b/WebCore/storage/IndexedDatabaseRequest.idl @@ -28,9 +28,11 @@ module storage { interface [ Conditional=INDEXED_DATABASE ] IndexedDatabaseRequest { - // FIXME: This should no longer raise. - IDBRequest open(in DOMString name, in DOMString description) - raises(IDBDatabaseException); + [CallWith=ScriptExecutionContext] IDBRequest open(in DOMString name, in DOMString description); + IDBKeyRange makeSingleKeyRange(in SerializedScriptValue value); + IDBKeyRange makeLeftBoundKeyRange(in SerializedScriptValue bound, in [Optional] boolean open); + IDBKeyRange makeRightBoundKeyRange(in SerializedScriptValue bound, in [Optional] boolean open); + IDBKeyRange makeBoundKeyRange(in SerializedScriptValue left, in SerializedScriptValue right, in [Optional] boolean openLeft, in [Optional] boolean openRight); }; } diff --git a/WebCore/storage/SQLResultSet.idl b/WebCore/storage/SQLResultSet.idl index 0b70e01..52f06da 100644 --- a/WebCore/storage/SQLResultSet.idl +++ b/WebCore/storage/SQLResultSet.idl @@ -35,8 +35,14 @@ module storage { ] SQLResultSet { readonly attribute SQLResultSetRowList rows; +#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP readonly attribute long insertId getter raises(DOMException); +#else + // Explicitely choose 'long long' here to avoid a 64bit->32bit shortening warning for us. + readonly attribute long long insertId + getter raises(DOMException); +#endif readonly attribute long rowsAffected; }; } diff --git a/WebCore/storage/SQLStatement.cpp b/WebCore/storage/SQLStatement.cpp index 2e1aea2..cd96535 100644 --- a/WebCore/storage/SQLStatement.cpp +++ b/WebCore/storage/SQLStatement.cpp @@ -31,12 +31,10 @@ #if ENABLE(DATABASE) #include "Database.h" -#include "DatabaseAuthorizer.h" #include "Logging.h" #include "SQLError.h" #include "SQLiteDatabase.h" #include "SQLiteStatement.h" -#include "SQLResultSet.h" #include "SQLStatementCallback.h" #include "SQLStatementErrorCallback.h" #include "SQLTransaction.h" @@ -73,7 +71,7 @@ bool SQLStatement::execute(Database* db) if (m_readOnly) db->setAuthorizerReadOnly(); - SQLiteDatabase* database = &db->m_sqliteDatabase; + SQLiteDatabase* database = &db->sqliteDatabase(); SQLiteStatement statement(*database, m_statement); int result = statement.prepare(); @@ -130,7 +128,7 @@ bool SQLStatement::execute(Database* db) } } else if (result == SQLResultDone) { // Didn't find anything, or was an insert - if (db->m_databaseAuthorizer->lastActionWasInsert()) + if (db->lastActionWasInsert()) resultSet->setInsertId(database->lastInsertRowID()); } else if (result == SQLResultFull) { // Return the Quota error - the delegate will be asked for more space and this statement might be re-run diff --git a/WebCore/storage/SQLStatement.h b/WebCore/storage/SQLStatement.h index f01f7bf..89af377 100644 --- a/WebCore/storage/SQLStatement.h +++ b/WebCore/storage/SQLStatement.h @@ -31,23 +31,18 @@ #if ENABLE(DATABASE) #include "PlatformString.h" - -#include "SQLError.h" #include "SQLResultSet.h" -#include "SQLStatementCallback.h" -#include "SQLStatementErrorCallback.h" #include "SQLValue.h" - -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> -#include <wtf/Threading.h> +#include <wtf/Forward.h> #include <wtf/Vector.h> namespace WebCore { class Database; +class SQLError; +class SQLStatementCallback; +class SQLStatementErrorCallback; class SQLTransaction; -class String; class SQLStatement : public ThreadSafeShared<SQLStatement> { public: @@ -66,7 +61,7 @@ public: SQLError* sqlError() const { return m_error.get(); } private: - SQLStatement(const String& statement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> errorCallback, bool readOnly); + SQLStatement(const String& statement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback>, PassRefPtr<SQLStatementErrorCallback>, bool readOnly); void setFailureDueToQuota(); void clearFailureDueToQuota(); diff --git a/WebCore/storage/SQLTransaction.cpp b/WebCore/storage/SQLTransaction.cpp index 7f16b63..b06d865 100644 --- a/WebCore/storage/SQLTransaction.cpp +++ b/WebCore/storage/SQLTransaction.cpp @@ -31,26 +31,26 @@ #if ENABLE(DATABASE) -#include "ChromeClient.h" #include "Database.h" -#include "DatabaseAuthorizer.h" -#include "DatabaseDetails.h" #include "DatabaseThread.h" #include "ExceptionCode.h" #include "Logging.h" -#include "Page.h" #include "PlatformString.h" #include "ScriptExecutionContext.h" -#include "Settings.h" #include "SQLError.h" #include "SQLiteTransaction.h" -#include "SQLResultSet.h" #include "SQLStatement.h" #include "SQLStatementCallback.h" #include "SQLStatementErrorCallback.h" +#include "SQLTransactionCallback.h" #include "SQLTransactionClient.h" #include "SQLTransactionCoordinator.h" +#include "SQLTransactionErrorCallback.h" #include "SQLValue.h" +#include "VoidCallback.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> // There's no way of knowing exactly how much more space will be required when a statement hits the quota limit. // For now, we'll arbitrarily choose currentQuota + 1mb. @@ -65,8 +65,8 @@ PassRefPtr<SQLTransaction> SQLTransaction::create(Database* db, PassRefPtr<SQLTr return adoptRef(new SQLTransaction(db, callback, errorCallback, successCallback, wrapper, readOnly)); } -SQLTransaction::SQLTransaction(Database* db, PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback, PassRefPtr<VoidCallback> successCallback, - PassRefPtr<SQLTransactionWrapper> wrapper, bool readOnly) +SQLTransaction::SQLTransaction(Database* db, PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback, + PassRefPtr<VoidCallback> successCallback, PassRefPtr<SQLTransactionWrapper> wrapper, bool readOnly) : m_nextStep(&SQLTransaction::acquireLock) , m_executeSqlAllowed(false) , m_database(db) @@ -234,7 +234,7 @@ void SQLTransaction::lockAcquired() void SQLTransaction::openTransactionAndPreflight() { - ASSERT(!m_database->m_sqliteDatabase.transactionInProgress()); + ASSERT(!m_database->sqliteDatabase().transactionInProgress()); ASSERT(m_lockAcquired); LOG(StorageAPI, "Opening and preflighting transaction %p", this); @@ -248,18 +248,19 @@ void SQLTransaction::openTransactionAndPreflight() // Set the maximum usage for this transaction if this transactions is not read-only if (!m_readOnly) - m_database->m_sqliteDatabase.setMaximumSize(m_database->maximumSize()); + m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize()); ASSERT(!m_sqliteTransaction); - m_sqliteTransaction.set(new SQLiteTransaction(m_database->m_sqliteDatabase, m_readOnly)); + m_sqliteTransaction.set(new SQLiteTransaction(m_database->sqliteDatabase(), m_readOnly)); - m_database->m_databaseAuthorizer->disable(); + m_database->resetDeletes(); + m_database->disableAuthorizer(); m_sqliteTransaction->begin(); - m_database->m_databaseAuthorizer->enable(); + m_database->enableAuthorizer(); // Transaction Steps 1+2 - Open a transaction to the database, jumping to the error callback if that fails if (!m_sqliteTransaction->inProgress()) { - ASSERT(!m_database->m_sqliteDatabase.transactionInProgress()); + ASSERT(!m_database->sqliteDatabase().transactionInProgress()); m_sqliteTransaction.clear(); m_transactionError = SQLError::create(0, "unable to open a transaction to the database"); handleTransactionError(false); @@ -268,7 +269,7 @@ void SQLTransaction::openTransactionAndPreflight() // Transaction Steps 3 - Peform preflight steps, jumping to the error callback if they fail if (m_wrapper && !m_wrapper->performPreflight(this)) { - ASSERT(!m_database->m_sqliteDatabase.transactionInProgress()); + ASSERT(!m_database->sqliteDatabase().transactionInProgress()); m_sqliteTransaction.clear(); m_transactionError = m_wrapper->sqlError(); if (!m_transactionError) @@ -326,7 +327,7 @@ void SQLTransaction::runStatements() // m_shouldRetryCurrentStatement is set to true only when a statement exceeds // the quota, which can happen only in a read-write transaction. Therefore, there // is no need to check here if the transaction is read-write. - m_database->m_sqliteDatabase.setMaximumSize(m_database->maximumSize()); + m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize()); } else { // If the current statement has already been run, failed due to quota constraints, and we're not retrying it, // that means it ended in an error. Handle it now @@ -353,8 +354,7 @@ void SQLTransaction::getNextStatement() MutexLocker locker(m_statementMutex); if (!m_statementQueue.isEmpty()) { - m_currentStatement = m_statementQueue.first(); - m_statementQueue.removeFirst(); + m_currentStatement = m_statementQueue.takeFirst(); } } @@ -363,10 +363,10 @@ bool SQLTransaction::runCurrentStatement() if (!m_currentStatement) return false; - m_database->m_databaseAuthorizer->reset(); + m_database->resetAuthorizer(); if (m_currentStatement->execute(m_database.get())) { - if (m_database->m_databaseAuthorizer->lastActionChangedDatabase()) { + if (m_database->lastActionChangedDatabase()) { // Flag this transaction as having changed the database for later delegate notification m_modifiedDatabase = true; // Also dirty the size of this database file for calculating quota usage @@ -455,9 +455,9 @@ void SQLTransaction::postflightAndCommit() // Transacton Step 8+9 - Commit the transaction, jumping to the error callback if that fails ASSERT(m_sqliteTransaction); - m_database->m_databaseAuthorizer->disable(); + m_database->disableAuthorizer(); m_sqliteTransaction->commit(); - m_database->m_databaseAuthorizer->enable(); + m_database->enableAuthorizer(); // If the commit failed, the transaction will still be marked as "in progress" if (m_sqliteTransaction->inProgress()) { @@ -466,12 +466,13 @@ void SQLTransaction::postflightAndCommit() return; } - // The commit was successful. If the transaction modified this database, - // vacuum the database if needed and notify the delegates. - if (m_modifiedDatabase) { + // Vacuum the database if anything was deleted. + if (m_database->hadDeletes()) m_database->incrementalVacuumIfNeeded(); + + // The commit was successful. If the transaction modified this database, notify the delegates. + if (m_modifiedDatabase) m_database->transactionClient()->didCommitTransaction(this); - } // Now release our unneeded callbacks, to break reference cycles. m_callback = 0; @@ -509,7 +510,7 @@ void SQLTransaction::cleanupAfterSuccessCallback() // Transaction Step 11 - End transaction steps // There is no next step LOG(StorageAPI, "Transaction %p is complete\n", this); - ASSERT(!m_database->m_sqliteDatabase.transactionInProgress()); + ASSERT(!m_database->sqliteDatabase().transactionInProgress()); m_sqliteTransaction.clear(); m_nextStep = 0; @@ -559,15 +560,15 @@ void SQLTransaction::cleanupAfterTransactionErrorCallback() { ASSERT(m_lockAcquired); - m_database->m_databaseAuthorizer->disable(); + m_database->disableAuthorizer(); if (m_sqliteTransaction) { // Transaction Step 12 - Rollback the transaction. m_sqliteTransaction->rollback(); - ASSERT(!m_database->m_sqliteDatabase.transactionInProgress()); + ASSERT(!m_database->sqliteDatabase().transactionInProgress()); m_sqliteTransaction.clear(); } - m_database->m_databaseAuthorizer->enable(); + m_database->enableAuthorizer(); // Transaction Step 12 - Any still-pending statements in the transaction are discarded. { @@ -577,7 +578,7 @@ void SQLTransaction::cleanupAfterTransactionErrorCallback() // Transaction is complete! There is no next step LOG(StorageAPI, "Transaction %p is complete with an error\n", this); - ASSERT(!m_database->m_sqliteDatabase.transactionInProgress()); + ASSERT(!m_database->sqliteDatabase().transactionInProgress()); m_nextStep = 0; // Now release our callbacks, to break reference cycles. diff --git a/WebCore/storage/SQLTransaction.h b/WebCore/storage/SQLTransaction.h index 1b02d01..3cef036 100644 --- a/WebCore/storage/SQLTransaction.h +++ b/WebCore/storage/SQLTransaction.h @@ -32,14 +32,9 @@ #include <wtf/Threading.h> -#include "SQLiteTransaction.h" #include "SQLStatement.h" -#include "SQLTransactionCallback.h" -#include "SQLTransactionErrorCallback.h" #include <wtf/Deque.h> #include <wtf/Forward.h> -#include <wtf/OwnPtr.h> -#include <wtf/RefPtr.h> #include <wtf/Vector.h> namespace WebCore { @@ -48,9 +43,12 @@ typedef int ExceptionCode; class Database; class SQLError; +class SQLiteTransaction; class SQLStatementCallback; class SQLStatementErrorCallback; class SQLTransaction; +class SQLTransactionCallback; +class SQLTransactionErrorCallback; class SQLValue; class String; class VoidCallback; @@ -72,7 +70,7 @@ public: ~SQLTransaction(); void executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, - PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> callbackError, ExceptionCode& e); + PassRefPtr<SQLStatementCallback>, PassRefPtr<SQLStatementErrorCallback>, ExceptionCode&); void lockAcquired(); bool performNextStep(); diff --git a/WebCore/storage/SQLTransactionCoordinator.cpp b/WebCore/storage/SQLTransactionCoordinator.cpp index dbd2739..104ea10 100644 --- a/WebCore/storage/SQLTransactionCoordinator.cpp +++ b/WebCore/storage/SQLTransactionCoordinator.cpp @@ -57,8 +57,7 @@ void SQLTransactionCoordinator::processPendingTransactions(CoordinationInfo& inf RefPtr<SQLTransaction> firstPendingTransaction = info.pendingTransactions.first(); if (firstPendingTransaction->isReadOnly()) { do { - firstPendingTransaction = info.pendingTransactions.first(); - info.pendingTransactions.removeFirst(); + firstPendingTransaction = info.pendingTransactions.takeFirst(); info.activeReadTransactions.add(firstPendingTransaction); firstPendingTransaction->lockAcquired(); } while (!info.pendingTransactions.isEmpty() && info.pendingTransactions.first()->isReadOnly()); diff --git a/WebCore/storage/StorageAreaSync.cpp b/WebCore/storage/StorageAreaSync.cpp index 4c385b7..59f558b 100644 --- a/WebCore/storage/StorageAreaSync.cpp +++ b/WebCore/storage/StorageAreaSync.cpp @@ -29,6 +29,7 @@ #if ENABLE(DOM_STORAGE) #include "EventNames.h" +#include "FileSystem.h" #include "HTMLElement.h" #include "SecurityOrigin.h" #include "SQLiteStatement.h" @@ -62,6 +63,7 @@ StorageAreaSync::StorageAreaSync(PassRefPtr<StorageSyncManager> storageSyncManag , m_clearItemsWhileSyncing(false) , m_syncScheduled(false) , m_syncInProgress(false) + , m_databaseOpenFailed(false) , m_importComplete(false) { ASSERT(isMainThread()); @@ -198,28 +200,47 @@ void StorageAreaSync::syncTimerFired(Timer<StorageAreaSync>*) } } -void StorageAreaSync::performImport() +void StorageAreaSync::openDatabase(OpenDatabaseParamType openingStrategy) { ASSERT(!isMainThread()); ASSERT(!m_database.isOpen()); + ASSERT(!m_databaseOpenFailed); String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier); + if (!fileExists(databaseFilename) && openingStrategy == SkipIfNonExistent) + return; + if (databaseFilename.isEmpty()) { LOG_ERROR("Filename for local storage database is empty - cannot open for persistent storage"); markImported(); + m_databaseOpenFailed = true; return; } if (!m_database.open(databaseFilename)) { LOG_ERROR("Failed to open database file %s for local storage", databaseFilename.utf8().data()); markImported(); + m_databaseOpenFailed = true; return; } if (!m_database.executeCommand("CREATE TABLE IF NOT EXISTS ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value TEXT NOT NULL ON CONFLICT FAIL)")) { LOG_ERROR("Failed to create table ItemTable for local storage"); markImported(); + m_databaseOpenFailed = true; + return; + } +} + +void StorageAreaSync::performImport() +{ + ASSERT(!isMainThread()); + ASSERT(!m_database.isOpen()); + + openDatabase(SkipIfNonExistent); + if (!m_database.isOpen()) { + markImported(); return; } @@ -285,6 +306,10 @@ void StorageAreaSync::sync(bool clearItems, const HashMap<String, String>& items { ASSERT(!isMainThread()); + if (m_databaseOpenFailed) + return; + if (!m_database.isOpen()) + openDatabase(CreateIfNonExistent); if (!m_database.isOpen()) return; diff --git a/WebCore/storage/StorageAreaSync.h b/WebCore/storage/StorageAreaSync.h index 0e46763..d26d399 100644 --- a/WebCore/storage/StorageAreaSync.h +++ b/WebCore/storage/StorageAreaSync.h @@ -75,7 +75,13 @@ namespace WebCore { void performSync(); private: + enum OpenDatabaseParamType { + CreateIfNonExistent, + SkipIfNonExistent + }; + void syncTimerFired(Timer<StorageAreaSync>*); + void openDatabase(OpenDatabaseParamType openingStrategy); void sync(bool clearItems, const HashMap<String, String>& items); const String m_databaseIdentifier; @@ -85,6 +91,7 @@ namespace WebCore { bool m_clearItemsWhileSyncing; bool m_syncScheduled; bool m_syncInProgress; + bool m_databaseOpenFailed; mutable Mutex m_importLock; mutable ThreadCondition m_importCondition; |