diff options
author | Steve Block <steveblock@google.com> | 2010-02-02 14:57:50 +0000 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-02-04 15:06:55 +0000 |
commit | d0825bca7fe65beaee391d30da42e937db621564 (patch) | |
tree | 7461c49eb5844ffd1f35d1ba2c8b7584c1620823 /WebCore/storage | |
parent | 3db770bd97c5a59b6c7574ca80a39e5a51c1defd (diff) | |
download | external_webkit-d0825bca7fe65beaee391d30da42e937db621564.zip external_webkit-d0825bca7fe65beaee391d30da42e937db621564.tar.gz external_webkit-d0825bca7fe65beaee391d30da42e937db621564.tar.bz2 |
Merge webkit.org at r54127 : Initial merge by git
Change-Id: Ib661abb595522f50ea406f72d3a0ce17f7193c82
Diffstat (limited to 'WebCore/storage')
41 files changed, 973 insertions, 187 deletions
diff --git a/WebCore/storage/Database.cpp b/WebCore/storage/Database.cpp index 29dec26..648492f 100644 --- a/WebCore/storage/Database.cpp +++ b/WebCore/storage/Database.cpp @@ -53,8 +53,8 @@ #include "SQLResultSet.h" #include "SQLTransactionClient.h" #include "SQLTransactionCoordinator.h" -#include <wtf/MainThread.h> -#endif + +#endif // ENABLE(DATABASE) #if USE(JSC) #include "JSDOMWindow.h" @@ -73,6 +73,18 @@ const String& Database::databaseInfoTableName() #if ENABLE(DATABASE) +static bool isDatabaseAvailable = false; + +void Database::setIsAvailable(bool available) +{ + isDatabaseAvailable = available; +} + +bool Database::isAvailable() +{ + return isDatabaseAvailable; +} + static Mutex& guidMutex() { // Note: We don't have to use AtomicallyInitializedStatic here because @@ -120,37 +132,41 @@ static const String& databaseVersionKey() static int guidForOriginAndName(const String& origin, const String& name); -PassRefPtr<Database> Database::openDatabase(Document* document, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode& e) +PassRefPtr<Database> Database::openDatabase(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode& e) { - if (!DatabaseTracker::tracker().canEstablishDatabase(document, name, displayName, estimatedSize)) { + if (!DatabaseTracker::tracker().canEstablishDatabase(context, name, displayName, estimatedSize)) { // FIXME: There should be an exception raised here in addition to returning a null Database object. The question has been raised with the WHATWG. - LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), document->securityOrigin()->toString().ascii().data()); + LOG(StorageAPI, "Database %s for origin %s not allowed to be established", name.ascii().data(), context->securityOrigin()->toString().ascii().data()); return 0; } - RefPtr<Database> database = adoptRef(new Database(document, name, expectedVersion, displayName, estimatedSize)); + RefPtr<Database> database = adoptRef(new Database(context, name, expectedVersion, displayName, estimatedSize)); if (!database->openAndVerifyVersion(e)) { - LOG(StorageAPI, "Failed to open and verify version (expected %s) of database %s", expectedVersion.ascii().data(), database->databaseDebugName().ascii().data()); - return 0; + LOG(StorageAPI, "Failed to open and verify version (expected %s) of database %s", expectedVersion.ascii().data(), database->databaseDebugName().ascii().data()); + context->removeOpenDatabase(database.get()); + DatabaseTracker::tracker().removeOpenDatabase(database.get()); + return 0; } - DatabaseTracker::tracker().setDatabaseDetails(document->securityOrigin(), name, displayName, estimatedSize); - - document->setHasOpenDatabases(); + DatabaseTracker::tracker().setDatabaseDetails(context->securityOrigin(), name, displayName, estimatedSize); + context->setHasOpenDatabases(); #if ENABLE(INSPECTOR) - if (Page* page = document->frame()->page()) - page->inspectorController()->didOpenDatabase(database.get(), document->securityOrigin()->host(), name, expectedVersion); + if (context->isDocument()) { + Document* document = static_cast<Document*>(context); + if (Page* page = document->page()) + page->inspectorController()->didOpenDatabase(database.get(), context->securityOrigin()->host(), name, expectedVersion); + } #endif return database; } -Database::Database(Document* document, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) +Database::Database(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) : m_transactionInProgress(false) , m_isTransactionQueueEnabled(true) - , m_document(document) + , m_scriptExecutionContext(context) , m_name(name.crossThreadString()) , m_guid(0) , m_expectedVersion(expectedVersion.crossThreadString()) @@ -160,16 +176,15 @@ Database::Database(Document* document, const String& name, const String& expecte , m_stopped(false) , m_opened(false) { - ASSERT(document); - m_mainThreadSecurityOrigin = document->securityOrigin(); + ASSERT(m_scriptExecutionContext.get()); + m_mainThreadSecurityOrigin = m_scriptExecutionContext->securityOrigin(); m_databaseThreadSecurityOrigin = m_mainThreadSecurityOrigin->threadsafeCopy(); - if (m_name.isNull()) m_name = ""; ScriptController::initializeThreading(); - m_guid = guidForOriginAndName(m_mainThreadSecurityOrigin->toString(), name); + m_guid = guidForOriginAndName(securityOrigin()->toString(), name); { MutexLocker locker(guidMutex()); @@ -183,34 +198,40 @@ Database::Database(Document* document, const String& name, const String& expecte hashSet->add(this); } - ASSERT(m_document->databaseThread()); - - m_filename = DatabaseTracker::tracker().fullPathForDatabase(m_mainThreadSecurityOrigin.get(), m_name); + ASSERT(m_scriptExecutionContext->databaseThread()); + m_filename = DatabaseTracker::tracker().fullPathForDatabase(securityOrigin(), m_name); DatabaseTracker::tracker().addOpenDatabase(this); - m_document->addOpenDatabase(this); + context->addOpenDatabase(this); } -static void derefDocument(void* document) -{ - static_cast<Document*>(document)->deref(); -} +class DerefContextTask : public ScriptExecutionContext::Task { +public: + static PassOwnPtr<DerefContextTask> create() + { + return new DerefContextTask(); + } -Database::~Database() -{ - if (m_document->databaseThread()) - m_document->databaseThread()->unscheduleDatabaseTasks(this); + virtual void performTask(ScriptExecutionContext* context) + { + context->deref(); + } - DatabaseTracker::tracker().removeOpenDatabase(this); - m_document->removeOpenDatabase(this); + virtual bool isCleanupTask() const { return true; } +}; - // Deref m_document on the main thread. - callOnMainThread(derefDocument, m_document.release().releaseRef()); +Database::~Database() +{ + // The reference to the ScriptExecutionContext needs to be cleared on the JavaScript thread. If we're on that thread already, we can just let the RefPtr's destruction do the dereffing. + if (!m_scriptExecutionContext->isContextThread()) { + m_scriptExecutionContext->postTask(DerefContextTask::create()); + m_scriptExecutionContext.release().releaseRef(); + } } bool Database::openAndVerifyVersion(ExceptionCode& e) { - if (!m_document->databaseThread()) + if (!m_scriptExecutionContext->databaseThread()) return false; m_databaseAuthorizer = DatabaseAuthorizer::create(); @@ -218,7 +239,7 @@ bool Database::openAndVerifyVersion(ExceptionCode& e) DatabaseTaskSynchronizer synchronizer; OwnPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this, &synchronizer, e, success); - m_document->databaseThread()->scheduleImmediateTask(task.release()); + m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release()); synchronizer.waitForTaskCompletion(); return success; @@ -313,49 +334,80 @@ bool Database::versionMatchesExpected() const void Database::markAsDeletedAndClose() { - if (m_deleted || !m_document->databaseThread()) + if (m_deleted || !m_scriptExecutionContext->databaseThread()) return; LOG(StorageAPI, "Marking %s (%p) as deleted", stringIdentifier().ascii().data(), this); m_deleted = true; - if (m_document->databaseThread()->terminationRequested()) { + if (m_scriptExecutionContext->databaseThread()->terminationRequested()) { LOG(StorageAPI, "Database handle %p is on a terminated DatabaseThread, cannot be marked for normal closure\n", this); return; } - m_document->databaseThread()->unscheduleDatabaseTasks(this); + m_scriptExecutionContext->databaseThread()->unscheduleDatabaseTasks(this); DatabaseTaskSynchronizer synchronizer; OwnPtr<DatabaseCloseTask> task = DatabaseCloseTask::create(this, &synchronizer); - m_document->databaseThread()->scheduleImmediateTask(task.release()); + m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release()); synchronizer.waitForTaskCompletion(); } +class ContextRemoveOpenDatabaseTask : public ScriptExecutionContext::Task { +public: + static PassOwnPtr<ContextRemoveOpenDatabaseTask> create(PassRefPtr<Database> database) + { + return new ContextRemoveOpenDatabaseTask(database); + } + + virtual void performTask(ScriptExecutionContext* context) + { + context->removeOpenDatabase(m_database.get()); + DatabaseTracker::tracker().removeOpenDatabase(m_database.get()); + } + + virtual bool isCleanupTask() const { return true; } + +private: + ContextRemoveOpenDatabaseTask(PassRefPtr<Database> database) + : m_database(database) + { + } + + RefPtr<Database> m_database; +}; + void Database::close() { - if (m_opened) { - ASSERT(m_document->databaseThread()); - ASSERT(currentThread() == document()->databaseThread()->getThreadID()); - m_sqliteDatabase.close(); - m_document->databaseThread()->recordDatabaseClosed(this); - m_opened = false; - - { - MutexLocker locker(guidMutex()); - - HashSet<Database*>* hashSet = guidToDatabaseMap().get(m_guid); - ASSERT(hashSet); - ASSERT(hashSet->contains(this)); - hashSet->remove(this); - if (hashSet->isEmpty()) { - guidToDatabaseMap().remove(m_guid); - delete hashSet; - guidToVersionMap().remove(m_guid); - } + RefPtr<Database> protect = this; + + if (!m_opened) + return; + + ASSERT(m_scriptExecutionContext->databaseThread()); + ASSERT(currentThread() == m_scriptExecutionContext->databaseThread()->getThreadID()); + m_sqliteDatabase.close(); + // Must ref() before calling databaseThread()->recordDatabaseClosed(). + m_scriptExecutionContext->databaseThread()->recordDatabaseClosed(this); + m_opened = false; + + { + MutexLocker locker(guidMutex()); + + HashSet<Database*>* hashSet = guidToDatabaseMap().get(m_guid); + ASSERT(hashSet); + ASSERT(hashSet->contains(this)); + hashSet->remove(this); + if (hashSet->isEmpty()) { + guidToDatabaseMap().remove(m_guid); + delete hashSet; + guidToVersionMap().remove(m_guid); } } + + m_scriptExecutionContext->databaseThread()->unscheduleDatabaseTasks(this); + m_scriptExecutionContext->postTask(ContextRemoveOpenDatabaseTask::create(this)); } void Database::stop() @@ -451,10 +503,6 @@ bool Database::performOpenAndVerify(ExceptionCode& e) return false; } - m_opened = true; - if (m_document->databaseThread()) - m_document->databaseThread()->recordDatabaseOpen(this); - ASSERT(m_databaseAuthorizer); m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer); m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime); @@ -475,6 +523,8 @@ bool Database::performOpenAndVerify(ExceptionCode& e) if (!m_sqliteDatabase.executeCommand("CREATE TABLE " + databaseInfoTableName() + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) { LOG_ERROR("Unable to create table %s in database %s", databaseInfoTableName().ascii().data(), databaseDebugName().ascii().data()); e = INVALID_STATE_ERR; + // Close the handle to the database file. + m_sqliteDatabase.close(); return false; } } @@ -482,6 +532,8 @@ bool Database::performOpenAndVerify(ExceptionCode& e) if (!getVersionFromDatabase(currentVersion)) { LOG_ERROR("Failed to get current version from database %s", databaseDebugName().ascii().data()); e = INVALID_STATE_ERR; + // Close the handle to the database file. + m_sqliteDatabase.close(); return false; } if (currentVersion.length()) { @@ -491,6 +543,8 @@ bool Database::performOpenAndVerify(ExceptionCode& e) if (!setVersionInDatabase(m_expectedVersion)) { LOG_ERROR("Failed to set version %s in database %s", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data()); e = INVALID_STATE_ERR; + // Close the handle to the database file. + m_sqliteDatabase.close(); return false; } currentVersion = m_expectedVersion; @@ -511,9 +565,17 @@ bool Database::performOpenAndVerify(ExceptionCode& e) LOG(StorageAPI, "page expects version %s from database %s, which actually has version name %s - openDatabase() call will fail", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data(), currentVersion.ascii().data()); e = INVALID_STATE_ERR; + // Close the handle to the database file. + m_sqliteDatabase.close(); return false; } + // All checks passed and we still have a handle to this database file. + // Make sure DatabaseThread closes it when DatabaseThread goes away. + m_opened = true; + if (m_scriptExecutionContext->databaseThread()) + m_scriptExecutionContext->databaseThread()->recordDatabaseOpen(this); + return true; } @@ -546,32 +608,52 @@ void Database::scheduleTransaction() m_transactionQueue.removeFirst(); } - if (transaction && m_document->databaseThread()) { + if (transaction && m_scriptExecutionContext->databaseThread()) { OwnPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction); LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for transaction %p\n", task.get(), task->transaction()); m_transactionInProgress = true; - m_document->databaseThread()->scheduleTask(task.release()); + m_scriptExecutionContext->databaseThread()->scheduleTask(task.release()); } else m_transactionInProgress = false; } void Database::scheduleTransactionStep(SQLTransaction* transaction, bool immediately) { - if (!m_document->databaseThread()) + if (!m_scriptExecutionContext->databaseThread()) return; OwnPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction); LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get()); if (immediately) - m_document->databaseThread()->scheduleImmediateTask(task.release()); + m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release()); else - m_document->databaseThread()->scheduleTask(task.release()); + m_scriptExecutionContext->databaseThread()->scheduleTask(task.release()); } +class DeliverPendingCallbackTask : public ScriptExecutionContext::Task { +public: + static PassOwnPtr<DeliverPendingCallbackTask> create(PassRefPtr<SQLTransaction> transaction) + { + return new DeliverPendingCallbackTask(transaction); + } + + virtual void performTask(ScriptExecutionContext*) + { + m_transaction->performPendingCallback(); + } + +private: + DeliverPendingCallbackTask(PassRefPtr<SQLTransaction> transaction) + : m_transaction(transaction) + { + } + + RefPtr<SQLTransaction> m_transaction; +}; + void Database::scheduleTransactionCallback(SQLTransaction* transaction) { - transaction->ref(); - callOnMainThread(deliverPendingCallback, transaction); + m_scriptExecutionContext->postTask(DeliverPendingCallbackTask::create(transaction)); } Vector<String> Database::performGetTableNames() @@ -605,12 +687,12 @@ Vector<String> Database::performGetTableNames() SQLTransactionClient* Database::transactionClient() const { - return m_document->databaseThread()->transactionClient(); + return m_scriptExecutionContext->databaseThread()->transactionClient(); } SQLTransactionCoordinator* Database::transactionCoordinator() const { - return m_document->databaseThread()->transactionCoordinator(); + return m_scriptExecutionContext->databaseThread()->transactionCoordinator(); } String Database::version() const @@ -621,25 +703,18 @@ String Database::version() const return guidToVersionMap().get(m_guid).threadsafeCopy(); } -void Database::deliverPendingCallback(void* context) -{ - SQLTransaction* transaction = static_cast<SQLTransaction*>(context); - transaction->performPendingCallback(); - transaction->deref(); // Was ref'd in scheduleTransactionCallback(). -} - Vector<String> Database::tableNames() { // FIXME: Not using threadsafeCopy on these strings looks ok since threads take strict turns // in dealing with them. However, if the code changes, this may not be true anymore. Vector<String> result; - if (!m_document->databaseThread()) + if (!m_scriptExecutionContext->databaseThread()) return result; DatabaseTaskSynchronizer synchronizer; OwnPtr<DatabaseTableNamesTask> task = DatabaseTableNamesTask::create(this, &synchronizer, result); - m_document->databaseThread()->scheduleImmediateTask(task.release()); + m_scriptExecutionContext->databaseThread()->scheduleImmediateTask(task.release()); synchronizer.waitForTaskCompletion(); return result; @@ -655,9 +730,9 @@ void Database::setExpectedVersion(const String& version) SecurityOrigin* Database::securityOrigin() const { - if (isMainThread()) + if (scriptExecutionContext()->isContextThread()) return m_mainThreadSecurityOrigin.get(); - if (currentThread() == document()->databaseThread()->getThreadID()) + if (currentThread() == m_scriptExecutionContext->databaseThread()->getThreadID()) return m_databaseThreadSecurityOrigin.get(); return 0; } @@ -685,6 +760,6 @@ String Database::fileName() const return m_filename.threadsafeCopy(); } -#endif +#endif // ENABLE(DATABASE) -} +} // namespace WebCore diff --git a/WebCore/storage/Database.h b/WebCore/storage/Database.h index 61c9b66..0d7f33c 100644 --- a/WebCore/storage/Database.h +++ b/WebCore/storage/Database.h @@ -52,7 +52,7 @@ namespace WebCore { class DatabaseAuthorizer; class DatabaseThread; -class Document; +class ScriptExecutionContext; class SQLResultSet; class SQLTransactionCallback; class SQLTransactionClient; @@ -67,10 +67,13 @@ class Database : public ThreadSafeShared<Database> { friend class SQLStatement; friend class SQLTransaction; public: + static void setIsAvailable(bool); + static bool isAvailable(); + ~Database(); // Direct support for the DOM API - static PassRefPtr<Database> openDatabase(Document* document, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode&); + static PassRefPtr<Database> openDatabase(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, ExceptionCode&); String version() const; void changeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback, @@ -87,7 +90,7 @@ public: Vector<String> tableNames(); - Document* document() const { return m_document.get(); } + ScriptExecutionContext* scriptExecutionContext() const { return m_scriptExecutionContext.get(); } SecurityOrigin* securityOrigin() const; String stringIdentifier() const; String displayName() const; @@ -123,8 +126,9 @@ public: SQLTransactionCoordinator* transactionCoordinator() const; private: - Database(Document* document, const String& name, const String& expectedVersion, - const String& displayName, unsigned long estimatedSize); + Database(ScriptExecutionContext* context, const String& name, + const String& expectedVersion, const String& displayName, + unsigned long estimatedSize); bool openAndVerifyVersion(ExceptionCode&); @@ -139,7 +143,7 @@ private: static void deliverPendingCallback(void*); - RefPtr<Document> m_document; + RefPtr<ScriptExecutionContext> m_scriptExecutionContext; RefPtr<SecurityOrigin> m_mainThreadSecurityOrigin; RefPtr<SecurityOrigin> m_databaseThreadSecurityOrigin; String m_name; diff --git a/WebCore/storage/Database.idl b/WebCore/storage/Database.idl index 6ca9c95..c8a537c 100644 --- a/WebCore/storage/Database.idl +++ b/WebCore/storage/Database.idl @@ -29,7 +29,8 @@ module storage { interface [ - Conditional=DATABASE + Conditional=DATABASE, + OmitConstructor ] Database { readonly attribute DOMString version; [Custom] void changeVersion(in DOMString oldVersion, in DOMString newVersion, in SQLTransactionCallback callback, in SQLTransactionErrorCallback errorCallback, in VoidCallback successCallback); diff --git a/WebCore/storage/DatabaseAuthorizer.cpp b/WebCore/storage/DatabaseAuthorizer.cpp index 93f9106..d87d4d9 100644 --- a/WebCore/storage/DatabaseAuthorizer.cpp +++ b/WebCore/storage/DatabaseAuthorizer.cpp @@ -38,6 +38,7 @@ DatabaseAuthorizer::DatabaseAuthorizer() : m_securityEnabled(false) { reset(); + addWhitelistedFunctions(); } void DatabaseAuthorizer::reset() @@ -47,6 +48,69 @@ void DatabaseAuthorizer::reset() m_readOnly = false; } +void DatabaseAuthorizer::addWhitelistedFunctions() +{ + // SQLite functions used to help implement some operations + // ALTER TABLE helpers + m_whitelistedFunctions.add("sqlite_rename_table"); + m_whitelistedFunctions.add("sqlite_rename_trigger"); + // GLOB helpers + m_whitelistedFunctions.add("glob"); + + // SQLite core functions + m_whitelistedFunctions.add("abs"); + m_whitelistedFunctions.add("changes"); + m_whitelistedFunctions.add("coalesce"); + m_whitelistedFunctions.add("glob"); + m_whitelistedFunctions.add("ifnull"); + m_whitelistedFunctions.add("hex"); + m_whitelistedFunctions.add("last_insert_rowid"); + m_whitelistedFunctions.add("length"); + m_whitelistedFunctions.add("like"); + m_whitelistedFunctions.add("lower"); + m_whitelistedFunctions.add("ltrim"); + m_whitelistedFunctions.add("max"); + m_whitelistedFunctions.add("min"); + m_whitelistedFunctions.add("nullif"); + m_whitelistedFunctions.add("quote"); + m_whitelistedFunctions.add("replace"); + m_whitelistedFunctions.add("round"); + m_whitelistedFunctions.add("rtrim"); + m_whitelistedFunctions.add("soundex"); + m_whitelistedFunctions.add("sqlite_source_id"); + m_whitelistedFunctions.add("sqlite_version"); + m_whitelistedFunctions.add("substr"); + m_whitelistedFunctions.add("total_changes"); + m_whitelistedFunctions.add("trim"); + m_whitelistedFunctions.add("typeof"); + m_whitelistedFunctions.add("upper"); + m_whitelistedFunctions.add("zeroblob"); + + // SQLite date and time functions + m_whitelistedFunctions.add("date"); + m_whitelistedFunctions.add("time"); + m_whitelistedFunctions.add("datetime"); + m_whitelistedFunctions.add("julianday"); + m_whitelistedFunctions.add("strftime"); + + // SQLite aggregate functions + // max() and min() are already in the list + m_whitelistedFunctions.add("avg"); + m_whitelistedFunctions.add("count"); + m_whitelistedFunctions.add("group_concat"); + m_whitelistedFunctions.add("sum"); + m_whitelistedFunctions.add("total"); + + // SQLite FTS functions + m_whitelistedFunctions.add("snippet"); + m_whitelistedFunctions.add("offsets"); + m_whitelistedFunctions.add("optimize"); + + // SQLite ICU functions + // like(), lower() and upper() are already in the list + m_whitelistedFunctions.add("regexp"); +} + int DatabaseAuthorizer::createTable(const String& tableName) { if (m_readOnly && m_securityEnabled) @@ -278,11 +342,11 @@ int DatabaseAuthorizer::allowDetach(const String&) return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; } -int DatabaseAuthorizer::allowFunction(const String&) +int DatabaseAuthorizer::allowFunction(const String& functionName) { - // FIXME: Are there any of these we need to prevent? One might guess current_date, current_time, current_timestamp because - // they would violate the "sandbox environment" part of 4.11.3, but scripts can generate the local client side information via - // javascript directly, anyways. Are there any other built-ins we need to be worried about? + if (m_securityEnabled && !m_whitelistedFunctions.contains(functionName)) + return SQLAuthDeny; + return SQLAuthAllow; } diff --git a/WebCore/storage/DatabaseAuthorizer.h b/WebCore/storage/DatabaseAuthorizer.h index 248b659..037409e 100644 --- a/WebCore/storage/DatabaseAuthorizer.h +++ b/WebCore/storage/DatabaseAuthorizer.h @@ -28,6 +28,8 @@ #ifndef DatabaseAuthorizer_h #define DatabaseAuthorizer_h +#include "StringHash.h" +#include <wtf/HashSet.h> #include <wtf/PassRefPtr.h> #include <wtf/Threading.h> @@ -94,12 +96,15 @@ public: private: DatabaseAuthorizer(); + void addWhitelistedFunctions(); int denyBasedOnTableName(const String&); bool m_securityEnabled : 1; bool m_lastActionWasInsert : 1; bool m_lastActionChangedDatabase : 1; bool m_readOnly : 1; + + HashSet<String, CaseFoldingHash> m_whitelistedFunctions; }; } // namespace WebCore diff --git a/WebCore/storage/DatabaseTask.h b/WebCore/storage/DatabaseTask.h index 97a23c7..998e373 100644 --- a/WebCore/storage/DatabaseTask.h +++ b/WebCore/storage/DatabaseTask.h @@ -50,16 +50,15 @@ 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 { - friend class DatabaseTask; public: DatabaseTaskSynchronizer(); // Called from main thread to wait until task is completed. void waitForTaskCompletion(); -private: // Called by the task. void taskCompleted(); +private: bool m_taskCompleted; Mutex m_synchronousMutex; diff --git a/WebCore/storage/DatabaseThread.cpp b/WebCore/storage/DatabaseThread.cpp index 12e9251..ec4c6d1 100644 --- a/WebCore/storage/DatabaseThread.cpp +++ b/WebCore/storage/DatabaseThread.cpp @@ -44,6 +44,7 @@ DatabaseThread::DatabaseThread() : m_threadID(0) , m_transactionClient(new SQLTransactionClient()) , m_transactionCoordinator(new SQLTransactionCoordinator()) + , m_cleanupSync(0) { m_selfRef = this; } @@ -51,6 +52,7 @@ DatabaseThread::DatabaseThread() DatabaseThread::~DatabaseThread() { // FIXME: Any cleanup required here? Since the thread deletes itself after running its detached course, I don't think so. Lets be sure. + ASSERT(terminationRequested()); } bool DatabaseThread::start() @@ -65,8 +67,10 @@ bool DatabaseThread::start() return m_threadID; } -void DatabaseThread::requestTermination() +void DatabaseThread::requestTermination(DatabaseTaskSynchronizer *cleanupSync) { + ASSERT(!m_cleanupSync); + m_cleanupSync = cleanupSync; LOG(StorageAPI, "DatabaseThread %p was asked to terminate\n", this); m_queue.kill(); } @@ -115,9 +119,14 @@ void* DatabaseThread::databaseThread() // Detach the thread so its resources are no longer of any concern to anyone else detachThread(m_threadID); + DatabaseTaskSynchronizer* cleanupSync = m_cleanupSync; + // Clear the self refptr, possibly resulting in deletion m_selfRef = 0; + if (cleanupSync) // Someone wanted to know when we were done cleaning up. + cleanupSync->taskCompleted(); + return 0; } @@ -162,6 +171,5 @@ void DatabaseThread::unscheduleDatabaseTasks(Database* database) SameDatabasePredicate predicate(database); m_queue.removeIf(predicate); } - } // namespace WebCore #endif diff --git a/WebCore/storage/DatabaseThread.h b/WebCore/storage/DatabaseThread.h index 269a633..3702619 100644 --- a/WebCore/storage/DatabaseThread.h +++ b/WebCore/storage/DatabaseThread.h @@ -43,6 +43,7 @@ namespace WebCore { class Database; class DatabaseTask; +class DatabaseTaskSynchronizer; class Document; class SQLTransactionClient; class SQLTransactionCoordinator; @@ -53,7 +54,7 @@ public: ~DatabaseThread(); bool start(); - void requestTermination(); + void requestTermination(DatabaseTaskSynchronizer* cleanupSync); bool terminationRequested() const; void scheduleTask(PassOwnPtr<DatabaseTask>); @@ -85,6 +86,7 @@ private: OwnPtr<SQLTransactionClient> m_transactionClient; OwnPtr<SQLTransactionCoordinator> m_transactionCoordinator; + DatabaseTaskSynchronizer* m_cleanupSync; }; } // namespace WebCore diff --git a/WebCore/storage/DatabaseTracker.cpp b/WebCore/storage/DatabaseTracker.cpp index c0c4242..bed83a7 100644 --- a/WebCore/storage/DatabaseTracker.cpp +++ b/WebCore/storage/DatabaseTracker.cpp @@ -31,14 +31,15 @@ #if ENABLE(DATABASE) +#include "Chrome.h" #include "ChromeClient.h" #include "Database.h" #include "DatabaseThread.h" #include "DatabaseTrackerClient.h" -#include "Document.h" #include "Logging.h" #include "OriginQuotaManager.h" #include "Page.h" +#include "ScriptExecutionContext.h" #include "SecurityOrigin.h" #include "SecurityOriginHash.h" #include "SQLiteFileSystem.h" @@ -119,7 +120,7 @@ void DatabaseTracker::openTrackerDatabase(bool createIfDoesNotExist) } } -bool DatabaseTracker::canEstablishDatabase(Document* document, const String& name, const String& displayName, unsigned long estimatedSize) +bool DatabaseTracker::canEstablishDatabase(ScriptExecutionContext* context, const String& name, const String& displayName, unsigned long estimatedSize) { ASSERT(currentThread() == m_thread); @@ -127,9 +128,9 @@ bool DatabaseTracker::canEstablishDatabase(Document* document, const String& nam // can run on the database thread later. populateOrigins(); - SecurityOrigin* origin = document->securityOrigin(); + SecurityOrigin* origin = context->securityOrigin(); - // Since we're imminently opening a database within this Document's origin, make sure this origin is being tracked by the QuotaTracker + // Since we're imminently opening a database within this context's origin, make sure this origin is being tracked by the QuotaTracker // by fetching it's current usage now unsigned long long usage = usageForOrigin(origin); @@ -146,12 +147,9 @@ bool DatabaseTracker::canEstablishDatabase(Document* document, const String& nam // Give the chrome client a chance to increase the quota. // Temporarily make the details of the proposed database available, so the client can get at them. - Page* page = document->page(); - if (!page) - return false; pair<SecurityOrigin*, DatabaseDetails> details(origin, DatabaseDetails(name, displayName, estimatedSize, 0)); m_proposedDatabase = &details; - page->chrome()->client()->exceededDatabaseQuota(document->frame(), name); + context->databaseExceededQuota(name); m_proposedDatabase = 0; // If the database will fit now, allow its creation. @@ -185,7 +183,7 @@ bool DatabaseTracker::hasEntryForDatabase(SecurityOrigin* origin, const String& unsigned long long DatabaseTracker::getMaxSizeForDatabase(const Database* database) { - ASSERT(currentThread() == database->document()->databaseThread()->getThreadID()); + ASSERT(currentThread() == database->scriptExecutionContext()->databaseThread()->getThreadID()); // The maximum size for a database is the full quota for its origin, minus the current usage within the origin, // plus the current usage of the given database Locker<OriginQuotaManager> locker(originQuotaManager()); diff --git a/WebCore/storage/DatabaseTracker.h b/WebCore/storage/DatabaseTracker.h index c87b26a..38a3418 100644 --- a/WebCore/storage/DatabaseTracker.h +++ b/WebCore/storage/DatabaseTracker.h @@ -37,6 +37,7 @@ #include "DatabaseDetails.h" #include "SQLiteDatabase.h" #include "StringHash.h" +#include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> #endif // !PLATFORM(CHROMIUM) @@ -44,7 +45,7 @@ namespace WebCore { class Database; -class Document; +class ScriptExecutionContext; class SecurityOrigin; #if !PLATFORM(CHROMIUM) @@ -58,8 +59,11 @@ struct SecurityOriginTraits; class DatabaseTracker : public Noncopyable { public: static DatabaseTracker& tracker(); + // FIXME: Due to workers having multiple threads in a single process sharing + // a DatabaseTracker, this singleton will have to be synchronized or moved + // to TLS. - bool canEstablishDatabase(Document*, const String& name, const String& displayName, unsigned long estimatedSize); + bool canEstablishDatabase(ScriptExecutionContext*, const String& name, const String& displayName, unsigned long estimatedSize); void setDatabaseDetails(SecurityOrigin*, const String& name, const String& displayName, unsigned long estimatedSize); String fullPathForDatabase(SecurityOrigin*, const String& name, bool createIfDoesNotExist = true); diff --git a/WebCore/storage/IDBDatabaseError.h b/WebCore/storage/IDBDatabaseError.h new file mode 100644 index 0000000..e8fd2dd --- /dev/null +++ b/WebCore/storage/IDBDatabaseError.h @@ -0,0 +1,64 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 IDBDatabaseError_h +#define IDBDatabaseError_h + +#include "PlatformString.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +#if ENABLE(INDEXED_DATABASE) + +namespace WebCore { + +class IDBDatabaseError : public RefCounted<IDBDatabaseError> { +public: + static PassRefPtr<IDBDatabaseError> create() + { + return adoptRef(new IDBDatabaseError()); + } + ~IDBDatabaseError() { } + + unsigned short code() const { return m_code; } + void setCode(unsigned short value) { m_code = value; } + String message() const { return m_message; } + void setMessage(const String& value) { m_message = value; } + +private: + IDBDatabaseError() { } + + unsigned short m_code; + String m_message; +}; + +} // namespace WebCore + +#endif + +#endif // IDBDatabaseError_h + diff --git a/WebCore/storage/IDBDatabaseError.idl b/WebCore/storage/IDBDatabaseError.idl new file mode 100644 index 0000000..6c6019c --- /dev/null +++ b/WebCore/storage/IDBDatabaseError.idl @@ -0,0 +1,37 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 + ] IDBDatabaseError { + attribute unsigned short code; + attribute DOMString message; + }; + +} diff --git a/WebCore/storage/IDBDatabaseException.h b/WebCore/storage/IDBDatabaseException.h new file mode 100644 index 0000000..d94a7f9 --- /dev/null +++ b/WebCore/storage/IDBDatabaseException.h @@ -0,0 +1,64 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 IDBDatabaseException_h +#define IDBDatabaseException_h + +#include "PlatformString.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +#if ENABLE(INDEXED_DATABASE) + +namespace WebCore { + +class IDBDatabaseException : public RefCounted<IDBDatabaseException> { +public: + static PassRefPtr<IDBDatabaseException> create() + { + return adoptRef(new IDBDatabaseException()); + } + ~IDBDatabaseException() { } + + unsigned short code() const { return m_code; } + void setCode(unsigned short value) { m_code = value; } + String message() const { return m_message; } + void setMessage(const String& value) { m_message = value; } + +private: + IDBDatabaseException() { } + + unsigned short m_code; + String m_message; +}; + +} // namespace WebCore + +#endif + +#endif // IDBDatabaseException_h + diff --git a/WebCore/storage/IDBDatabaseException.idl b/WebCore/storage/IDBDatabaseException.idl new file mode 100644 index 0000000..898e5f9 --- /dev/null +++ b/WebCore/storage/IDBDatabaseException.idl @@ -0,0 +1,48 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 + ] IDBDatabaseException { + const unsigned short UNKNOWN_ERR = 0; + const unsigned short NON_TRANSIENT_ERR = 1; + const unsigned short NOT_FOUND_ERR = 2; + const unsigned short CONSTRAINT_ERR = 3; + const unsigned short DATA_ERR = 4; + const unsigned short NOT_ALLOWED_ERR = 5; + const unsigned short SERIAL_ERR = 11; + const unsigned short RECOVERABLE_ERR = 21; + const unsigned short TRANSIENT_ERR = 31; + const unsigned short TIMEOUT_ERR = 32; + const unsigned short DEADLOCK_ERR = 33; + attribute unsigned short code; + attribute DOMString message; + }; + +} diff --git a/WebCore/storage/IDBRequest.cpp b/WebCore/storage/IDBRequest.cpp new file mode 100644 index 0000000..1a20499 --- /dev/null +++ b/WebCore/storage/IDBRequest.cpp @@ -0,0 +1,64 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 "IDBRequest.h" + +#if ENABLE(INDEXED_DATABASE) + +#include "IDBDatabaseError.h" +#include "SerializedScriptValue.h" + +namespace WebCore { + +IDBRequest::IDBRequest(ScriptExecutionContext* context) + : ActiveDOMObject(context, this) +{ +} + +IDBRequest::~IDBRequest() +{ +} + +void IDBRequest::abort() +{ +} + +EventTargetData* IDBRequest::eventTargetData() +{ + return 0; +} + +EventTargetData* IDBRequest::ensureEventTargetData() +{ + return 0; +} + +} // namespace WebCore + +#endif // ENABLE(INDEXED_DATABASE) + diff --git a/WebCore/storage/IDBRequest.h b/WebCore/storage/IDBRequest.h new file mode 100644 index 0000000..5f00aa8 --- /dev/null +++ b/WebCore/storage/IDBRequest.h @@ -0,0 +1,88 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 IDBRequest_h +#define IDBRequest_h + +#include "ActiveDOMObject.h" +#include "EventTarget.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +#if ENABLE(INDEXED_DATABASE) + +namespace WebCore { + +class IDBDatabaseError; +class SerializedScriptValue; + +class IDBRequest : public RefCounted<IDBRequest>, public ActiveDOMObject, public EventTarget { +public: + static PassRefPtr<IDBRequest> create(ScriptExecutionContext* context) + { + return adoptRef(new IDBRequest(context)); + } + ~IDBRequest(); + + void abort(); + unsigned short readyState() const { return m_readyState; } + IDBDatabaseError* error() const { return m_error.get(); } + SerializedScriptValue* result() const { return m_result.get(); } + + DEFINE_ATTRIBUTE_EVENT_LISTENER(success); + DEFINE_ATTRIBUTE_EVENT_LISTENER(error); + + using RefCounted<IDBRequest>::ref; + using RefCounted<IDBRequest>::deref; + + // EventTarget interface + virtual ScriptExecutionContext* scriptExecutionContext() const { return ActiveDOMObject::scriptExecutionContext(); } + virtual IDBRequest* toIDBRequest() { return this; } + +private: + explicit IDBRequest(ScriptExecutionContext* context); + + // EventTarget interface + virtual void refEventTarget() { ref(); } + virtual void derefEventTarget() { deref(); } + virtual EventTargetData* eventTargetData(); + virtual EventTargetData* ensureEventTargetData(); + + unsigned short m_readyState; + RefPtr<IDBDatabaseError> m_error; + RefPtr<SerializedScriptValue> m_result; + + EventTargetData m_eventTargetData; +}; + +} // namespace WebCore + +#endif + +#endif // IDBRequest_h + diff --git a/WebCore/storage/IDBRequest.idl b/WebCore/storage/IDBRequest.idl new file mode 100644 index 0000000..b34184c --- /dev/null +++ b/WebCore/storage/IDBRequest.idl @@ -0,0 +1,45 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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, + EventTarget + ] IDBRequest { + void abort(); + const unsigned short INITIAL = 0; + const unsigned short LOADING = 1; + const unsigned short DONE = 2; + readonly attribute unsigned short readyState; + readonly attribute IDBDatabaseError error; + readonly attribute [CustomGetter] any result; + attribute EventListener onsuccess; + attribute EventListener onerror; + }; + +} diff --git a/WebCore/storage/IndexedDatabaseRequest.cpp b/WebCore/storage/IndexedDatabaseRequest.cpp new file mode 100644 index 0000000..827493b --- /dev/null +++ b/WebCore/storage/IndexedDatabaseRequest.cpp @@ -0,0 +1,53 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 "IndexedDatabaseRequest.h" + +#if ENABLE(INDEXED_DATABASE) + +#include "ExceptionCode.h" +#include "IDBRequest.h" + +namespace WebCore { + +IndexedDatabaseRequest::IndexedDatabaseRequest() +{ +} + +IndexedDatabaseRequest::~IndexedDatabaseRequest() +{ +} + +void IndexedDatabaseRequest::open(const String& name, const String& description, bool modifyDatabase, ExceptionCode& exception) +{ +} + +} // namespace WebCore + +#endif // ENABLE(INDEXED_DATABASE) + diff --git a/WebCore/storage/IndexedDatabaseRequest.h b/WebCore/storage/IndexedDatabaseRequest.h new file mode 100644 index 0000000..74aada3 --- /dev/null +++ b/WebCore/storage/IndexedDatabaseRequest.h @@ -0,0 +1,65 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 IndexedDatabaseRequest_h +#define IndexedDatabaseRequest_h + +#include "ExceptionCode.h" +#include "PlatformString.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +#if ENABLE(INDEXED_DATABASE) + +namespace WebCore { + +class IDBRequest; + +class IndexedDatabaseRequest : public RefCounted<IndexedDatabaseRequest> { +public: + static PassRefPtr<IndexedDatabaseRequest> create() + { + return adoptRef(new IndexedDatabaseRequest()); + } + ~IndexedDatabaseRequest(); + + IDBRequest* request() const { return m_request.get(); } + void open(const String& name, const String& description, bool modifyDatabase, ExceptionCode&); + +private: + IndexedDatabaseRequest(); + + PassRefPtr<IDBRequest> m_request; +}; + +} // namespace WebCore + +#endif + +#endif // IndexedDatabaseRequest_h + diff --git a/WebCore/storage/IndexedDatabaseRequest.idl b/WebCore/storage/IndexedDatabaseRequest.idl new file mode 100644 index 0000000..b1fc7da --- /dev/null +++ b/WebCore/storage/IndexedDatabaseRequest.idl @@ -0,0 +1,38 @@ +/* + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 + ] IndexedDatabaseRequest { + readonly attribute IDBRequest request; + [Custom] void open(in DOMString name, in DOMString description, in optional boolean modifyDatabase) + raises(IDBDatabaseException); + }; + +} diff --git a/WebCore/storage/SQLError.idl b/WebCore/storage/SQLError.idl index d889c5b..503fe6f 100644 --- a/WebCore/storage/SQLError.idl +++ b/WebCore/storage/SQLError.idl @@ -29,7 +29,8 @@ module storage { interface [ - Conditional=DATABASE + Conditional=DATABASE, + OmitConstructor ] SQLError { readonly attribute unsigned long code; readonly attribute DOMString message; diff --git a/WebCore/storage/SQLResultSet.idl b/WebCore/storage/SQLResultSet.idl index 1db07cd..c98fff6 100644 --- a/WebCore/storage/SQLResultSet.idl +++ b/WebCore/storage/SQLResultSet.idl @@ -29,7 +29,8 @@ module storage { interface [ - Conditional=DATABASE + Conditional=DATABASE, + OmitConstructor ] SQLResultSet { readonly attribute SQLResultSetRowList rows; diff --git a/WebCore/storage/SQLResultSetRowList.idl b/WebCore/storage/SQLResultSetRowList.idl index 6a477e9..7ae7a9c 100644 --- a/WebCore/storage/SQLResultSetRowList.idl +++ b/WebCore/storage/SQLResultSetRowList.idl @@ -29,7 +29,8 @@ module storage { interface [ - Conditional=DATABASE + Conditional=DATABASE, + OmitConstructor ] SQLResultSetRowList { readonly attribute unsigned long length; [Custom] DOMObject item(in unsigned long index); diff --git a/WebCore/storage/SQLTransaction.cpp b/WebCore/storage/SQLTransaction.cpp index 165685b..de615ca 100644 --- a/WebCore/storage/SQLTransaction.cpp +++ b/WebCore/storage/SQLTransaction.cpp @@ -35,11 +35,11 @@ #include "Database.h" #include "DatabaseAuthorizer.h" #include "DatabaseDetails.h" -#include "Document.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" @@ -94,8 +94,7 @@ void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValu bool readOnlyMode = m_readOnly; if (!readOnlyMode) { - Page* page = m_database->document()->page(); - if (!page || page->settings()->privateBrowsingEnabled()) + if (m_database->scriptExecutionContext()->isDatabaseReadOnly()) readOnlyMode = true; } diff --git a/WebCore/storage/SQLTransaction.idl b/WebCore/storage/SQLTransaction.idl index 5d4885c..7d694e8 100644 --- a/WebCore/storage/SQLTransaction.idl +++ b/WebCore/storage/SQLTransaction.idl @@ -29,7 +29,8 @@ module storage { interface [ - Conditional=DATABASE + Conditional=DATABASE, + OmitConstructor ] SQLTransaction { [Custom] void executeSql(in DOMString sqlStatement, in ObjectArray arguments, in SQLStatementCallback callback, in SQLStatementErrorCallback errorCallback); }; diff --git a/WebCore/storage/SQLTransactionClient.cpp b/WebCore/storage/SQLTransactionClient.cpp index 5918bd8..6064c99 100644 --- a/WebCore/storage/SQLTransactionClient.cpp +++ b/WebCore/storage/SQLTransactionClient.cpp @@ -31,6 +31,9 @@ #include "config.h" #include "SQLTransactionClient.h" +#if ENABLE(DATABASE) + +#include "Chrome.h" #include "ChromeClient.h" #include "Database.h" #include "DatabaseThread.h" @@ -44,7 +47,7 @@ namespace WebCore { void SQLTransactionClient::didCommitTransaction(SQLTransaction* transaction) { - ASSERT(currentThread() == transaction->database()->document()->databaseThread()->getThreadID()); + ASSERT(currentThread() == transaction->database()->scriptExecutionContext()->databaseThread()->getThreadID()); Database* database = transaction->database(); DatabaseTracker::tracker().scheduleNotifyDatabaseChanged( database->securityOrigin(), database->stringIdentifier()); @@ -52,7 +55,7 @@ void SQLTransactionClient::didCommitTransaction(SQLTransaction* transaction) void SQLTransactionClient::didExecuteStatement(SQLTransaction* transaction) { - ASSERT(currentThread() == transaction->database()->document()->databaseThread()->getThreadID()); + ASSERT(currentThread() == transaction->database()->scriptExecutionContext()->databaseThread()->getThreadID()); OriginQuotaManager& manager(DatabaseTracker::tracker().originQuotaManager()); Locker<OriginQuotaManager> locker(manager); manager.markDatabase(transaction->database()); @@ -60,15 +63,15 @@ void SQLTransactionClient::didExecuteStatement(SQLTransaction* transaction) bool SQLTransactionClient::didExceedQuota(SQLTransaction* transaction) { - ASSERT(isMainThread()); + ASSERT(transaction->database()->scriptExecutionContext()->isContextThread()); Database* database = transaction->database(); - Page* page = database->document()->page(); - ASSERT(page); unsigned long long currentQuota = DatabaseTracker::tracker().quotaForOrigin(database->securityOrigin()); - page->chrome()->client()->exceededDatabaseQuota(database->document()->frame(), database->stringIdentifier()); + database->scriptExecutionContext()->databaseExceededQuota(database->stringIdentifier()); unsigned long long newQuota = DatabaseTracker::tracker().quotaForOrigin(database->securityOrigin()); return (newQuota > currentQuota); } } + +#endif // ENABLE(DATABASE) diff --git a/WebCore/storage/SQLTransactionClient.h b/WebCore/storage/SQLTransactionClient.h index e822594..801647b 100644 --- a/WebCore/storage/SQLTransactionClient.h +++ b/WebCore/storage/SQLTransactionClient.h @@ -31,6 +31,8 @@ #ifndef SQLTransactionClient_h #define SQLTransactionClient_h +#if ENABLE(DATABASE) + #include <wtf/Noncopyable.h> namespace WebCore { @@ -47,4 +49,6 @@ namespace WebCore { }; } +#endif // ENABLE(DATABASE) + #endif // SQLTransactionClient_h diff --git a/WebCore/storage/SQLTransactionCoordinator.cpp b/WebCore/storage/SQLTransactionCoordinator.cpp index 30b0c4a..efdcd1d 100644 --- a/WebCore/storage/SQLTransactionCoordinator.cpp +++ b/WebCore/storage/SQLTransactionCoordinator.cpp @@ -31,6 +31,8 @@ #include "config.h" #include "SQLTransactionCoordinator.h" +#if ENABLE(DATABASE) + #include "CString.h" #include "Database.h" #include "SQLTransaction.h" @@ -111,4 +113,6 @@ void SQLTransactionCoordinator::shutdown() m_coordinationInfoMap.clear(); } -} +} // namespace WebCore + +#endif // ENABLE(DATABASE) diff --git a/WebCore/storage/SQLTransactionCoordinator.h b/WebCore/storage/SQLTransactionCoordinator.h index ae5674b..a51084f 100644 --- a/WebCore/storage/SQLTransactionCoordinator.h +++ b/WebCore/storage/SQLTransactionCoordinator.h @@ -31,6 +31,8 @@ #ifndef SQLTransactionCoordinator_h #define SQLTransactionCoordinator_h +#if ENABLE(DATABASE) + #include "CString.h" #include "StringHash.h" #include <wtf/Deque.h> @@ -62,4 +64,6 @@ namespace WebCore { }; } +#endif // ENABLE(DATABASE) + #endif // SQLTransactionCoordinator_h diff --git a/WebCore/storage/Storage.idl b/WebCore/storage/Storage.idl index 7127efd..ffd1af1 100644 --- a/WebCore/storage/Storage.idl +++ b/WebCore/storage/Storage.idl @@ -26,7 +26,6 @@ module storage { interface [ - GenerateConstructor, HasNameGetter, CustomDeleteProperty, CustomGetPropertyNames, diff --git a/WebCore/storage/StorageArea.h b/WebCore/storage/StorageArea.h index a64d44a..6081240 100644 --- a/WebCore/storage/StorageArea.h +++ b/WebCore/storage/StorageArea.h @@ -50,9 +50,9 @@ namespace WebCore { virtual unsigned length() const = 0; virtual String key(unsigned index) const = 0; virtual String getItem(const String& key) const = 0; - virtual void setItem(const String& key, const String& value, ExceptionCode& ec, Frame* sourceFrame) = 0; - virtual void removeItem(const String& key, Frame* sourceFrame) = 0; - virtual void clear(Frame* sourceFrame) = 0; + virtual String setItem(const String& key, const String& value, ExceptionCode& ec, Frame* sourceFrame) = 0; + virtual String removeItem(const String& key, Frame* sourceFrame) = 0; + virtual bool clear(Frame* sourceFrame) = 0; virtual bool contains(const String& key) const = 0; }; diff --git a/WebCore/storage/StorageAreaImpl.cpp b/WebCore/storage/StorageAreaImpl.cpp index 8c2a29c..aa04781 100644 --- a/WebCore/storage/StorageAreaImpl.cpp +++ b/WebCore/storage/StorageAreaImpl.cpp @@ -128,7 +128,7 @@ String StorageAreaImpl::getItem(const String& key) const return m_storageMap->getItem(key); } -void StorageAreaImpl::setItem(const String& key, const String& value, ExceptionCode& ec, Frame* frame) +String StorageAreaImpl::setItem(const String& key, const String& value, ExceptionCode& ec, Frame* frame) { ASSERT(!m_isShutdown); ASSERT(!value.isNull()); @@ -136,7 +136,7 @@ void StorageAreaImpl::setItem(const String& key, const String& value, ExceptionC if (privateBrowsingEnabled(frame)) { ec = QUOTA_EXCEEDED_ERR; - return; + return String(); } String oldValue; @@ -147,24 +147,25 @@ void StorageAreaImpl::setItem(const String& key, const String& value, ExceptionC if (quotaException) { ec = QUOTA_EXCEEDED_ERR; - return; + return oldValue; } if (oldValue == value) - return; + return oldValue; if (m_storageAreaSync) m_storageAreaSync->scheduleItemForSync(key, value); StorageEventDispatcher::dispatch(key, oldValue, value, m_storageType, m_securityOrigin.get(), frame); + return oldValue; } -void StorageAreaImpl::removeItem(const String& key, Frame* frame) +String StorageAreaImpl::removeItem(const String& key, Frame* frame) { ASSERT(!m_isShutdown); blockUntilImportComplete(); if (privateBrowsingEnabled(frame)) - return; + return String(); String oldValue; RefPtr<StorageMap> newMap = m_storageMap->removeItem(key, oldValue); @@ -172,23 +173,24 @@ void StorageAreaImpl::removeItem(const String& key, Frame* frame) m_storageMap = newMap.release(); if (oldValue.isNull()) - return; + return oldValue; if (m_storageAreaSync) m_storageAreaSync->scheduleItemForSync(key, String()); StorageEventDispatcher::dispatch(key, oldValue, String(), m_storageType, m_securityOrigin.get(), frame); + return oldValue; } -void StorageAreaImpl::clear(Frame* frame) +bool StorageAreaImpl::clear(Frame* frame) { ASSERT(!m_isShutdown); blockUntilImportComplete(); if (privateBrowsingEnabled(frame)) - return; + return false; if (!m_storageMap->length()) - return; + return false; unsigned quota = m_storageMap->quota(); m_storageMap = StorageMap::create(quota); @@ -196,6 +198,7 @@ void StorageAreaImpl::clear(Frame* frame) if (m_storageAreaSync) m_storageAreaSync->scheduleClear(); StorageEventDispatcher::dispatch(String(), String(), String(), m_storageType, m_securityOrigin.get(), frame); + return true; } bool StorageAreaImpl::contains(const String& key) const diff --git a/WebCore/storage/StorageAreaImpl.h b/WebCore/storage/StorageAreaImpl.h index 0b2d34d..60d72cb 100644 --- a/WebCore/storage/StorageAreaImpl.h +++ b/WebCore/storage/StorageAreaImpl.h @@ -48,9 +48,9 @@ namespace WebCore { virtual unsigned length() const; virtual String key(unsigned index) const; virtual String getItem(const String& key) const; - virtual void setItem(const String& key, const String& value, ExceptionCode& ec, Frame* sourceFrame); - virtual void removeItem(const String& key, Frame* sourceFrame); - virtual void clear(Frame* sourceFrame); + virtual String setItem(const String& key, const String& value, ExceptionCode& ec, Frame* sourceFrame); + virtual String removeItem(const String& key, Frame* sourceFrame); + virtual bool clear(Frame* sourceFrame); virtual bool contains(const String& key) const; PassRefPtr<StorageAreaImpl> copy(); diff --git a/WebCore/storage/StorageEvent.cpp b/WebCore/storage/StorageEvent.cpp index 13ccfe9..126aca0 100644 --- a/WebCore/storage/StorageEvent.cpp +++ b/WebCore/storage/StorageEvent.cpp @@ -47,7 +47,7 @@ PassRefPtr<StorageEvent> StorageEvent::create(const AtomicString& type, const St } StorageEvent::StorageEvent(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& uri, Storage* storageArea) - : Event(type, false, true) + : Event(type, false, false) , m_key(key) , m_oldValue(oldValue) , m_newValue(newValue) diff --git a/WebCore/storage/StorageEvent.idl b/WebCore/storage/StorageEvent.idl index 7c87561..3e77eda 100644 --- a/WebCore/storage/StorageEvent.idl +++ b/WebCore/storage/StorageEvent.idl @@ -26,10 +26,9 @@ module storage { interface [ - GenerateConstructor, Conditional=DOM_STORAGE ] StorageEvent : Event { - readonly attribute DOMString key; + readonly attribute [ConvertNullStringTo=Null] DOMString key; readonly attribute [ConvertNullStringTo=Null] DOMString oldValue; readonly attribute [ConvertNullStringTo=Null] DOMString newValue; readonly attribute DOMString uri; diff --git a/WebCore/storage/StorageEventDispatcher.cpp b/WebCore/storage/StorageEventDispatcher.cpp index 9763e07..dc0295b 100644 --- a/WebCore/storage/StorageEventDispatcher.cpp +++ b/WebCore/storage/StorageEventDispatcher.cpp @@ -50,25 +50,25 @@ void StorageEventDispatcher::dispatch(const String& key, const String& oldValue, if (storageType == SessionStorage) { // Send events only to our page. for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { - if (frame->document()->securityOrigin()->equal(securityOrigin)) + if (sourceFrame != frame && frame->document()->securityOrigin()->equal(securityOrigin)) frames.append(frame); } for (unsigned i = 0; i < frames.size(); ++i) - frames[i]->document()->dispatchWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), frames[i]->domWindow()->sessionStorage())); + frames[i]->document()->enqueueStorageEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), frames[i]->domWindow()->sessionStorage())); } else { // Send events to every page. const HashSet<Page*>& pages = page->group().pages(); HashSet<Page*>::const_iterator end = pages.end(); for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) { for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) { - if (frame->document()->securityOrigin()->equal(securityOrigin)) + if (sourceFrame != frame && frame->document()->securityOrigin()->equal(securityOrigin)) frames.append(frame); } } for (unsigned i = 0; i < frames.size(); ++i) - frames[i]->document()->dispatchWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), frames[i]->domWindow()->localStorage())); + frames[i]->document()->enqueueStorageEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), frames[i]->domWindow()->localStorage())); } } diff --git a/WebCore/storage/StorageMap.cpp b/WebCore/storage/StorageMap.cpp index bb08671..790fde2 100644 --- a/WebCore/storage/StorageMap.cpp +++ b/WebCore/storage/StorageMap.cpp @@ -47,6 +47,7 @@ PassRefPtr<StorageMap> StorageMap::copy() { RefPtr<StorageMap> newMap = create(m_quotaSize); newMap->m_map = m_map; + newMap->m_currentLength = m_currentLength; return newMap.release(); } diff --git a/WebCore/storage/StorageNamespace.cpp b/WebCore/storage/StorageNamespace.cpp index 6b8caeb..b54ba16 100644 --- a/WebCore/storage/StorageNamespace.cpp +++ b/WebCore/storage/StorageNamespace.cpp @@ -41,7 +41,8 @@ PassRefPtr<StorageNamespace> StorageNamespace::localStorageNamespace(const Strin return StorageNamespaceImpl::localStorageNamespace(path, quota); } -PassRefPtr<StorageNamespace> StorageNamespace::sessionStorageNamespace() +// The page argument is only used by the Chromium port. +PassRefPtr<StorageNamespace> StorageNamespace::sessionStorageNamespace(Page*) { return StorageNamespaceImpl::sessionStorageNamespace(); } diff --git a/WebCore/storage/StorageNamespace.h b/WebCore/storage/StorageNamespace.h index 0ac5f86..e84e5a6 100644 --- a/WebCore/storage/StorageNamespace.h +++ b/WebCore/storage/StorageNamespace.h @@ -35,21 +35,22 @@ namespace WebCore { - class SecurityOrigin; - class StorageArea; - - // This interface is required for Chromium since these actions need to be proxied between processes. - class StorageNamespace : public RefCounted<StorageNamespace> { - public: - static PassRefPtr<StorageNamespace> localStorageNamespace(const String& path, unsigned quota); - static PassRefPtr<StorageNamespace> sessionStorageNamespace(); - - virtual ~StorageNamespace() { } - virtual PassRefPtr<StorageArea> storageArea(PassRefPtr<SecurityOrigin>) = 0; - virtual PassRefPtr<StorageNamespace> copy() = 0; - virtual void close() = 0; - virtual void unlock() = 0; - }; +class Page; +class SecurityOrigin; +class StorageArea; + +// This interface is required for Chromium since these actions need to be proxied between processes. +class StorageNamespace : public RefCounted<StorageNamespace> { +public: + static PassRefPtr<StorageNamespace> localStorageNamespace(const String& path, unsigned quota); + static PassRefPtr<StorageNamespace> sessionStorageNamespace(Page*); + + virtual ~StorageNamespace() { } + virtual PassRefPtr<StorageArea> storageArea(PassRefPtr<SecurityOrigin>) = 0; + virtual PassRefPtr<StorageNamespace> copy() = 0; + virtual void close() = 0; + virtual void unlock() = 0; +}; } // namespace WebCore diff --git a/WebCore/storage/chromium/DatabaseTrackerChromium.cpp b/WebCore/storage/chromium/DatabaseTrackerChromium.cpp index e4b8178..e18706b 100644 --- a/WebCore/storage/chromium/DatabaseTrackerChromium.cpp +++ b/WebCore/storage/chromium/DatabaseTrackerChromium.cpp @@ -35,11 +35,12 @@ #include "Database.h" #include "DatabaseObserver.h" #include "DatabaseThread.h" -#include "Document.h" #include "QuotaTracker.h" +#include "ScriptExecutionContext.h" #include "SecurityOrigin.h" #include "SQLiteFileSystem.h" #include <wtf/HashSet.h> +#include <wtf/MainThread.h> #include <wtf/StdLibExtras.h> namespace WebCore { @@ -55,7 +56,7 @@ DatabaseTracker::DatabaseTracker() SQLiteFileSystem::registerSQLiteVFS(); } -bool DatabaseTracker::canEstablishDatabase(Document*, const String&, const String&, unsigned long) +bool DatabaseTracker::canEstablishDatabase(ScriptExecutionContext*, const String&, const String&, unsigned long) { // In Chromium, a database can always be established (even though we might not // be able to write anything to it if the quota for this origin was exceeded) @@ -74,21 +75,44 @@ String DatabaseTracker::fullPathForDatabase(SecurityOrigin* origin, const String void DatabaseTracker::addOpenDatabase(Database* database) { - ASSERT(isMainThread()); + ASSERT(database->scriptExecutionContext()->isContextThread()); DatabaseObserver::databaseOpened(database); } +class TrackerRemoveOpenDatabaseTask : public ScriptExecutionContext::Task { +public: + static PassOwnPtr<TrackerRemoveOpenDatabaseTask> create(PassRefPtr<Database> database) + { + return new TrackerRemoveOpenDatabaseTask(database); + } + + virtual void performTask(ScriptExecutionContext* context) + { + DatabaseTracker::tracker().removeOpenDatabase(m_database.get()); + } + +private: + TrackerRemoveOpenDatabaseTask(PassRefPtr<Database> database) + : m_database(database) + { + } + + RefPtr<Database> m_database; +}; + void DatabaseTracker::removeOpenDatabase(Database* database) { - // FIXME: once we know how to use this information, figure out - // how to get this method called on the main thread - //ASSERT(isMainThread()); - //DatabaseObserver::databaseClosed(database); + if (!database->scriptExecutionContext()->isContextThread()) { + database->scriptExecutionContext()->postTask(TrackerRemoveOpenDatabaseTask::create(database)); + return; + } + + DatabaseObserver::databaseClosed(database); } unsigned long long DatabaseTracker::getMaxSizeForDatabase(const Database* database) { - ASSERT(currentThread() == database->document()->databaseThread()->getThreadID()); + ASSERT(currentThread() == database->scriptExecutionContext()->databaseThread()->getThreadID()); unsigned long long spaceAvailable = 0; unsigned long long databaseSize = 0; QuotaTracker::instance().getDatabaseSizeAndSpaceAvailableToOrigin( diff --git a/WebCore/storage/chromium/SQLTransactionClientChromium.cpp b/WebCore/storage/chromium/SQLTransactionClientChromium.cpp index 46d73ba..a10ca3e 100644 --- a/WebCore/storage/chromium/SQLTransactionClientChromium.cpp +++ b/WebCore/storage/chromium/SQLTransactionClientChromium.cpp @@ -38,20 +38,34 @@ #include "SQLTransaction.h" #include <wtf/MainThread.h> -static void notifyDatabaseChanged(void* context) { - WebCore::Database* database = static_cast<WebCore::Database*>(context); - WebCore::DatabaseObserver::databaseModified(database); - database->deref(); // ref()'d in didCommitTransaction() -} - namespace WebCore { +class NotifyDatabaseChangedTask : public ScriptExecutionContext::Task { +public: + static PassOwnPtr<NotifyDatabaseChangedTask> create(Database *database) + { + return new NotifyDatabaseChangedTask(database); + } + + virtual void performTask(ScriptExecutionContext*) + { + WebCore::DatabaseObserver::databaseModified(m_database.get()); + } + +private: + NotifyDatabaseChangedTask(PassRefPtr<Database> database) + : m_database(database) + { + } + + RefPtr<Database> m_database; +}; + void SQLTransactionClient::didCommitTransaction(SQLTransaction* transaction) { - ASSERT(currentThread() == transaction->database()->document()->databaseThread()->getThreadID()); + ASSERT(currentThread() == transaction->database()->scriptExecutionContext()->databaseThread()->getThreadID()); if (!transaction->isReadOnly()) { - transaction->database()->ref(); // deref()'d in notifyDatabaseChanged() - callOnMainThread(notifyDatabaseChanged, transaction->database()); + transaction->database()->scriptExecutionContext()->postTask(NotifyDatabaseChangedTask::create(transaction->database())); } } @@ -59,14 +73,14 @@ void SQLTransactionClient::didExecuteStatement(SQLTransaction* transaction) { // This method is called after executing every statement that changes the DB. // Chromium doesn't need to do anything at that point. - ASSERT(currentThread() == transaction->database()->document()->databaseThread()->getThreadID()); + ASSERT(currentThread() == transaction->database()->scriptExecutionContext()->databaseThread()->getThreadID()); } -bool SQLTransactionClient::didExceedQuota(SQLTransaction*) +bool SQLTransactionClient::didExceedQuota(SQLTransaction* transaction) { // Chromium does not allow users to manually change the quota for an origin (for now, at least). // Don't do anything. - ASSERT(isMainThread()); + ASSERT(transaction->database()->scriptExecutionContext()->isContextThread()); return false; } |