summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/storage
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/storage')
-rw-r--r--Source/WebCore/storage/AbstractDatabase.h4
-rw-r--r--Source/WebCore/storage/DatabaseAuthorizer.h4
-rw-r--r--Source/WebCore/storage/DatabaseCallback.h4
-rw-r--r--Source/WebCore/storage/DatabaseThread.h2
-rw-r--r--Source/WebCore/storage/IDBBackingStore.h62
-rw-r--r--Source/WebCore/storage/IDBCallbacks.h4
-rw-r--r--Source/WebCore/storage/IDBCursorBackendInterface.h2
-rw-r--r--Source/WebCore/storage/IDBDatabase.cpp9
-rw-r--r--Source/WebCore/storage/IDBDatabase.h10
-rw-r--r--Source/WebCore/storage/IDBDatabaseBackendInterface.h2
-rw-r--r--Source/WebCore/storage/IDBDatabaseCallbacksImpl.cpp63
-rw-r--r--Source/WebCore/storage/IDBDatabaseCallbacksImpl.h58
-rw-r--r--Source/WebCore/storage/IDBFactory.cpp2
-rw-r--r--Source/WebCore/storage/IDBFactoryBackendImpl.cpp6
-rw-r--r--Source/WebCore/storage/IDBFactoryBackendImpl.h2
-rw-r--r--Source/WebCore/storage/IDBFactoryBackendInterface.h9
-rw-r--r--Source/WebCore/storage/IDBIndexBackendInterface.h2
-rw-r--r--Source/WebCore/storage/IDBKey.h6
-rw-r--r--Source/WebCore/storage/IDBKeyRange.h2
-rw-r--r--Source/WebCore/storage/IDBObjectStoreBackendInterface.h2
-rw-r--r--Source/WebCore/storage/IDBRequest.cpp6
-rw-r--r--Source/WebCore/storage/IDBRequest.h5
-rw-r--r--Source/WebCore/storage/IDBSQLiteBackingStore.cpp (renamed from Source/WebCore/storage/IDBBackingStore.cpp)60
-rw-r--r--Source/WebCore/storage/IDBSQLiteBackingStore.h82
-rw-r--r--Source/WebCore/storage/IDBTransactionBackendInterface.h2
-rw-r--r--Source/WebCore/storage/LocalStorageTask.cpp34
-rw-r--r--Source/WebCore/storage/LocalStorageTask.h12
-rw-r--r--Source/WebCore/storage/SQLCallbackWrapper.h108
-rw-r--r--Source/WebCore/storage/SQLError.h4
-rw-r--r--Source/WebCore/storage/SQLResultSet.h4
-rw-r--r--Source/WebCore/storage/SQLStatement.cpp25
-rw-r--r--Source/WebCore/storage/SQLStatement.h15
-rw-r--r--Source/WebCore/storage/SQLStatementCallback.h4
-rw-r--r--Source/WebCore/storage/SQLStatementErrorCallback.h4
-rw-r--r--Source/WebCore/storage/SQLTransaction.cpp45
-rw-r--r--Source/WebCore/storage/SQLTransaction.h12
-rw-r--r--Source/WebCore/storage/SQLTransactionCallback.h4
-rw-r--r--Source/WebCore/storage/SQLTransactionErrorCallback.h4
-rw-r--r--Source/WebCore/storage/StorageAreaImpl.cpp25
-rw-r--r--Source/WebCore/storage/StorageAreaImpl.h5
-rw-r--r--Source/WebCore/storage/StorageAreaSync.cpp51
-rw-r--r--Source/WebCore/storage/StorageAreaSync.h5
-rw-r--r--Source/WebCore/storage/StorageNamespace.h6
-rw-r--r--Source/WebCore/storage/StorageNamespaceImpl.cpp27
-rw-r--r--Source/WebCore/storage/StorageNamespaceImpl.h11
-rw-r--r--Source/WebCore/storage/StorageTracker.cpp539
-rw-r--r--Source/WebCore/storage/StorageTracker.h117
-rw-r--r--Source/WebCore/storage/StorageTrackerClient.h41
48 files changed, 1339 insertions, 173 deletions
diff --git a/Source/WebCore/storage/AbstractDatabase.h b/Source/WebCore/storage/AbstractDatabase.h
index bd5d0db..9279adc 100644
--- a/Source/WebCore/storage/AbstractDatabase.h
+++ b/Source/WebCore/storage/AbstractDatabase.h
@@ -35,7 +35,7 @@
#include "PlatformString.h"
#include "SQLiteDatabase.h"
#include <wtf/Forward.h>
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
#ifndef NDEBUG
#include "SecurityOrigin.h"
#endif
@@ -46,7 +46,7 @@ class DatabaseAuthorizer;
class ScriptExecutionContext;
class SecurityOrigin;
-class AbstractDatabase : public ThreadSafeShared<AbstractDatabase> {
+class AbstractDatabase : public ThreadSafeRefCounted<AbstractDatabase> {
public:
static bool isAvailable();
static void setIsAvailable(bool available);
diff --git a/Source/WebCore/storage/DatabaseAuthorizer.h b/Source/WebCore/storage/DatabaseAuthorizer.h
index da7761d..939b409 100644
--- a/Source/WebCore/storage/DatabaseAuthorizer.h
+++ b/Source/WebCore/storage/DatabaseAuthorizer.h
@@ -31,7 +31,7 @@
#include "PlatformString.h"
#include <wtf/Forward.h>
#include <wtf/HashSet.h>
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/text/StringHash.h>
namespace WebCore {
@@ -40,7 +40,7 @@ extern const int SQLAuthAllow;
extern const int SQLAuthIgnore;
extern const int SQLAuthDeny;
-class DatabaseAuthorizer : public ThreadSafeShared<DatabaseAuthorizer> {
+class DatabaseAuthorizer : public ThreadSafeRefCounted<DatabaseAuthorizer> {
public:
enum Permissions {
diff --git a/Source/WebCore/storage/DatabaseCallback.h b/Source/WebCore/storage/DatabaseCallback.h
index 8ad56ed..586416a 100644
--- a/Source/WebCore/storage/DatabaseCallback.h
+++ b/Source/WebCore/storage/DatabaseCallback.h
@@ -33,14 +33,14 @@
#if ENABLE(DATABASE)
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
namespace WebCore {
class Database;
class DatabaseSync;
-class DatabaseCallback : public ThreadSafeShared<DatabaseCallback> {
+class DatabaseCallback : public ThreadSafeRefCounted<DatabaseCallback> {
public:
virtual ~DatabaseCallback() { }
virtual bool handleEvent(Database*) = 0;
diff --git a/Source/WebCore/storage/DatabaseThread.h b/Source/WebCore/storage/DatabaseThread.h
index c81e376..ee1702c 100644
--- a/Source/WebCore/storage/DatabaseThread.h
+++ b/Source/WebCore/storage/DatabaseThread.h
@@ -48,7 +48,7 @@ class Document;
class SQLTransactionClient;
class SQLTransactionCoordinator;
-class DatabaseThread : public ThreadSafeShared<DatabaseThread> {
+class DatabaseThread : public ThreadSafeRefCounted<DatabaseThread> {
public:
static PassRefPtr<DatabaseThread> create() { return adoptRef(new DatabaseThread); }
~DatabaseThread();
diff --git a/Source/WebCore/storage/IDBBackingStore.h b/Source/WebCore/storage/IDBBackingStore.h
index e75fee1..29523a2 100644
--- a/Source/WebCore/storage/IDBBackingStore.h
+++ b/Source/WebCore/storage/IDBBackingStore.h
@@ -44,37 +44,36 @@ class SecurityOrigin;
class IDBBackingStore : public RefCounted<IDBBackingStore> {
public:
- static PassRefPtr<IDBBackingStore> open(SecurityOrigin*, const String& pathBase, int64_t maximumSize, const String& fileIdentifier, IDBFactoryBackendImpl*);
- ~IDBBackingStore();
-
- bool extractIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId);
- bool setIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId, bool invalidRowId);
-
- void getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags);
- bool createObjectStore(const String& name, const String& keyPath, bool autoIncrement, int64_t databaseId, int64_t& assignedObjectStoreId);
- void deleteObjectStore(int64_t objectStoreId);
- String getObjectStoreRecord(int64_t objectStoreId, const IDBKey&);
- bool putObjectStoreRecord(int64_t objectStoreId, const IDBKey&, const String& value, int64_t& rowId, bool invalidRowId);
- void clearObjectStore(int64_t objectStoreId);
- void deleteObjectStoreRecord(int64_t objectStoreId, int64_t objectStoreDataId);
- double nextAutoIncrementNumber(int64_t objectStoreId);
- bool keyExistsInObjectStore(int64_t objectStoreId, const IDBKey&, int64_t& foundObjectStoreDataId);
+ virtual ~IDBBackingStore() {};
+
+ virtual bool extractIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId) = 0;
+ virtual bool setIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId, bool invalidRowId) = 0;
+
+ virtual void getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags) = 0;
+ virtual bool createObjectStore(const String& name, const String& keyPath, bool autoIncrement, int64_t databaseId, int64_t& assignedObjectStoreId) = 0;
+ virtual void deleteObjectStore(int64_t objectStoreId) = 0;
+ virtual String getObjectStoreRecord(int64_t objectStoreId, const IDBKey&) = 0;
+ virtual bool putObjectStoreRecord(int64_t objectStoreId, const IDBKey&, const String& value, int64_t& rowId, bool invalidRowId) = 0;
+ virtual void clearObjectStore(int64_t objectStoreId) = 0;
+ virtual void deleteObjectStoreRecord(int64_t objectStoreId, int64_t objectStoreDataId) = 0;
+ virtual double nextAutoIncrementNumber(int64_t objectStoreId) = 0;
+ virtual bool keyExistsInObjectStore(int64_t objectStoreId, const IDBKey&, int64_t& foundObjectStoreDataId) = 0;
class ObjectStoreRecordCallback {
public:
virtual bool callback(int64_t objectStoreDataId, const String& value) = 0;
virtual ~ObjectStoreRecordCallback() {};
};
- bool forEachObjectStoreRecord(int64_t objectStoreId, ObjectStoreRecordCallback&);
+ virtual bool forEachObjectStoreRecord(int64_t objectStoreId, ObjectStoreRecordCallback&) = 0;
- void getIndexes(int64_t objectStoreId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundUniqueFlags);
- bool createIndex(int64_t objectStoreId, const String& name, const String& keyPath, bool isUnique, int64_t& indexId);
- void deleteIndex(int64_t indexId);
- bool putIndexDataForRecord(int64_t indexId, const IDBKey&, int64_t objectStoreDataId);
- bool deleteIndexDataForRecord(int64_t objectStoreDataId);
- String getObjectViaIndex(int64_t indexId, const IDBKey&);
- PassRefPtr<IDBKey> getPrimaryKeyViaIndex(int64_t indexId, const IDBKey&);
- bool keyExistsInIndex(int64_t indexId, const IDBKey&);
+ virtual void getIndexes(int64_t objectStoreId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundUniqueFlags) = 0;
+ virtual bool createIndex(int64_t objectStoreId, const String& name, const String& keyPath, bool isUnique, int64_t& indexId) = 0;
+ virtual void deleteIndex(int64_t indexId) = 0;
+ virtual bool putIndexDataForRecord(int64_t indexId, const IDBKey&, int64_t objectStoreDataId) = 0;
+ virtual bool deleteIndexDataForRecord(int64_t objectStoreDataId) = 0;
+ virtual String getObjectViaIndex(int64_t indexId, const IDBKey&) = 0;
+ virtual PassRefPtr<IDBKey> getPrimaryKeyViaIndex(int64_t indexId, const IDBKey&) = 0;
+ virtual bool keyExistsInIndex(int64_t indexId, const IDBKey&) = 0;
class Cursor : public RefCounted<Cursor> {
public:
@@ -87,9 +86,9 @@ public:
virtual ~Cursor() {};
};
- PassRefPtr<Cursor> openObjectStoreCursor(int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction);
- PassRefPtr<Cursor> openIndexKeyCursor(int64_t indexId, const IDBKeyRange*, IDBCursor::Direction);
- PassRefPtr<Cursor> openIndexCursor(int64_t indexId, const IDBKeyRange*, IDBCursor::Direction);
+ virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction) = 0;
+ virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t indexId, const IDBKeyRange*, IDBCursor::Direction) = 0;
+ virtual PassRefPtr<Cursor> openIndexCursor(int64_t indexId, const IDBKeyRange*, IDBCursor::Direction) = 0;
class Transaction : public RefCounted<Transaction> {
public:
@@ -97,14 +96,7 @@ public:
virtual void commit() = 0;
virtual void rollback() = 0;
};
- PassRefPtr<Transaction> createTransaction();
-
-private:
- IDBBackingStore(String identifier, IDBFactoryBackendImpl* factory);
-
- SQLiteDatabase m_db;
- String m_identifier;
- RefPtr<IDBFactoryBackendImpl> m_factory;
+ virtual PassRefPtr<Transaction> createTransaction() = 0;
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/IDBCallbacks.h b/Source/WebCore/storage/IDBCallbacks.h
index f4e1b98..ddc6e60 100644
--- a/Source/WebCore/storage/IDBCallbacks.h
+++ b/Source/WebCore/storage/IDBCallbacks.h
@@ -32,7 +32,6 @@
#include "IDBCursorBackendInterface.h"
#include "IDBDatabaseBackendInterface.h"
#include "IDBDatabaseError.h"
-#include "IDBIndexBackendInterface.h"
#include "IDBKey.h"
#include "IDBObjectStoreBackendInterface.h"
#include "IDBTransactionBackendInterface.h"
@@ -44,14 +43,13 @@
namespace WebCore {
// FIXME: All child classes need to be made threadsafe.
-class IDBCallbacks : public ThreadSafeShared<IDBCallbacks> {
+class IDBCallbacks : public ThreadSafeRefCounted<IDBCallbacks> {
public:
virtual ~IDBCallbacks() { }
virtual void onError(PassRefPtr<IDBDatabaseError>) = 0;
virtual void onSuccess(PassRefPtr<IDBCursorBackendInterface>) = 0;
virtual void onSuccess(PassRefPtr<IDBDatabaseBackendInterface>) = 0;
- virtual void onSuccess(PassRefPtr<IDBIndexBackendInterface>) = 0;
virtual void onSuccess(PassRefPtr<IDBKey>) = 0;
virtual void onSuccess(PassRefPtr<IDBTransactionBackendInterface>) = 0;
virtual void onSuccess(PassRefPtr<SerializedScriptValue>) = 0;
diff --git a/Source/WebCore/storage/IDBCursorBackendInterface.h b/Source/WebCore/storage/IDBCursorBackendInterface.h
index 6cdab42..21425c9 100644
--- a/Source/WebCore/storage/IDBCursorBackendInterface.h
+++ b/Source/WebCore/storage/IDBCursorBackendInterface.h
@@ -41,7 +41,7 @@ class IDBKey;
class IDBRequest;
class SerializedScriptValue;
-class IDBCursorBackendInterface : public ThreadSafeShared<IDBCursorBackendInterface> {
+class IDBCursorBackendInterface : public ThreadSafeRefCounted<IDBCursorBackendInterface> {
public:
virtual ~IDBCursorBackendInterface() {}
diff --git a/Source/WebCore/storage/IDBDatabase.cpp b/Source/WebCore/storage/IDBDatabase.cpp
index fe8d350..d54b969 100644
--- a/Source/WebCore/storage/IDBDatabase.cpp
+++ b/Source/WebCore/storage/IDBDatabase.cpp
@@ -29,6 +29,7 @@
#include "Document.h"
#include "EventQueue.h"
#include "IDBAny.h"
+#include "IDBDatabaseCallbacksImpl.h"
#include "IDBDatabaseError.h"
#include "IDBDatabaseException.h"
#include "IDBEventDispatcher.h"
@@ -58,10 +59,12 @@ IDBDatabase::IDBDatabase(ScriptExecutionContext* context, PassRefPtr<IDBDatabase
{
// We pass a reference of this object before it can be adopted.
relaxAdoptionRequirement();
+ m_databaseCallbacks = IDBDatabaseCallbacksImpl::create(this);
}
IDBDatabase::~IDBDatabase()
{
+ m_databaseCallbacks->unregisterDatabase(this);
}
void IDBDatabase::setSetVersionTransaction(IDBTransaction* transaction)
@@ -103,7 +106,7 @@ void IDBDatabase::deleteObjectStore(const String& name, ExceptionCode& ec)
PassRefPtr<IDBVersionChangeRequest> IDBDatabase::setVersion(ScriptExecutionContext* context, const String& version, ExceptionCode& ec)
{
RefPtr<IDBVersionChangeRequest> request = IDBVersionChangeRequest::create(context, IDBAny::create(this), version);
- m_backend->setVersion(version, request, this, ec);
+ m_backend->setVersion(version, request, m_databaseCallbacks, ec);
return request;
}
@@ -154,7 +157,7 @@ void IDBDatabase::close()
}
m_noNewTransactions = true;
- m_backend->close(this);
+ m_backend->close(m_databaseCallbacks);
}
void IDBDatabase::onVersionChange(const String& version)
@@ -174,7 +177,7 @@ bool IDBDatabase::hasPendingActivity() const
void IDBDatabase::open()
{
- m_backend->open(this);
+ m_backend->open(m_databaseCallbacks);
}
void IDBDatabase::enqueueEvent(PassRefPtr<Event> event)
diff --git a/Source/WebCore/storage/IDBDatabase.h b/Source/WebCore/storage/IDBDatabase.h
index 51f1d23..9d4883e 100644
--- a/Source/WebCore/storage/IDBDatabase.h
+++ b/Source/WebCore/storage/IDBDatabase.h
@@ -32,7 +32,7 @@
#include "EventTarget.h"
#include "ExceptionCode.h"
#include "IDBDatabaseBackendInterface.h"
-#include "IDBDatabaseCallbacks.h"
+#include "IDBDatabaseCallbacksImpl.h"
#include "IDBObjectStore.h"
#include "IDBTransaction.h"
#include "OptionsObject.h"
@@ -47,7 +47,7 @@ namespace WebCore {
class IDBVersionChangeRequest;
class ScriptExecutionContext;
-class IDBDatabase : public IDBDatabaseCallbacks, public EventTarget, public ActiveDOMObject {
+class IDBDatabase : public RefCounted<IDBDatabase>, public EventTarget, public ActiveDOMObject {
public:
static PassRefPtr<IDBDatabase> create(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>);
~IDBDatabase();
@@ -91,8 +91,8 @@ public:
bool dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) { return EventTarget::dispatchEvent(event, ec); }
virtual bool dispatchEvent(PassRefPtr<Event>);
- using RefCounted<IDBDatabaseCallbacks>::ref;
- using RefCounted<IDBDatabaseCallbacks>::deref;
+ using RefCounted<IDBDatabase>::ref;
+ using RefCounted<IDBDatabase>::deref;
private:
IDBDatabase(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>);
@@ -114,6 +114,8 @@ private:
// Keep track of the versionchange events waiting to be fired on this
// database so that we can cancel them if the database closes.
Vector<RefPtr<Event> > m_enqueuedEvents;
+
+ RefPtr<IDBDatabaseCallbacksImpl> m_databaseCallbacks;
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/IDBDatabaseBackendInterface.h b/Source/WebCore/storage/IDBDatabaseBackendInterface.h
index ad6fdc7..2245bd7 100644
--- a/Source/WebCore/storage/IDBDatabaseBackendInterface.h
+++ b/Source/WebCore/storage/IDBDatabaseBackendInterface.h
@@ -46,7 +46,7 @@ class IDBTransactionBackendInterface;
// This is implemented by IDBDatabaseBackendImpl and optionally others (in order to proxy
// calls across process barriers). All calls to these classes should be non-blocking and
// trigger work on a background thread if necessary.
-class IDBDatabaseBackendInterface : public ThreadSafeShared<IDBDatabaseBackendInterface> {
+class IDBDatabaseBackendInterface : public ThreadSafeRefCounted<IDBDatabaseBackendInterface> {
public:
virtual ~IDBDatabaseBackendInterface() { }
diff --git a/Source/WebCore/storage/IDBDatabaseCallbacksImpl.cpp b/Source/WebCore/storage/IDBDatabaseCallbacksImpl.cpp
new file mode 100644
index 0000000..39c4409
--- /dev/null
+++ b/Source/WebCore/storage/IDBDatabaseCallbacksImpl.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 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 "IDBDatabaseCallbacksImpl.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBDatabase.h"
+
+namespace WebCore {
+
+PassRefPtr<IDBDatabaseCallbacksImpl> IDBDatabaseCallbacksImpl::create(IDBDatabase* database)
+{
+ return adoptRef(new IDBDatabaseCallbacksImpl(database));
+}
+
+IDBDatabaseCallbacksImpl::IDBDatabaseCallbacksImpl(IDBDatabase* database)
+ : m_database(database)
+{
+}
+
+IDBDatabaseCallbacksImpl::~IDBDatabaseCallbacksImpl()
+{
+}
+
+void IDBDatabaseCallbacksImpl::onVersionChange(const String& version)
+{
+ if (m_database)
+ m_database->onVersionChange(version);
+}
+
+void IDBDatabaseCallbacksImpl::unregisterDatabase(IDBDatabase* database)
+{
+ ASSERT(database == m_database);
+ m_database = 0;
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/storage/IDBDatabaseCallbacksImpl.h b/Source/WebCore/storage/IDBDatabaseCallbacksImpl.h
new file mode 100644
index 0000000..e8b1f99
--- /dev/null
+++ b/Source/WebCore/storage/IDBDatabaseCallbacksImpl.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 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 IDBDatabaseCallbacksImpl_h
+#define IDBDatabaseCallbacksImpl_h
+
+#include "IDBDatabaseCallbacks.h"
+#include "PlatformString.h"
+#include <wtf/RefCounted.h>
+
+#if ENABLE(INDEXED_DATABASE)
+
+namespace WebCore {
+
+class IDBDatabase;
+
+class IDBDatabaseCallbacksImpl : public IDBDatabaseCallbacks {
+public:
+ static PassRefPtr<IDBDatabaseCallbacksImpl> create(IDBDatabase*);
+ virtual ~IDBDatabaseCallbacksImpl();
+
+ virtual void onVersionChange(const String& version);
+ void unregisterDatabase(IDBDatabase*);
+
+private:
+ IDBDatabaseCallbacksImpl(IDBDatabase*);
+
+ // m_database has a RefPtr to this, so use a weak pointer to avoid a cycle.
+ IDBDatabase* m_database;
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // IDBDatabaseCallbacksImpl_h
diff --git a/Source/WebCore/storage/IDBFactory.cpp b/Source/WebCore/storage/IDBFactory.cpp
index 85e976c..295398b 100644
--- a/Source/WebCore/storage/IDBFactory.cpp
+++ b/Source/WebCore/storage/IDBFactory.cpp
@@ -74,7 +74,7 @@ PassRefPtr<IDBRequest> IDBFactory::open(ScriptExecutionContext* context, const S
RefPtr<IDBRequest> request = IDBRequest::create(document, IDBAny::create(this), 0);
GroupSettings* groupSettings = document->page()->group().groupSettings();
- m_factoryBackend->open(name, request, document->securityOrigin(), document->frame(), groupSettings->indexedDBDatabasePath(), groupSettings->indexedDBQuotaBytes());
+ m_factoryBackend->open(name, request, document->securityOrigin(), document->frame(), groupSettings->indexedDBDatabasePath(), groupSettings->indexedDBQuotaBytes(), IDBFactoryBackendInterface::DefaultBackingStore);
return request;
}
diff --git a/Source/WebCore/storage/IDBFactoryBackendImpl.cpp b/Source/WebCore/storage/IDBFactoryBackendImpl.cpp
index 9127455..461e930 100644
--- a/Source/WebCore/storage/IDBFactoryBackendImpl.cpp
+++ b/Source/WebCore/storage/IDBFactoryBackendImpl.cpp
@@ -30,9 +30,9 @@
#include "IDBFactoryBackendImpl.h"
#include "DOMStringList.h"
-#include "IDBBackingStore.h"
#include "IDBDatabaseBackendImpl.h"
#include "IDBDatabaseException.h"
+#include "IDBSQLiteBackingStore.h"
#include "IDBTransactionCoordinator.h"
#include "SecurityOrigin.h"
#include <wtf/Threading.h>
@@ -69,7 +69,7 @@ void IDBFactoryBackendImpl::removeIDBBackingStore(const String& uniqueIdentifier
m_backingStoreMap.remove(uniqueIdentifier);
}
-void IDBFactoryBackendImpl::open(const String& name, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> securityOrigin, Frame*, const String& dataDir, int64_t maximumSize)
+void IDBFactoryBackendImpl::open(const String& name, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> securityOrigin, Frame*, const String& dataDir, int64_t maximumSize, BackingStoreType)
{
String fileIdentifier = securityOrigin->databaseIdentifier();
String uniqueIdentifier = fileIdentifier + "@" + name;
@@ -86,7 +86,7 @@ void IDBFactoryBackendImpl::open(const String& name, PassRefPtr<IDBCallbacks> ca
if (it2 != m_backingStoreMap.end())
backingStore = it2->second;
else {
- backingStore = IDBBackingStore::open(securityOrigin.get(), dataDir, maximumSize, fileIdentifier, this);
+ backingStore = IDBSQLiteBackingStore::open(securityOrigin.get(), dataDir, maximumSize, fileIdentifier, this);
if (!backingStore) {
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
return;
diff --git a/Source/WebCore/storage/IDBFactoryBackendImpl.h b/Source/WebCore/storage/IDBFactoryBackendImpl.h
index 071bcf8..ab6e153 100644
--- a/Source/WebCore/storage/IDBFactoryBackendImpl.h
+++ b/Source/WebCore/storage/IDBFactoryBackendImpl.h
@@ -55,7 +55,7 @@ public:
void addIDBBackingStore(const String& uniqueIdentifier, IDBBackingStore*);
void removeIDBBackingStore(const String& uniqueIdentifier);
- virtual void open(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize);
+ virtual void open(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize, BackingStoreType);
private:
IDBFactoryBackendImpl();
diff --git a/Source/WebCore/storage/IDBFactoryBackendInterface.h b/Source/WebCore/storage/IDBFactoryBackendInterface.h
index e05f316..87362d4 100644
--- a/Source/WebCore/storage/IDBFactoryBackendInterface.h
+++ b/Source/WebCore/storage/IDBFactoryBackendInterface.h
@@ -46,12 +46,17 @@ class SecurityOrigin;
// This is implemented by IDBFactoryBackendImpl and optionally others (in order to proxy
// calls across process barriers). All calls to these classes should be non-blocking and
// trigger work on a background thread if necessary.
-class IDBFactoryBackendInterface : public ThreadSafeShared<IDBFactoryBackendInterface> {
+class IDBFactoryBackendInterface : public ThreadSafeRefCounted<IDBFactoryBackendInterface> {
public:
static PassRefPtr<IDBFactoryBackendInterface> create();
virtual ~IDBFactoryBackendInterface() { }
- virtual void open(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize) = 0;
+ enum BackingStoreType {
+ DefaultBackingStore,
+ LevelDBBackingStore
+ };
+
+ virtual void open(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize, BackingStoreType) = 0;
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/IDBIndexBackendInterface.h b/Source/WebCore/storage/IDBIndexBackendInterface.h
index e0e578d..81ef1d5 100644
--- a/Source/WebCore/storage/IDBIndexBackendInterface.h
+++ b/Source/WebCore/storage/IDBIndexBackendInterface.h
@@ -39,7 +39,7 @@ class IDBKey;
class IDBKeyRange;
class IDBTransactionBackendInterface;
-class IDBIndexBackendInterface : public ThreadSafeShared<IDBIndexBackendInterface> {
+class IDBIndexBackendInterface : public ThreadSafeRefCounted<IDBIndexBackendInterface> {
public:
virtual ~IDBIndexBackendInterface() { }
diff --git a/Source/WebCore/storage/IDBKey.h b/Source/WebCore/storage/IDBKey.h
index 5816ce3..8ee9b8e 100644
--- a/Source/WebCore/storage/IDBKey.h
+++ b/Source/WebCore/storage/IDBKey.h
@@ -34,7 +34,7 @@
namespace WebCore {
-class IDBKey : public ThreadSafeShared<IDBKey> {
+class IDBKey : public ThreadSafeRefCounted<IDBKey> {
public:
static PassRefPtr<IDBKey> createNull()
{
@@ -100,8 +100,8 @@ public:
bool isLessThan(const IDBKey* other) const;
bool isEqual(const IDBKey* other) const;
- using ThreadSafeShared<IDBKey>::ref;
- using ThreadSafeShared<IDBKey>::deref;
+ using ThreadSafeRefCounted<IDBKey>::ref;
+ using ThreadSafeRefCounted<IDBKey>::deref;
private:
IDBKey();
diff --git a/Source/WebCore/storage/IDBKeyRange.h b/Source/WebCore/storage/IDBKeyRange.h
index 636a5c1..7a87088 100644
--- a/Source/WebCore/storage/IDBKeyRange.h
+++ b/Source/WebCore/storage/IDBKeyRange.h
@@ -35,7 +35,7 @@
namespace WebCore {
-class IDBKeyRange : public ThreadSafeShared<IDBKeyRange> {
+class IDBKeyRange : public ThreadSafeRefCounted<IDBKeyRange> {
public:
static PassRefPtr<IDBKeyRange> create(PassRefPtr<IDBKey> lower, PassRefPtr<IDBKey> upper, bool lowerOpen, bool upperOpen)
{
diff --git a/Source/WebCore/storage/IDBObjectStoreBackendInterface.h b/Source/WebCore/storage/IDBObjectStoreBackendInterface.h
index 177701c..2975ed7 100644
--- a/Source/WebCore/storage/IDBObjectStoreBackendInterface.h
+++ b/Source/WebCore/storage/IDBObjectStoreBackendInterface.h
@@ -42,7 +42,7 @@ class IDBKeyRange;
class IDBTransactionBackendInterface;
class SerializedScriptValue;
-class IDBObjectStoreBackendInterface : public ThreadSafeShared<IDBObjectStoreBackendInterface> {
+class IDBObjectStoreBackendInterface : public ThreadSafeRefCounted<IDBObjectStoreBackendInterface> {
public:
virtual ~IDBObjectStoreBackendInterface() { }
diff --git a/Source/WebCore/storage/IDBRequest.cpp b/Source/WebCore/storage/IDBRequest.cpp
index e1837fc..f8d818a 100644
--- a/Source/WebCore/storage/IDBRequest.cpp
+++ b/Source/WebCore/storage/IDBRequest.cpp
@@ -39,7 +39,6 @@
#include "IDBCursorWithValue.h"
#include "IDBDatabase.h"
#include "IDBEventDispatcher.h"
-#include "IDBIndex.h"
#include "IDBPendingTransactionMonitor.h"
#include "IDBTransaction.h"
@@ -205,11 +204,6 @@ void IDBRequest::onSuccess(PassRefPtr<IDBDatabaseBackendInterface> backend)
enqueueEvent(createSuccessEvent());
}
-void IDBRequest::onSuccess(PassRefPtr<IDBIndexBackendInterface> backend)
-{
- ASSERT_NOT_REACHED(); // FIXME: This method should go away.
-}
-
void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey)
{
ASSERT(!m_errorCode && m_errorMessage.isNull() && !m_result);
diff --git a/Source/WebCore/storage/IDBRequest.h b/Source/WebCore/storage/IDBRequest.h
index b6b4e5b..900df01 100644
--- a/Source/WebCore/storage/IDBRequest.h
+++ b/Source/WebCore/storage/IDBRequest.h
@@ -76,7 +76,6 @@ public:
virtual void onError(PassRefPtr<IDBDatabaseError>);
virtual void onSuccess(PassRefPtr<IDBDatabaseBackendInterface>);
virtual void onSuccess(PassRefPtr<IDBCursorBackendInterface>);
- virtual void onSuccess(PassRefPtr<IDBIndexBackendInterface>);
virtual void onSuccess(PassRefPtr<IDBKey>);
virtual void onSuccess(PassRefPtr<IDBTransactionBackendInterface>);
virtual void onSuccess(PassRefPtr<SerializedScriptValue>);
@@ -92,8 +91,8 @@ public:
bool dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) { return EventTarget::dispatchEvent(event, ec); }
virtual void uncaughtExceptionInEventHandler();
- using ThreadSafeShared<IDBCallbacks>::ref;
- using ThreadSafeShared<IDBCallbacks>::deref;
+ using ThreadSafeRefCounted<IDBCallbacks>::ref;
+ using ThreadSafeRefCounted<IDBCallbacks>::deref;
protected:
IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction*);
diff --git a/Source/WebCore/storage/IDBBackingStore.cpp b/Source/WebCore/storage/IDBSQLiteBackingStore.cpp
index 3859c4c..e43b7a3 100644
--- a/Source/WebCore/storage/IDBBackingStore.cpp
+++ b/Source/WebCore/storage/IDBSQLiteBackingStore.cpp
@@ -24,7 +24,7 @@
*/
#include "config.h"
-#include "IDBBackingStore.h"
+#include "IDBSQLiteBackingStore.h"
#if ENABLE(INDEXED_DATABASE)
@@ -39,14 +39,14 @@
namespace WebCore {
-IDBBackingStore::IDBBackingStore(String identifier, IDBFactoryBackendImpl* factory)
+IDBSQLiteBackingStore::IDBSQLiteBackingStore(String identifier, IDBFactoryBackendImpl* factory)
: m_identifier(identifier)
, m_factory(factory)
{
m_factory->addIDBBackingStore(identifier, this);
}
-IDBBackingStore::~IDBBackingStore()
+IDBSQLiteBackingStore::~IDBSQLiteBackingStore()
{
m_factory->removeIDBBackingStore(m_identifier);
}
@@ -165,9 +165,9 @@ static bool migrateDatabase(SQLiteDatabase& sqliteDatabase)
return true;
}
-PassRefPtr<IDBBackingStore> IDBBackingStore::open(SecurityOrigin* securityOrigin, const String& pathBase, int64_t maximumSize, const String& fileIdentifier, IDBFactoryBackendImpl* factory)
+PassRefPtr<IDBBackingStore> IDBSQLiteBackingStore::open(SecurityOrigin* securityOrigin, const String& pathBase, int64_t maximumSize, const String& fileIdentifier, IDBFactoryBackendImpl* factory)
{
- RefPtr<IDBBackingStore> backingStore(adoptRef(new IDBBackingStore(fileIdentifier, factory)));
+ RefPtr<IDBSQLiteBackingStore> backingStore(adoptRef(new IDBSQLiteBackingStore(fileIdentifier, factory)));
String path = ":memory:";
if (!pathBase.isEmpty()) {
@@ -197,7 +197,7 @@ PassRefPtr<IDBBackingStore> IDBBackingStore::open(SecurityOrigin* securityOrigin
return backingStore.release();
}
-bool IDBBackingStore::extractIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId)
+bool IDBSQLiteBackingStore::extractIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId)
{
SQLiteStatement databaseQuery(m_db, "SELECT id, version FROM Databases WHERE name = ?");
if (databaseQuery.prepare() != SQLResultOk) {
@@ -216,7 +216,7 @@ bool IDBBackingStore::extractIDBDatabaseMetaData(const String& name, String& fou
return true;
}
-bool IDBBackingStore::setIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId, bool invalidRowId)
+bool IDBSQLiteBackingStore::setIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId, bool invalidRowId)
{
ASSERT(!name.isNull());
ASSERT(!version.isNull());
@@ -242,7 +242,7 @@ bool IDBBackingStore::setIDBDatabaseMetaData(const String& name, const String& v
return true;
}
-void IDBBackingStore::getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags)
+void IDBSQLiteBackingStore::getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags)
{
SQLiteStatement query(m_db, "SELECT id, name, keyPath, doAutoIncrement FROM ObjectStores WHERE databaseId = ?");
bool ok = query.prepare() == SQLResultOk;
@@ -263,7 +263,7 @@ void IDBBackingStore::getObjectStores(int64_t databaseId, Vector<int64_t>& found
}
}
-bool IDBBackingStore::createObjectStore(const String& name, const String& keyPath, bool autoIncrement, int64_t databaseId, int64_t& assignedObjectStoreId)
+bool IDBSQLiteBackingStore::createObjectStore(const String& name, const String& keyPath, bool autoIncrement, int64_t databaseId, int64_t& assignedObjectStoreId)
{
SQLiteStatement query(m_db, "INSERT INTO ObjectStores (name, keyPath, doAutoIncrement, databaseId) VALUES (?, ?, ?, ?)");
if (query.prepare() != SQLResultOk)
@@ -291,7 +291,7 @@ static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id)
ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
}
-void IDBBackingStore::deleteObjectStore(int64_t objectStoreId)
+void IDBSQLiteBackingStore::deleteObjectStore(int64_t objectStoreId)
{
doDelete(m_db, "DELETE FROM ObjectStores WHERE id = ?", objectStoreId);
doDelete(m_db, "DELETE FROM ObjectStoreData WHERE objectStoreId = ?", objectStoreId);
@@ -373,7 +373,7 @@ static String upperCursorWhereFragment(const IDBKey& key, String comparisonOpera
return "";
}
-String IDBBackingStore::getObjectStoreRecord(int64_t objectStoreId, const IDBKey& key)
+String IDBSQLiteBackingStore::getObjectStoreRecord(int64_t objectStoreId, const IDBKey& key)
{
SQLiteStatement query(m_db, "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData WHERE objectStoreId = ? AND " + whereSyntaxForKey(key));
bool ok = query.prepare() == SQLResultOk;
@@ -422,7 +422,7 @@ static void bindKeyToQueryWithNulls(SQLiteStatement& query, int baseColumn, cons
}
}
-bool IDBBackingStore::putObjectStoreRecord(int64_t objectStoreId, const IDBKey& key, const String& value, int64_t& rowId, bool invalidRowId)
+bool IDBSQLiteBackingStore::putObjectStoreRecord(int64_t objectStoreId, const IDBKey& key, const String& value, int64_t& rowId, bool invalidRowId)
{
String sql = !invalidRowId ? "UPDATE ObjectStoreData SET keyString = ?, keyDate = ?, keyNumber = ?, value = ? WHERE id = ?"
: "INSERT INTO ObjectStoreData (keyString, keyDate, keyNumber, value, objectStoreId) VALUES (?, ?, ?, ?, ?)";
@@ -446,13 +446,13 @@ bool IDBBackingStore::putObjectStoreRecord(int64_t objectStoreId, const IDBKey&
return true;
}
-void IDBBackingStore::clearObjectStore(int64_t objectStoreId)
+void IDBSQLiteBackingStore::clearObjectStore(int64_t objectStoreId)
{
doDelete(m_db, "DELETE FROM IndexData WHERE objectStoreDataId IN (SELECT id FROM ObjectStoreData WHERE objectStoreId = ?)", objectStoreId);
doDelete(m_db, "DELETE FROM ObjectStoreData WHERE objectStoreId = ?", objectStoreId);
}
-void IDBBackingStore::deleteObjectStoreRecord(int64_t, int64_t objectStoreDataId)
+void IDBSQLiteBackingStore::deleteObjectStoreRecord(int64_t, int64_t objectStoreDataId)
{
SQLiteStatement osQuery(m_db, "DELETE FROM ObjectStoreData WHERE id = ?");
bool ok = osQuery.prepare() == SQLResultOk;
@@ -473,7 +473,7 @@ void IDBBackingStore::deleteObjectStoreRecord(int64_t, int64_t objectStoreDataId
ASSERT_UNUSED(ok, ok);
}
-double IDBBackingStore::nextAutoIncrementNumber(int64_t objectStoreId)
+double IDBSQLiteBackingStore::nextAutoIncrementNumber(int64_t objectStoreId)
{
SQLiteStatement query(m_db, "SELECT max(keyNumber) + 1 FROM ObjectStoreData WHERE objectStoreId = ? AND keyString IS NULL AND keyDate IS NULL");
bool ok = query.prepare() == SQLResultOk;
@@ -487,7 +487,7 @@ double IDBBackingStore::nextAutoIncrementNumber(int64_t objectStoreId)
return query.getColumnDouble(0);
}
-bool IDBBackingStore::keyExistsInObjectStore(int64_t objectStoreId, const IDBKey& key, int64_t& foundObjectStoreDataId)
+bool IDBSQLiteBackingStore::keyExistsInObjectStore(int64_t objectStoreId, const IDBKey& key, int64_t& foundObjectStoreDataId)
{
String sql = String("SELECT id FROM ObjectStoreData WHERE objectStoreId = ? AND ") + whereSyntaxForKey(key);
SQLiteStatement query(m_db, sql);
@@ -504,7 +504,7 @@ bool IDBBackingStore::keyExistsInObjectStore(int64_t objectStoreId, const IDBKey
return true;
}
-bool IDBBackingStore::forEachObjectStoreRecord(int64_t objectStoreId, ObjectStoreRecordCallback& callback)
+bool IDBSQLiteBackingStore::forEachObjectStoreRecord(int64_t objectStoreId, ObjectStoreRecordCallback& callback)
{
SQLiteStatement query(m_db, "SELECT id, value FROM ObjectStoreData WHERE objectStoreId = ?");
if (query.prepare() != SQLResultOk)
@@ -522,7 +522,7 @@ bool IDBBackingStore::forEachObjectStoreRecord(int64_t objectStoreId, ObjectStor
return true;
}
-void IDBBackingStore::getIndexes(int64_t objectStoreId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundUniqueFlags)
+void IDBSQLiteBackingStore::getIndexes(int64_t objectStoreId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundUniqueFlags)
{
SQLiteStatement query(m_db, "SELECT id, name, keyPath, isUnique FROM Indexes WHERE objectStoreId = ?");
bool ok = query.prepare() == SQLResultOk;
@@ -543,7 +543,7 @@ void IDBBackingStore::getIndexes(int64_t objectStoreId, Vector<int64_t>& foundId
}
}
-bool IDBBackingStore::createIndex(int64_t objectStoreId, const String& name, const String& keyPath, bool isUnique, int64_t& indexId)
+bool IDBSQLiteBackingStore::createIndex(int64_t objectStoreId, const String& name, const String& keyPath, bool isUnique, int64_t& indexId)
{
SQLiteStatement query(m_db, "INSERT INTO Indexes (objectStoreId, name, keyPath, isUnique) VALUES (?, ?, ?, ?)");
if (query.prepare() != SQLResultOk)
@@ -561,13 +561,13 @@ bool IDBBackingStore::createIndex(int64_t objectStoreId, const String& name, con
return true;
}
-void IDBBackingStore::deleteIndex(int64_t indexId)
+void IDBSQLiteBackingStore::deleteIndex(int64_t indexId)
{
doDelete(m_db, "DELETE FROM Indexes WHERE id = ?", indexId);
doDelete(m_db, "DELETE FROM IndexData WHERE indexId = ?", indexId);
}
-bool IDBBackingStore::putIndexDataForRecord(int64_t indexId, const IDBKey& key, int64_t objectStoreDataId)
+bool IDBSQLiteBackingStore::putIndexDataForRecord(int64_t indexId, const IDBKey& key, int64_t objectStoreDataId)
{
SQLiteStatement query(m_db, "INSERT INTO IndexData (keyString, keyDate, keyNumber, indexId, objectStoreDataId) VALUES (?, ?, ?, ?, ?)");
if (query.prepare() != SQLResultOk)
@@ -580,7 +580,7 @@ bool IDBBackingStore::putIndexDataForRecord(int64_t indexId, const IDBKey& key,
return query.step() == SQLResultDone;
}
-bool IDBBackingStore::deleteIndexDataForRecord(int64_t objectStoreDataId)
+bool IDBSQLiteBackingStore::deleteIndexDataForRecord(int64_t objectStoreDataId)
{
SQLiteStatement query(m_db, "DELETE FROM IndexData WHERE objectStoreDataId = ?");
if (query.prepare() != SQLResultOk)
@@ -590,7 +590,7 @@ bool IDBBackingStore::deleteIndexDataForRecord(int64_t objectStoreDataId)
return query.step() == SQLResultDone;
}
-String IDBBackingStore::getObjectViaIndex(int64_t indexId, const IDBKey& key)
+String IDBSQLiteBackingStore::getObjectViaIndex(int64_t indexId, const IDBKey& key)
{
String sql = String("SELECT ")
+ "ObjectStoreData.value "
@@ -629,7 +629,7 @@ static PassRefPtr<IDBKey> keyFromQuery(SQLiteStatement& query, int baseColumn)
return IDBKey::createNull();
}
-PassRefPtr<IDBKey> IDBBackingStore::getPrimaryKeyViaIndex(int64_t indexId, const IDBKey& key)
+PassRefPtr<IDBKey> IDBSQLiteBackingStore::getPrimaryKeyViaIndex(int64_t indexId, const IDBKey& key)
{
String sql = String("SELECT ")
+ "ObjectStoreData.keyString, ObjectStoreData.keyDate, ObjectStoreData.keyNumber "
@@ -651,7 +651,7 @@ PassRefPtr<IDBKey> IDBBackingStore::getPrimaryKeyViaIndex(int64_t indexId, const
return foundKey.release();
}
-bool IDBBackingStore::keyExistsInIndex(int64_t indexId, const IDBKey& key)
+bool IDBSQLiteBackingStore::keyExistsInIndex(int64_t indexId, const IDBKey& key)
{
String sql = String("SELECT id FROM IndexData WHERE indexId = ? AND ") + whereSyntaxForKey(key);
SQLiteStatement query(m_db, sql);
@@ -666,7 +666,7 @@ bool IDBBackingStore::keyExistsInIndex(int64_t indexId, const IDBKey& key)
namespace {
-class CursorImplCommon : public IDBBackingStore::Cursor {
+class CursorImplCommon : public IDBSQLiteBackingStore::Cursor {
public:
CursorImplCommon(SQLiteDatabase& sqliteDatabase, String query, bool uniquenessConstraint, bool iterateForward)
: m_query(sqliteDatabase, query)
@@ -849,7 +849,7 @@ bool IndexCursorImpl::currentRowExists()
} // namespace
-PassRefPtr<IDBBackingStore::Cursor> IDBBackingStore::openObjectStoreCursor(int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction)
+PassRefPtr<IDBBackingStore::Cursor> IDBSQLiteBackingStore::openObjectStoreCursor(int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction)
{
bool lowerBound = range && range->lower();
bool upperBound = range && range->upper();
@@ -886,7 +886,7 @@ PassRefPtr<IDBBackingStore::Cursor> IDBBackingStore::openObjectStoreCursor(int64
return cursor.release();
}
-PassRefPtr<IDBBackingStore::Cursor> IDBBackingStore::openIndexKeyCursor(int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
+PassRefPtr<IDBBackingStore::Cursor> IDBSQLiteBackingStore::openIndexKeyCursor(int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
{
String sql = String("SELECT IndexData.id, IndexData.keyString, IndexData.keyDate, IndexData.keyNumber, ")
+ ("ObjectStoreData.keyString, ObjectStoreData.keyDate, ObjectStoreData.keyNumber ")
@@ -926,7 +926,7 @@ PassRefPtr<IDBBackingStore::Cursor> IDBBackingStore::openIndexKeyCursor(int64_t
return cursor.release();
}
-PassRefPtr<IDBBackingStore::Cursor> IDBBackingStore::openIndexCursor(int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
+PassRefPtr<IDBBackingStore::Cursor> IDBSQLiteBackingStore::openIndexCursor(int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
{
String sql = String("SELECT IndexData.id, IndexData.keyString, IndexData.keyDate, IndexData.keyNumber, ")
+ ("ObjectStoreData.value, ObjectStoreData.keyString, ObjectStoreData.keyDate, ObjectStoreData.keyNumber ")
@@ -986,7 +986,7 @@ private:
} // namespace
-PassRefPtr<IDBBackingStore::Transaction> IDBBackingStore::createTransaction()
+PassRefPtr<IDBBackingStore::Transaction> IDBSQLiteBackingStore::createTransaction()
{
return adoptRef(new TransactionImpl(m_db));
}
diff --git a/Source/WebCore/storage/IDBSQLiteBackingStore.h b/Source/WebCore/storage/IDBSQLiteBackingStore.h
new file mode 100644
index 0000000..fe0c6c1
--- /dev/null
+++ b/Source/WebCore/storage/IDBSQLiteBackingStore.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 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 IDBSQLiteBackingStore_h
+#define IDBSQLiteBackingStore_h
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBBackingStore.h"
+
+namespace WebCore {
+
+class IDBSQLiteBackingStore : public IDBBackingStore {
+public:
+ static PassRefPtr<IDBBackingStore> open(SecurityOrigin*, const String& pathBase, int64_t maximumSize, const String& fileIdentifier, IDBFactoryBackendImpl*);
+ virtual ~IDBSQLiteBackingStore();
+
+ virtual bool extractIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId);
+ virtual bool setIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId, bool invalidRowId);
+
+ virtual void getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags);
+ virtual bool createObjectStore(const String& name, const String& keyPath, bool autoIncrement, int64_t databaseId, int64_t& assignedObjectStoreId);
+ virtual void deleteObjectStore(int64_t objectStoreId);
+ virtual String getObjectStoreRecord(int64_t objectStoreId, const IDBKey&);
+ virtual bool putObjectStoreRecord(int64_t objectStoreId, const IDBKey&, const String& value, int64_t& rowId, bool invalidRowId);
+ virtual void clearObjectStore(int64_t objectStoreId);
+ virtual void deleteObjectStoreRecord(int64_t objectStoreId, int64_t objectStoreDataId);
+ virtual double nextAutoIncrementNumber(int64_t objectStoreId);
+ virtual bool keyExistsInObjectStore(int64_t objectStoreId, const IDBKey&, int64_t& foundObjectStoreDataId);
+
+ virtual bool forEachObjectStoreRecord(int64_t objectStoreId, ObjectStoreRecordCallback&);
+
+ virtual void getIndexes(int64_t objectStoreId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundUniqueFlags);
+ virtual bool createIndex(int64_t objectStoreId, const String& name, const String& keyPath, bool isUnique, int64_t& indexId);
+ virtual void deleteIndex(int64_t indexId);
+ virtual bool putIndexDataForRecord(int64_t indexId, const IDBKey&, int64_t objectStoreDataId);
+ virtual bool deleteIndexDataForRecord(int64_t objectStoreDataId);
+ virtual String getObjectViaIndex(int64_t indexId, const IDBKey&);
+ virtual PassRefPtr<IDBKey> getPrimaryKeyViaIndex(int64_t indexId, const IDBKey&);
+ virtual bool keyExistsInIndex(int64_t indexId, const IDBKey&);
+
+ virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction);
+ virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t indexId, const IDBKeyRange*, IDBCursor::Direction);
+ virtual PassRefPtr<Cursor> openIndexCursor(int64_t indexId, const IDBKeyRange*, IDBCursor::Direction);
+
+ virtual PassRefPtr<Transaction> createTransaction();
+
+private:
+ IDBSQLiteBackingStore(String identifier, IDBFactoryBackendImpl*);
+
+ SQLiteDatabase m_db;
+ String m_identifier;
+ RefPtr<IDBFactoryBackendImpl> m_factory;
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // IDBSQLiteBackingStore_h
diff --git a/Source/WebCore/storage/IDBTransactionBackendInterface.h b/Source/WebCore/storage/IDBTransactionBackendInterface.h
index 1b370af..3432e9a 100644
--- a/Source/WebCore/storage/IDBTransactionBackendInterface.h
+++ b/Source/WebCore/storage/IDBTransactionBackendInterface.h
@@ -43,7 +43,7 @@ class IDBTransactionCallbacks;
// This is implemented by IDBTransactionBackendImpl and optionally others (in order to proxy
// calls across process barriers). All calls to these classes should be non-blocking and
// trigger work on a background thread if necessary.
-class IDBTransactionBackendInterface : public ThreadSafeShared<IDBTransactionBackendInterface> {
+class IDBTransactionBackendInterface : public ThreadSafeRefCounted<IDBTransactionBackendInterface> {
public:
virtual ~IDBTransactionBackendInterface() { }
diff --git a/Source/WebCore/storage/LocalStorageTask.cpp b/Source/WebCore/storage/LocalStorageTask.cpp
index d31c991..5d2c807 100644
--- a/Source/WebCore/storage/LocalStorageTask.cpp
+++ b/Source/WebCore/storage/LocalStorageTask.cpp
@@ -30,6 +30,7 @@
#include "LocalStorageThread.h"
#include "StorageAreaSync.h"
+#include "StorageTracker.h"
namespace WebCore {
@@ -50,6 +51,27 @@ LocalStorageTask::LocalStorageTask(Type type, LocalStorageThread* thread)
ASSERT(m_thread);
ASSERT(m_type == TerminateThread);
}
+
+LocalStorageTask::LocalStorageTask(Type type)
+ : m_type(type)
+{
+ ASSERT(m_type == ImportOrigins || m_type == DeleteAllOrigins);
+}
+
+LocalStorageTask::LocalStorageTask(Type type, const String& originIdentifier)
+ : m_type(type)
+ , m_originIdentifier(originIdentifier)
+{
+ ASSERT(m_type == DeleteOrigin);
+}
+
+LocalStorageTask::LocalStorageTask(Type type, const String& originIdentifier, const String& databaseFilename)
+ : m_type(type)
+ , m_originIdentifier(originIdentifier)
+ , m_databaseFilename(databaseFilename)
+{
+ ASSERT(m_type == SetOriginDetails);
+}
LocalStorageTask::~LocalStorageTask()
{
@@ -64,6 +86,18 @@ void LocalStorageTask::performTask()
case AreaSync:
m_area->performSync();
break;
+ case SetOriginDetails:
+ StorageTracker::tracker().syncSetOriginDetails(m_originIdentifier, m_databaseFilename);
+ break;
+ case ImportOrigins:
+ StorageTracker::tracker().syncImportOriginIdentifiers();
+ break;
+ case DeleteAllOrigins:
+ StorageTracker::tracker().syncDeleteAllOrigins();
+ break;
+ case DeleteOrigin:
+ StorageTracker::tracker().syncDeleteOrigin(m_originIdentifier);
+ break;
case DeleteEmptyDatabase:
m_area->deleteEmptyDatabase();
break;
diff --git a/Source/WebCore/storage/LocalStorageTask.h b/Source/WebCore/storage/LocalStorageTask.h
index 27a8eb5..99e72f5 100644
--- a/Source/WebCore/storage/LocalStorageTask.h
+++ b/Source/WebCore/storage/LocalStorageTask.h
@@ -28,6 +28,7 @@
#if ENABLE(DOM_STORAGE)
+#include "PlatformString.h"
#include <wtf/PassOwnPtr.h>
#include <wtf/Threading.h>
@@ -40,13 +41,17 @@ namespace WebCore {
class LocalStorageTask {
WTF_MAKE_NONCOPYABLE(LocalStorageTask); WTF_MAKE_FAST_ALLOCATED;
public:
- enum Type { AreaImport, AreaSync, DeleteEmptyDatabase, TerminateThread };
+ enum Type { AreaImport, AreaSync, DeleteEmptyDatabase, SetOriginDetails, ImportOrigins, DeleteAllOrigins, DeleteOrigin, TerminateThread };
~LocalStorageTask();
static PassOwnPtr<LocalStorageTask> createImport(StorageAreaSync* area) { return adoptPtr(new LocalStorageTask(AreaImport, area)); }
static PassOwnPtr<LocalStorageTask> createSync(StorageAreaSync* area) { return adoptPtr(new LocalStorageTask(AreaSync, area)); }
static PassOwnPtr<LocalStorageTask> createDeleteEmptyDatabase(StorageAreaSync* area) { return adoptPtr(new LocalStorageTask(DeleteEmptyDatabase, area)); }
+ static PassOwnPtr<LocalStorageTask> createOriginIdentifiersImport() { return adoptPtr(new LocalStorageTask(ImportOrigins)); }
+ static PassOwnPtr<LocalStorageTask> createSetOriginDetails(const String& originIdentifier, const String& databaseFilename) { return adoptPtr(new LocalStorageTask(SetOriginDetails, originIdentifier, databaseFilename)); }
+ static PassOwnPtr<LocalStorageTask> createDeleteOrigin(const String& originIdentifier) { return adoptPtr(new LocalStorageTask(DeleteOrigin, originIdentifier)); }
+ static PassOwnPtr<LocalStorageTask> createDeleteAllOrigins() { return adoptPtr(new LocalStorageTask(DeleteAllOrigins)); }
static PassOwnPtr<LocalStorageTask> createTerminate(LocalStorageThread* thread) { return adoptPtr(new LocalStorageTask(TerminateThread, thread)); }
void performTask();
@@ -54,10 +59,15 @@ namespace WebCore {
private:
LocalStorageTask(Type, StorageAreaSync*);
LocalStorageTask(Type, LocalStorageThread*);
+ LocalStorageTask(Type, const String& originIdentifier);
+ LocalStorageTask(Type, const String& originIdentifier, const String& databaseFilename);
+ LocalStorageTask(Type);
Type m_type;
StorageAreaSync* m_area;
LocalStorageThread* m_thread;
+ String m_originIdentifier;
+ String m_databaseFilename;
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/SQLCallbackWrapper.h b/Source/WebCore/storage/SQLCallbackWrapper.h
new file mode 100644
index 0000000..38059fa
--- /dev/null
+++ b/Source/WebCore/storage/SQLCallbackWrapper.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 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 SQLCallbackWrapper_h
+#define SQLCallbackWrapper_h
+
+#if ENABLE(DATABASE)
+
+#include "CrossThreadTask.h"
+#include "ScriptExecutionContext.h"
+#include <wtf/ThreadingPrimitives.h>
+
+namespace WebCore {
+
+// A helper class to safely dereference the callback objects held by
+// SQLStatement and SQLTransaction on the proper thread. The 'wrapped'
+// callback is dereferenced:
+// - by destructing the enclosing wrapper - on any thread
+// - by calling clear() - on any thread
+// - by unwrapping and then dereferencing normally - on context thread only
+template<typename T> class SQLCallbackWrapper {
+public:
+ SQLCallbackWrapper(PassRefPtr<T> callback, ScriptExecutionContext* scriptExecutionContext)
+ : m_callback(callback)
+ , m_scriptExecutionContext(m_callback ? scriptExecutionContext : 0)
+ {
+ ASSERT(!m_callback || (m_scriptExecutionContext.get() && m_scriptExecutionContext->isContextThread()));
+ }
+
+ ~SQLCallbackWrapper()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ ScriptExecutionContext* context;
+ T* callback;
+ {
+ MutexLocker locker(m_mutex);
+ if (!m_callback) {
+ ASSERT(!m_scriptExecutionContext);
+ return;
+ }
+ if (m_scriptExecutionContext->isContextThread()) {
+ m_callback = 0;
+ m_scriptExecutionContext = 0;
+ return;
+ }
+ context = m_scriptExecutionContext.release().leakRef();
+ callback = m_callback.release().leakRef();
+ }
+ context->postTask(createCallbackTask(&safeRelease, callback));
+ }
+
+ PassRefPtr<T> unwrap()
+ {
+ MutexLocker locker(m_mutex);
+ ASSERT(!m_callback || m_scriptExecutionContext->isContextThread());
+ m_scriptExecutionContext = 0;
+ return m_callback.release();
+ }
+
+ // Useful for optimizations only, please test the return value of unwrap to be sure.
+ bool hasCallback() const { return m_callback; }
+
+private:
+ static void safeRelease(ScriptExecutionContext* context, T* callback)
+ {
+ ASSERT(callback && context && context->isContextThread());
+ callback->deref();
+ context->deref();
+ }
+
+ Mutex m_mutex;
+ RefPtr<T> m_callback;
+ RefPtr<ScriptExecutionContext> m_scriptExecutionContext;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DATABASE)
+
+#endif // SQLCallbackWrapper_h
diff --git a/Source/WebCore/storage/SQLError.h b/Source/WebCore/storage/SQLError.h
index 496145a..eb9005b 100644
--- a/Source/WebCore/storage/SQLError.h
+++ b/Source/WebCore/storage/SQLError.h
@@ -32,11 +32,11 @@
#if ENABLE(DATABASE)
#include "PlatformString.h"
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
namespace WebCore {
-class SQLError : public ThreadSafeShared<SQLError> {
+class SQLError : public ThreadSafeRefCounted<SQLError> {
public:
static PassRefPtr<SQLError> create(unsigned code, const String& message) { return adoptRef(new SQLError(code, message)); }
diff --git a/Source/WebCore/storage/SQLResultSet.h b/Source/WebCore/storage/SQLResultSet.h
index 268472f..964504c 100644
--- a/Source/WebCore/storage/SQLResultSet.h
+++ b/Source/WebCore/storage/SQLResultSet.h
@@ -33,11 +33,11 @@
#include "ExceptionCode.h"
#include "SQLResultSetRowList.h"
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
namespace WebCore {
-class SQLResultSet : public ThreadSafeShared<SQLResultSet> {
+class SQLResultSet : public ThreadSafeRefCounted<SQLResultSet> {
public:
static PassRefPtr<SQLResultSet> create() { return adoptRef(new SQLResultSet); }
diff --git a/Source/WebCore/storage/SQLStatement.cpp b/Source/WebCore/storage/SQLStatement.cpp
index 306f561..58b7f71 100644
--- a/Source/WebCore/storage/SQLStatement.cpp
+++ b/Source/WebCore/storage/SQLStatement.cpp
@@ -43,16 +43,16 @@
namespace WebCore {
-PassRefPtr<SQLStatement> SQLStatement::create(const String& statement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> errorCallback, int permissions)
+PassRefPtr<SQLStatement> SQLStatement::create(Database* database, const String& statement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> errorCallback, int permissions)
{
- return adoptRef(new SQLStatement(statement, arguments, callback, errorCallback, permissions));
+ return adoptRef(new SQLStatement(database, statement, arguments, callback, errorCallback, permissions));
}
-SQLStatement::SQLStatement(const String& statement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> errorCallback, int permissions)
+SQLStatement::SQLStatement(Database* database, const String& statement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> errorCallback, int permissions)
: m_statement(statement.crossThreadString())
, m_arguments(arguments)
- , m_statementCallback(callback)
- , m_statementErrorCallback(errorCallback)
+ , m_statementCallbackWrapper(callback, database->scriptExecutionContext())
+ , m_statementErrorCallbackWrapper(errorCallback, database->scriptExecutionContext())
, m_permissions(permissions)
{
}
@@ -166,17 +166,16 @@ bool SQLStatement::performCallback(SQLTransaction* transaction)
bool callbackError = false;
+ RefPtr<SQLStatementCallback> callback = m_statementCallbackWrapper.unwrap();
+ RefPtr<SQLStatementErrorCallback> errorCallback = m_statementErrorCallbackWrapper.unwrap();
+
// Call the appropriate statement callback and track if it resulted in an error,
// because then we need to jump to the transaction error callback.
if (m_error) {
- ASSERT(m_statementErrorCallback);
- callbackError = m_statementErrorCallback->handleEvent(transaction, m_error.get());
- } else if (m_statementCallback)
- callbackError = !m_statementCallback->handleEvent(transaction, m_resultSet.get());
-
- // Now release our callbacks, to break reference cycles.
- m_statementCallback = 0;
- m_statementErrorCallback = 0;
+ ASSERT(errorCallback);
+ callbackError = errorCallback->handleEvent(transaction, m_error.get());
+ } else if (callback)
+ callbackError = !callback->handleEvent(transaction, m_resultSet.get());
return callbackError;
}
diff --git a/Source/WebCore/storage/SQLStatement.h b/Source/WebCore/storage/SQLStatement.h
index afd605a..1d81eb2 100644
--- a/Source/WebCore/storage/SQLStatement.h
+++ b/Source/WebCore/storage/SQLStatement.h
@@ -31,6 +31,7 @@
#if ENABLE(DATABASE)
#include "PlatformString.h"
+#include "SQLCallbackWrapper.h"
#include "SQLResultSet.h"
#include "SQLValue.h"
#include <wtf/Forward.h>
@@ -44,15 +45,15 @@ class SQLStatementCallback;
class SQLStatementErrorCallback;
class SQLTransaction;
-class SQLStatement : public ThreadSafeShared<SQLStatement> {
+class SQLStatement : public ThreadSafeRefCounted<SQLStatement> {
public:
- static PassRefPtr<SQLStatement> create(const String&, const Vector<SQLValue>&, PassRefPtr<SQLStatementCallback>, PassRefPtr<SQLStatementErrorCallback>, int permissions);
+ static PassRefPtr<SQLStatement> create(Database*, const String&, const Vector<SQLValue>&, PassRefPtr<SQLStatementCallback>, PassRefPtr<SQLStatementErrorCallback>, int permissions);
bool execute(Database*);
bool lastExecutionFailedDueToQuota() const;
- bool hasStatementCallback() const { return m_statementCallback; }
- bool hasStatementErrorCallback() const { return m_statementErrorCallback; }
+ bool hasStatementCallback() const { return m_statementCallbackWrapper.hasCallback(); }
+ bool hasStatementErrorCallback() const { return m_statementErrorCallbackWrapper.hasCallback(); }
void setDatabaseDeletedError();
void setVersionMismatchedError();
@@ -61,15 +62,15 @@ public:
SQLError* sqlError() const { return m_error.get(); }
private:
- SQLStatement(const String& statement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback>, PassRefPtr<SQLStatementErrorCallback>, int permissions);
+ SQLStatement(Database*, const String& statement, const Vector<SQLValue>& arguments, PassRefPtr<SQLStatementCallback>, PassRefPtr<SQLStatementErrorCallback>, int permissions);
void setFailureDueToQuota();
void clearFailureDueToQuota();
String m_statement;
Vector<SQLValue> m_arguments;
- RefPtr<SQLStatementCallback> m_statementCallback;
- RefPtr<SQLStatementErrorCallback> m_statementErrorCallback;
+ SQLCallbackWrapper<SQLStatementCallback> m_statementCallbackWrapper;
+ SQLCallbackWrapper<SQLStatementErrorCallback> m_statementErrorCallbackWrapper;
RefPtr<SQLError> m_error;
RefPtr<SQLResultSet> m_resultSet;
diff --git a/Source/WebCore/storage/SQLStatementCallback.h b/Source/WebCore/storage/SQLStatementCallback.h
index f86e29f..cae5827 100644
--- a/Source/WebCore/storage/SQLStatementCallback.h
+++ b/Source/WebCore/storage/SQLStatementCallback.h
@@ -30,14 +30,14 @@
#if ENABLE(DATABASE)
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
namespace WebCore {
class SQLTransaction;
class SQLResultSet;
-class SQLStatementCallback : public ThreadSafeShared<SQLStatementCallback> {
+class SQLStatementCallback : public ThreadSafeRefCounted<SQLStatementCallback> {
public:
virtual ~SQLStatementCallback() { }
virtual bool handleEvent(SQLTransaction*, SQLResultSet*) = 0;
diff --git a/Source/WebCore/storage/SQLStatementErrorCallback.h b/Source/WebCore/storage/SQLStatementErrorCallback.h
index acb8f64..5fecec4 100644
--- a/Source/WebCore/storage/SQLStatementErrorCallback.h
+++ b/Source/WebCore/storage/SQLStatementErrorCallback.h
@@ -31,14 +31,14 @@
#if ENABLE(DATABASE)
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
namespace WebCore {
class SQLTransaction;
class SQLError;
-class SQLStatementErrorCallback : public ThreadSafeShared<SQLStatementErrorCallback> {
+class SQLStatementErrorCallback : public ThreadSafeRefCounted<SQLStatementErrorCallback> {
public:
virtual ~SQLStatementErrorCallback() { }
virtual bool handleEvent(SQLTransaction*, SQLError*) = 0;
diff --git a/Source/WebCore/storage/SQLTransaction.cpp b/Source/WebCore/storage/SQLTransaction.cpp
index dea9d97..dfcd568 100644
--- a/Source/WebCore/storage/SQLTransaction.cpp
+++ b/Source/WebCore/storage/SQLTransaction.cpp
@@ -71,9 +71,9 @@ SQLTransaction::SQLTransaction(Database* db, PassRefPtr<SQLTransactionCallback>
, m_executeSqlAllowed(false)
, m_database(db)
, m_wrapper(wrapper)
- , m_callback(callback)
- , m_successCallback(successCallback)
- , m_errorCallback(errorCallback)
+ , m_callbackWrapper(callback, db->scriptExecutionContext())
+ , m_successCallbackWrapper(successCallback, db->scriptExecutionContext())
+ , m_errorCallbackWrapper(errorCallback, db->scriptExecutionContext())
, m_shouldRetryCurrentStatement(false)
, m_modifiedDatabase(false)
, m_lockAcquired(false)
@@ -100,7 +100,7 @@ void SQLTransaction::executeSQL(const String& sqlStatement, const Vector<SQLValu
else if (m_readOnly)
permissions |= DatabaseAuthorizer::ReadOnlyMask;
- RefPtr<SQLStatement> statement = SQLStatement::create(sqlStatement, arguments, callback, callbackError, permissions);
+ RefPtr<SQLStatement> statement = SQLStatement::create(m_database.get(), sqlStatement, arguments, callback, callbackError, permissions);
if (m_database->deleted())
statement->setDatabaseDeletedError();
@@ -159,9 +159,9 @@ void SQLTransaction::checkAndHandleClosedOrInterruptedDatabase()
m_nextStep = 0;
// Release the unneeded callbacks, to break reference cycles.
- m_callback = 0;
- m_successCallback = 0;
- m_errorCallback = 0;
+ m_callbackWrapper.clear();
+ m_successCallbackWrapper.clear();
+ m_errorCallbackWrapper.clear();
// The next steps should be executed only if we're on the DB thread.
if (currentThread() != database()->scriptExecutionContext()->databaseThread()->getThreadID())
@@ -293,11 +293,11 @@ void SQLTransaction::deliverTransactionCallback()
{
bool shouldDeliverErrorCallback = false;
- if (m_callback) {
+ RefPtr<SQLTransactionCallback> callback = m_callbackWrapper.unwrap();
+ if (callback) {
m_executeSqlAllowed = true;
- shouldDeliverErrorCallback = !m_callback->handleEvent(this);
+ shouldDeliverErrorCallback = !callback->handleEvent(this);
m_executeSqlAllowed = false;
- m_callback = 0;
}
// Transaction Step 5 - If the transaction callback was null or raised an exception, jump to the error callback
@@ -425,7 +425,7 @@ void SQLTransaction::deliverStatementCallback()
m_executeSqlAllowed = false;
if (result) {
- m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "the statement callback raised an exception or statement error callback did not return false");
+ m_transactionError = SQLError::create(SQLError::UNKNOWN_ERR, "the statement callback raised an exception or statement error callback did not return false");
handleTransactionError(true);
} else
scheduleToRunStatements();
@@ -465,7 +465,7 @@ void SQLTransaction::postflightAndCommit()
// If the commit failed, the transaction will still be marked as "in progress"
if (m_sqliteTransaction->inProgress()) {
- m_successCallback = 0;
+ m_successCallbackWrapper.clear();
m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "failed to commit the transaction");
handleTransactionError(false);
return;
@@ -480,10 +480,10 @@ void SQLTransaction::postflightAndCommit()
m_database->transactionClient()->didCommitWriteTransaction(database());
// Now release our unneeded callbacks, to break reference cycles.
- m_errorCallback = 0;
+ m_errorCallbackWrapper.clear();
// Transaction Step 10 - Deliver success callback, if there is one
- if (m_successCallback) {
+ if (m_successCallbackWrapper.hasCallback()) {
m_nextStep = &SQLTransaction::deliverSuccessCallback;
LOG(StorageAPI, "Scheduling deliverSuccessCallback for transaction %p\n", this);
m_database->scheduleTransactionCallback(this);
@@ -494,11 +494,9 @@ void SQLTransaction::postflightAndCommit()
void SQLTransaction::deliverSuccessCallback()
{
// Transaction Step 10 - Deliver success callback
- ASSERT(m_successCallback);
- m_successCallback->handleEvent();
-
- // Release the last callback to break reference cycle
- m_successCallback = 0;
+ RefPtr<VoidCallback> successCallback = m_successCallbackWrapper.unwrap();
+ if (successCallback)
+ successCallback->handleEvent();
// Schedule a "post-success callback" step to return control to the database thread in case there
// are further transactions queued up for this Database
@@ -524,7 +522,7 @@ void SQLTransaction::cleanupAfterSuccessCallback()
void SQLTransaction::handleTransactionError(bool inCallback)
{
- if (m_errorCallback) {
+ if (m_errorCallbackWrapper.hasCallback()) {
if (inCallback)
deliverTransactionErrorCallback();
else {
@@ -552,10 +550,9 @@ void SQLTransaction::deliverTransactionErrorCallback()
// Transaction Step 12 - If exists, invoke error callback with the last
// error to have occurred in this transaction.
- if (m_errorCallback) {
- m_errorCallback->handleEvent(m_transactionError.get());
- m_errorCallback = 0;
- }
+ RefPtr<SQLTransactionErrorCallback> errorCallback = m_errorCallbackWrapper.unwrap();
+ if (errorCallback)
+ errorCallback->handleEvent(m_transactionError.get());
m_nextStep = &SQLTransaction::cleanupAfterTransactionErrorCallback;
LOG(StorageAPI, "Scheduling cleanupAfterTransactionErrorCallback for transaction %p\n", this);
diff --git a/Source/WebCore/storage/SQLTransaction.h b/Source/WebCore/storage/SQLTransaction.h
index 3eb1fd5..4c84f91 100644
--- a/Source/WebCore/storage/SQLTransaction.h
+++ b/Source/WebCore/storage/SQLTransaction.h
@@ -34,7 +34,7 @@
#include "SQLStatement.h"
#include <wtf/Deque.h>
#include <wtf/Forward.h>
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/Vector.h>
namespace WebCore {
@@ -50,7 +50,7 @@ class SQLTransactionErrorCallback;
class SQLValue;
class VoidCallback;
-class SQLTransactionWrapper : public ThreadSafeShared<SQLTransactionWrapper> {
+class SQLTransactionWrapper : public ThreadSafeRefCounted<SQLTransactionWrapper> {
public:
virtual ~SQLTransactionWrapper() { }
virtual bool performPreflight(SQLTransaction*) = 0;
@@ -59,7 +59,7 @@ public:
virtual SQLError* sqlError() const = 0;
};
-class SQLTransaction : public ThreadSafeShared<SQLTransaction> {
+class SQLTransaction : public ThreadSafeRefCounted<SQLTransaction> {
public:
static PassRefPtr<SQLTransaction> create(Database*, PassRefPtr<SQLTransactionCallback>, PassRefPtr<SQLTransactionErrorCallback>,
PassRefPtr<VoidCallback>, PassRefPtr<SQLTransactionWrapper>, bool readOnly = false);
@@ -115,9 +115,9 @@ private:
RefPtr<Database> m_database;
RefPtr<SQLTransactionWrapper> m_wrapper;
- RefPtr<SQLTransactionCallback> m_callback;
- RefPtr<VoidCallback> m_successCallback;
- RefPtr<SQLTransactionErrorCallback> m_errorCallback;
+ SQLCallbackWrapper<SQLTransactionCallback> m_callbackWrapper;
+ SQLCallbackWrapper<VoidCallback> m_successCallbackWrapper;
+ SQLCallbackWrapper<SQLTransactionErrorCallback> m_errorCallbackWrapper;
RefPtr<SQLError> m_transactionError;
bool m_shouldRetryCurrentStatement;
bool m_modifiedDatabase;
diff --git a/Source/WebCore/storage/SQLTransactionCallback.h b/Source/WebCore/storage/SQLTransactionCallback.h
index aff6233..6904880 100644
--- a/Source/WebCore/storage/SQLTransactionCallback.h
+++ b/Source/WebCore/storage/SQLTransactionCallback.h
@@ -31,13 +31,13 @@
#if ENABLE(DATABASE)
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
namespace WebCore {
class SQLTransaction;
-class SQLTransactionCallback : public ThreadSafeShared<SQLTransactionCallback> {
+class SQLTransactionCallback : public ThreadSafeRefCounted<SQLTransactionCallback> {
public:
virtual ~SQLTransactionCallback() { }
virtual bool handleEvent(SQLTransaction*) = 0;
diff --git a/Source/WebCore/storage/SQLTransactionErrorCallback.h b/Source/WebCore/storage/SQLTransactionErrorCallback.h
index 4095d6a..f067571 100644
--- a/Source/WebCore/storage/SQLTransactionErrorCallback.h
+++ b/Source/WebCore/storage/SQLTransactionErrorCallback.h
@@ -31,13 +31,13 @@
#if ENABLE(DATABASE)
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
namespace WebCore {
class SQLError;
-class SQLTransactionErrorCallback : public ThreadSafeShared<SQLTransactionErrorCallback> {
+class SQLTransactionErrorCallback : public ThreadSafeRefCounted<SQLTransactionErrorCallback> {
public:
virtual ~SQLTransactionErrorCallback() { }
virtual bool handleEvent(SQLError*) = 0;
diff --git a/Source/WebCore/storage/StorageAreaImpl.cpp b/Source/WebCore/storage/StorageAreaImpl.cpp
index 54df135..bb2d702 100644
--- a/Source/WebCore/storage/StorageAreaImpl.cpp
+++ b/Source/WebCore/storage/StorageAreaImpl.cpp
@@ -231,6 +231,31 @@ void StorageAreaImpl::close()
#endif
}
+void StorageAreaImpl::clearForOriginDeletion()
+{
+ ASSERT(!m_isShutdown);
+ blockUntilImportComplete();
+
+ if (m_storageMap->length()) {
+ unsigned quota = m_storageMap->quota();
+ m_storageMap = StorageMap::create(quota);
+ }
+
+ if (m_storageAreaSync) {
+ m_storageAreaSync->scheduleClear();
+ m_storageAreaSync->scheduleCloseDatabase();
+ }
+}
+
+void StorageAreaImpl::sync()
+{
+ ASSERT(!m_isShutdown);
+ blockUntilImportComplete();
+
+ if (m_storageAreaSync)
+ m_storageAreaSync->scheduleSync();
+}
+
void StorageAreaImpl::blockUntilImportComplete() const
{
if (m_storageAreaSync)
diff --git a/Source/WebCore/storage/StorageAreaImpl.h b/Source/WebCore/storage/StorageAreaImpl.h
index 60d72cb..9f87e69 100644
--- a/Source/WebCore/storage/StorageAreaImpl.h
+++ b/Source/WebCore/storage/StorageAreaImpl.h
@@ -59,6 +59,11 @@ namespace WebCore {
// Only called from a background thread.
void importItem(const String& key, const String& value);
+ // Used to clear a StorageArea and close db before backing db file is deleted.
+ void clearForOriginDeletion();
+
+ void sync();
+
private:
StorageAreaImpl(StorageType, PassRefPtr<SecurityOrigin>, PassRefPtr<StorageSyncManager>, unsigned quota);
StorageAreaImpl(StorageAreaImpl*);
diff --git a/Source/WebCore/storage/StorageAreaSync.cpp b/Source/WebCore/storage/StorageAreaSync.cpp
index f2008ab..94a002a 100644
--- a/Source/WebCore/storage/StorageAreaSync.cpp
+++ b/Source/WebCore/storage/StorageAreaSync.cpp
@@ -36,6 +36,7 @@
#include "SecurityOrigin.h"
#include "StorageAreaImpl.h"
#include "StorageSyncManager.h"
+#include "StorageTracker.h"
#include "SuddenTermination.h"
#include <wtf/text/CString.h>
@@ -60,6 +61,7 @@ inline StorageAreaSync::StorageAreaSync(PassRefPtr<StorageSyncManager> storageSy
, m_syncScheduled(false)
, m_syncInProgress(false)
, m_databaseOpenFailed(false)
+ , m_syncCloseDatabase(false)
, m_importComplete(false)
{
ASSERT(isMainThread());
@@ -138,6 +140,25 @@ void StorageAreaSync::scheduleClear()
}
}
+void StorageAreaSync::scheduleCloseDatabase()
+{
+ ASSERT(isMainThread());
+ ASSERT(!m_finalSyncScheduled);
+
+ if (!m_database.isOpen())
+ return;
+
+ m_syncCloseDatabase = true;
+
+ if (!m_syncTimer.isActive()) {
+ m_syncTimer.startOneShot(StorageSyncInterval);
+
+ // The following is balanced by the call to enableSuddenTermination in the
+ // syncTimerFired function.
+ disableSuddenTermination();
+ }
+}
+
void StorageAreaSync::syncTimerFired(Timer<StorageAreaSync>*)
{
ASSERT(isMainThread());
@@ -222,6 +243,10 @@ void StorageAreaSync::openDatabase(OpenDatabaseParamType openingStrategy)
return;
}
+ // A StorageTracker thread may have been scheduled to delete the db we're
+ // reopening, so cancel possible deletion.
+ StorageTracker::tracker().cancelDeletingOrigin(m_databaseIdentifier);
+
if (!m_database.open(databaseFilename)) {
LOG_ERROR("Failed to open database file %s for local storage", databaseFilename.utf8().data());
markImported();
@@ -235,6 +260,8 @@ void StorageAreaSync::openDatabase(OpenDatabaseParamType openingStrategy)
m_databaseOpenFailed = true;
return;
}
+
+ StorageTracker::tracker().setOriginDetails(m_databaseIdentifier, databaseFilename);
}
void StorageAreaSync::performImport()
@@ -319,6 +346,15 @@ void StorageAreaSync::sync(bool clearItems, const HashMap<String, String>& items
if (!m_database.isOpen())
return;
+ // Closing this db because it is about to be deleted by StorageTracker.
+ // The delete will be cancelled if StorageAreaSync needs to reopen the db
+ // to write new items created after the request to delete the db.
+ if (m_syncCloseDatabase) {
+ m_syncCloseDatabase = false;
+ m_database.close();
+ return;
+ }
+
// If the clear flag is set, then we clear all items out before we write any new ones in.
if (clearItems) {
SQLiteStatement clear(m_database, "DELETE FROM ItemTable");
@@ -421,12 +457,21 @@ void StorageAreaSync::deleteEmptyDatabase()
if (!count) {
query.finalize();
m_database.close();
- String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier);
- if (!SQLiteFileSystem::deleteDatabaseFile(databaseFilename))
- LOG_ERROR("Failed to delete database file %s\n", databaseFilename.utf8().data());
+ if (StorageTracker::tracker().isActive())
+ StorageTracker::tracker().deleteOrigin(m_databaseIdentifier);
+ else {
+ String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier);
+ if (!SQLiteFileSystem::deleteDatabaseFile(databaseFilename))
+ LOG_ERROR("Failed to delete database file %s\n", databaseFilename.utf8().data());
+ }
}
}
+void StorageAreaSync::scheduleSync()
+{
+ syncTimerFired(&m_syncTimer);
+}
+
} // namespace WebCore
#endif // ENABLE(DOM_STORAGE)
diff --git a/Source/WebCore/storage/StorageAreaSync.h b/Source/WebCore/storage/StorageAreaSync.h
index 90aa6a7..ebfb053 100644
--- a/Source/WebCore/storage/StorageAreaSync.h
+++ b/Source/WebCore/storage/StorageAreaSync.h
@@ -49,6 +49,9 @@ namespace WebCore {
void scheduleItemForSync(const String& key, const String& value);
void scheduleClear();
+ void scheduleCloseDatabase();
+
+ void scheduleSync();
private:
StorageAreaSync(PassRefPtr<StorageSyncManager>, PassRefPtr<StorageAreaImpl>, const String& databaseIdentifier);
@@ -92,6 +95,8 @@ namespace WebCore {
bool m_syncScheduled;
bool m_syncInProgress;
bool m_databaseOpenFailed;
+
+ bool m_syncCloseDatabase;
mutable Mutex m_importLock;
mutable ThreadCondition m_importCondition;
diff --git a/Source/WebCore/storage/StorageNamespace.h b/Source/WebCore/storage/StorageNamespace.h
index f7dad1e..f5604b0 100644
--- a/Source/WebCore/storage/StorageNamespace.h
+++ b/Source/WebCore/storage/StorageNamespace.h
@@ -50,10 +50,16 @@ public:
virtual PassRefPtr<StorageNamespace> copy() = 0;
virtual void close() = 0;
virtual void unlock() = 0;
+<<<<<<< HEAD
#ifdef ANDROID
virtual void clear(Page*) = 0;
#endif
+=======
+ virtual void clearOriginForDeletion(SecurityOrigin*) = 0;
+ virtual void clearAllOriginsForDeletion() = 0;
+ virtual void sync() = 0;
+>>>>>>> webkit.org at r82507
};
} // namespace WebCore
diff --git a/Source/WebCore/storage/StorageNamespaceImpl.cpp b/Source/WebCore/storage/StorageNamespaceImpl.cpp
index 68508a7..c6279ed 100644
--- a/Source/WebCore/storage/StorageNamespaceImpl.cpp
+++ b/Source/WebCore/storage/StorageNamespaceImpl.cpp
@@ -32,6 +32,7 @@
#include "StorageAreaImpl.h"
#include "StorageMap.h"
#include "StorageSyncManager.h"
+#include "StorageTracker.h"
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringHash.h>
@@ -167,6 +168,32 @@ void StorageNamespaceImpl::unlock()
// Because there's a single event loop per-process, this is a no-op.
}
+void StorageNamespaceImpl::clearOriginForDeletion(SecurityOrigin* origin)
+{
+ ASSERT(isMainThread());
+
+ RefPtr<StorageAreaImpl> storageArea = m_storageAreaMap.get(origin);
+ if (storageArea)
+ storageArea->clearForOriginDeletion();
+}
+
+void StorageNamespaceImpl::clearAllOriginsForDeletion()
+{
+ ASSERT(isMainThread());
+
+ StorageAreaMap::iterator end = m_storageAreaMap.end();
+ for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
+ it->second->clearForOriginDeletion();
+}
+
+void StorageNamespaceImpl::sync()
+{
+ ASSERT(isMainThread());
+ StorageAreaMap::iterator end = m_storageAreaMap.end();
+ for (StorageAreaMap::iterator it = m_storageAreaMap.begin(); it != end; ++it)
+ it->second->sync();
+}
+
} // namespace WebCore
#endif // ENABLE(DOM_STORAGE)
diff --git a/Source/WebCore/storage/StorageNamespaceImpl.h b/Source/WebCore/storage/StorageNamespaceImpl.h
index c2361fa..871f540 100644
--- a/Source/WebCore/storage/StorageNamespaceImpl.h
+++ b/Source/WebCore/storage/StorageNamespaceImpl.h
@@ -53,10 +53,21 @@ namespace WebCore {
virtual void close();
virtual void unlock();
+<<<<<<< HEAD
#ifdef ANDROID
virtual void clear(Page*);
#endif
+=======
+ // Not removing the origin's StorageArea from m_storageAreaMap because
+ // we're just deleting the underlying db file. If an item is added immediately
+ // after file deletion, we want the same StorageArea to eventually trigger
+ // a sync and for StorageAreaSync to recreate the backing db file.
+ virtual void clearOriginForDeletion(SecurityOrigin*);
+ virtual void clearAllOriginsForDeletion();
+ virtual void sync();
+
+>>>>>>> webkit.org at r82507
private:
StorageNamespaceImpl(StorageType, const String& path, unsigned quota);
diff --git a/Source/WebCore/storage/StorageTracker.cpp b/Source/WebCore/storage/StorageTracker.cpp
new file mode 100644
index 0000000..e18b4b8
--- /dev/null
+++ b/Source/WebCore/storage/StorageTracker.cpp
@@ -0,0 +1,539 @@
+/*
+ * Copyright (C) 2011 Apple 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 INC. 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 INC. 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 "StorageTracker.h"
+
+#if ENABLE(DOM_STORAGE)
+
+#include "DatabaseThread.h"
+#include "FileSystem.h"
+#include "LocalStorageTask.h"
+#include "LocalStorageThread.h"
+#include "Logging.h"
+#include "PageGroup.h"
+#include "SQLiteFileSystem.h"
+#include "SQLiteStatement.h"
+#include "SecurityOrigin.h"
+#include "StorageTrackerClient.h"
+#include "TextEncoding.h"
+#include <wtf/MainThread.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+static StorageTracker* storageTracker = 0;
+
+void StorageTracker::initializeTracker(const String& storagePath)
+{
+ ASSERT(isMainThread());
+ ASSERT(!storageTracker);
+
+ if (!storageTracker)
+ storageTracker = new StorageTracker(storagePath);
+
+ // Make sure text encoding maps have been built on the main thread, as the StorageTracker thread might try to do it there instead.
+ // FIXME (<rdar://problem/9127819>): Is there a more explicit way of doing this besides accessing the UTF8Encoding?
+ UTF8Encoding();
+
+ SQLiteFileSystem::registerSQLiteVFS();
+ storageTracker->setIsActive(true);
+ storageTracker->m_thread->start();
+ storageTracker->importOriginIdentifiers();
+}
+
+StorageTracker& StorageTracker::tracker()
+{
+ if (!storageTracker)
+ storageTracker = new StorageTracker("");
+
+ return *storageTracker;
+}
+
+StorageTracker::StorageTracker(const String& storagePath)
+ : m_client(0)
+ , m_thread(LocalStorageThread::create())
+ , m_isActive(false)
+{
+ setStorageDirectoryPath(storagePath);
+}
+
+void StorageTracker::setStorageDirectoryPath(const String& path)
+{
+ MutexLocker lockDatabase(m_databaseGuard);
+ ASSERT(!m_database.isOpen());
+
+ m_storageDirectoryPath = path.threadsafeCopy();
+}
+
+String StorageTracker::trackerDatabasePath()
+{
+ ASSERT(!m_databaseGuard.tryLock());
+ return SQLiteFileSystem::appendDatabaseFileNameToPath(m_storageDirectoryPath, "StorageTracker.db");
+}
+
+void StorageTracker::openTrackerDatabase(bool createIfDoesNotExist)
+{
+ ASSERT(m_isActive);
+ ASSERT(!isMainThread());
+ ASSERT(!m_databaseGuard.tryLock());
+
+ if (m_database.isOpen())
+ return;
+
+ String databasePath = trackerDatabasePath();
+
+ if (!SQLiteFileSystem::ensureDatabaseFileExists(databasePath, createIfDoesNotExist)) {
+ if (createIfDoesNotExist)
+ LOG_ERROR("Failed to create database file '%s'", databasePath.ascii().data());
+ return;
+ }
+
+ if (!m_database.open(databasePath)) {
+ LOG_ERROR("Failed to open databasePath %s.", databasePath.ascii().data());
+ return;
+ }
+
+ m_database.disableThreadingChecks();
+
+ if (!m_database.tableExists("Origins")) {
+ if (!m_database.executeCommand("CREATE TABLE Origins (origin TEXT UNIQUE ON CONFLICT REPLACE, path TEXT);"))
+ LOG_ERROR("Failed to create Origins table.");
+ }
+}
+
+void StorageTracker::importOriginIdentifiers()
+{
+ if (!m_isActive)
+ return;
+
+ ASSERT(isMainThread());
+ ASSERT(m_thread);
+
+ m_thread->scheduleTask(LocalStorageTask::createOriginIdentifiersImport());
+}
+
+void StorageTracker::syncImportOriginIdentifiers()
+{
+ ASSERT(m_isActive);
+
+ ASSERT(!isMainThread());
+
+ {
+ MutexLocker lockDatabase(m_databaseGuard);
+
+ // Don't force creation of StorageTracker's db just because a tracker
+ // was initialized. It will be created if local storage dbs are found
+ // by syncFileSystemAndTrackerDatabse() or the next time a local storage
+ // db is created by StorageAreaSync.
+ openTrackerDatabase(false);
+
+ if (m_database.isOpen()) {
+ SQLiteStatement statement(m_database, "SELECT origin FROM Origins");
+ if (statement.prepare() != SQLResultOk) {
+ LOG_ERROR("Failed to prepare statement.");
+ return;
+ }
+
+ int result;
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+ while ((result = statement.step()) == SQLResultRow)
+ m_originSet.add(statement.getColumnText(0).threadsafeCopy());
+ }
+
+ if (result != SQLResultDone) {
+ LOG_ERROR("Failed to read in all origins from the database.");
+ return;
+ }
+ }
+ }
+
+ syncFileSystemAndTrackerDatabase();
+
+ {
+ MutexLocker lockClient(m_clientGuard);
+ if (m_client) {
+ MutexLocker lockOrigins(m_originSetGuard);
+ OriginSet::const_iterator end = m_originSet.end();
+ for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it)
+ m_client->dispatchDidModifyOrigin(*it);
+ }
+ }
+}
+
+void StorageTracker::syncFileSystemAndTrackerDatabase()
+{
+ ASSERT(!isMainThread());
+ ASSERT(m_isActive);
+
+ m_databaseGuard.lock();
+ DEFINE_STATIC_LOCAL(const String, fileMatchPattern, ("*.localstorage"));
+ DEFINE_STATIC_LOCAL(const String, fileExt, (".localstorage"));
+ DEFINE_STATIC_LOCAL(const unsigned, fileExtLength, (fileExt.length()));
+ m_databaseGuard.unlock();
+
+ Vector<String> paths;
+ {
+ MutexLocker lock(m_databaseGuard);
+ paths = listDirectory(m_storageDirectoryPath, fileMatchPattern);
+ }
+
+ // Use a copy of m_originSet to find expired entries and to schedule their
+ // deletions from disk and from m_originSet.
+ OriginSet originSetCopy;
+ {
+ MutexLocker lock(m_originSetGuard);
+ OriginSet::const_iterator end = m_originSet.end();
+ for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it)
+ originSetCopy.add((*it).threadsafeCopy());
+ }
+
+ // Add missing StorageTracker records.
+ OriginSet foundOrigins;
+ Vector<String>::const_iterator end = paths.end();
+ for (Vector<String>::const_iterator it = paths.begin(); it != end; ++it) {
+ String path = *it;
+ if (path.endsWith(fileExt, true) && path.length() > fileExtLength) {
+ String file = pathGetFileName(path);
+ String originIdentifier = file.substring(0, file.length() - fileExtLength);
+ if (!originSetCopy.contains(originIdentifier))
+ syncSetOriginDetails(originIdentifier, path);
+
+ foundOrigins.add(originIdentifier);
+ }
+ }
+
+ // Delete stale StorageTracker records.
+ OriginSet::const_iterator setEnd = originSetCopy.end();
+ for (OriginSet::const_iterator it = originSetCopy.begin(); it != setEnd; ++it) {
+ if (!foundOrigins.contains(*it))
+ syncDeleteOrigin(*it);
+ }
+}
+
+void StorageTracker::setOriginDetails(const String& originIdentifier, const String& databaseFile)
+{
+ if (!m_isActive)
+ return;
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+
+ if (m_originSet.contains(originIdentifier))
+ return;
+
+ m_originSet.add(originIdentifier);
+ }
+
+ OwnPtr<LocalStorageTask> task = LocalStorageTask::createSetOriginDetails(originIdentifier.threadsafeCopy(), databaseFile);
+
+ if (isMainThread()) {
+ ASSERT(m_thread);
+ m_thread->scheduleTask(task.release());
+ } else
+ callOnMainThread(scheduleTask, reinterpret_cast<void*>(task.leakPtr()));
+}
+
+void StorageTracker::scheduleTask(void* taskIn)
+{
+ ASSERT(isMainThread());
+ ASSERT(StorageTracker::tracker().m_thread);
+
+ OwnPtr<LocalStorageTask> task = adoptPtr(reinterpret_cast<LocalStorageTask*>(taskIn));
+
+ StorageTracker::tracker().m_thread->scheduleTask(task.release());
+}
+
+void StorageTracker::syncSetOriginDetails(const String& originIdentifier, const String& databaseFile)
+{
+ ASSERT(!isMainThread());
+
+ MutexLocker lockDatabase(m_databaseGuard);
+
+ openTrackerDatabase(true);
+
+ if (!m_database.isOpen())
+ return;
+
+ SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)");
+ if (statement.prepare() != SQLResultOk) {
+ LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.ascii().data());
+ return;
+ }
+
+ statement.bindText(1, originIdentifier);
+ statement.bindText(2, databaseFile);
+
+ if (statement.step() != SQLResultDone)
+ LOG_ERROR("Unable to establish origin '%s' in the tracker", originIdentifier.ascii().data());
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+ if (!m_originSet.contains(originIdentifier))
+ m_originSet.add(originIdentifier);
+ }
+
+ {
+ MutexLocker lockClient(m_clientGuard);
+ if (m_client)
+ m_client->dispatchDidModifyOrigin(originIdentifier);
+ }
+}
+
+void StorageTracker::origins(Vector<RefPtr<SecurityOrigin> >& result)
+{
+ ASSERT(m_isActive);
+
+ if (!m_isActive)
+ return;
+
+ MutexLocker lockOrigins(m_originSetGuard);
+
+ OriginSet::const_iterator end = m_originSet.end();
+ for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it)
+ result.append(SecurityOrigin::createFromDatabaseIdentifier(*it));
+}
+
+void StorageTracker::deleteAllOrigins()
+{
+ ASSERT(m_isActive);
+ ASSERT(isMainThread());
+ ASSERT(m_thread);
+
+ if (!m_isActive)
+ return;
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+ willDeleteAllOrigins();
+ m_originSet.clear();
+ }
+
+ PageGroup::clearLocalStorageForAllOrigins();
+
+ m_thread->scheduleTask(LocalStorageTask::createDeleteAllOrigins());
+}
+
+void StorageTracker::syncDeleteAllOrigins()
+{
+ ASSERT(!isMainThread());
+
+ MutexLocker lockDatabase(m_databaseGuard);
+
+ openTrackerDatabase(false);
+ if (!m_database.isOpen())
+ return;
+
+ SQLiteStatement statement(m_database, "SELECT origin, path FROM Origins");
+ if (statement.prepare() != SQLResultOk) {
+ LOG_ERROR("Failed to prepare statement.");
+ return;
+ }
+
+ int result;
+ while ((result = statement.step()) == SQLResultRow) {
+ if (!canDeleteOrigin(statement.getColumnText(0)))
+ continue;
+
+ SQLiteFileSystem::deleteDatabaseFile(statement.getColumnText(1));
+
+ {
+ MutexLocker lockClient(m_clientGuard);
+ if (m_client)
+ m_client->dispatchDidModifyOrigin(statement.getColumnText(0));
+ }
+ }
+
+ if (result != SQLResultDone)
+ LOG_ERROR("Failed to read in all origins from the database.");
+
+ if (m_database.isOpen())
+ m_database.close();
+
+ SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
+ SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_storageDirectoryPath);
+}
+
+void StorageTracker::deleteOrigin(const String& originIdentifier)
+{
+ deleteOrigin(SecurityOrigin::createFromDatabaseIdentifier(originIdentifier).get());
+}
+
+void StorageTracker::deleteOrigin(SecurityOrigin* origin)
+{
+ ASSERT(m_isActive);
+ ASSERT(isMainThread());
+ ASSERT(m_thread);
+
+ if (!m_isActive)
+ return;
+
+ // Before deleting database, we need to clear in-memory local storage data
+ // in StorageArea, and to close the StorageArea db. It's possible for an
+ // item to be added immediately after closing the db and cause StorageAreaSync
+ // to reopen the db before the db is deleted by a StorageTracker thread.
+ // In this case, reopening the db in StorageAreaSync will cancel a pending
+ // StorageTracker db deletion.
+ PageGroup::clearLocalStorageForOrigin(origin);
+
+ String originId = origin->databaseIdentifier();
+
+ {
+ MutexLocker lockOrigins(m_originSetGuard);
+ willDeleteOrigin(originId);
+ m_originSet.remove(originId);
+ }
+
+ m_thread->scheduleTask(LocalStorageTask::createDeleteOrigin(originId));
+}
+
+void StorageTracker::syncDeleteOrigin(const String& originIdentifier)
+{
+ ASSERT(!isMainThread());
+
+ MutexLocker lockDatabase(m_databaseGuard);
+
+ if (!canDeleteOrigin(originIdentifier)) {
+ LOG_ERROR("Attempted to delete origin '%s' while it was being created\n", originIdentifier.ascii().data());
+ return;
+ }
+
+ openTrackerDatabase(false);
+ if (!m_database.isOpen())
+ return;
+
+ // Get origin's db file path, delete entry in tracker's db, then delete db file.
+ SQLiteStatement pathStatement(m_database, "SELECT path FROM Origins WHERE origin=?");
+ if (pathStatement.prepare() != SQLResultOk) {
+ LOG_ERROR("Unable to prepare selection of path for origin '%s'", originIdentifier.ascii().data());
+ return;
+ }
+ pathStatement.bindText(1, originIdentifier);
+ int result = pathStatement.step();
+ if (result != SQLResultRow) {
+ LOG_ERROR("Unable to find origin '%s' in Origins table", originIdentifier.ascii().data());
+ return;
+ }
+
+ String path = pathStatement.getColumnText(0);
+
+ ASSERT(!path.isEmpty());
+
+ SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins where origin=?");
+ if (deleteStatement.prepare() != SQLResultOk) {
+ LOG_ERROR("Unable to prepare deletion of origin '%s'", originIdentifier.ascii().data());
+ return;
+ }
+ deleteStatement.bindText(1, originIdentifier);
+ if (!deleteStatement.executeCommand()) {
+ LOG_ERROR("Unable to execute deletion of origin '%s'", originIdentifier.ascii().data());
+ return;
+ }
+
+ SQLiteFileSystem::deleteDatabaseFile(path);
+
+ bool shouldDeleteTrackerFiles = false;
+ {
+ MutexLocker originLock(m_originSetGuard);
+ m_originSet.remove(originIdentifier);
+ shouldDeleteTrackerFiles = m_originSet.isEmpty();
+ }
+
+ if (shouldDeleteTrackerFiles) {
+ m_database.close();
+ SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath());
+ SQLiteFileSystem::deleteEmptyDatabaseDirectory(m_storageDirectoryPath);
+ }
+
+ {
+ MutexLocker lockClient(m_clientGuard);
+ if (m_client)
+ m_client->dispatchDidModifyOrigin(originIdentifier);
+ }
+}
+
+void StorageTracker::willDeleteAllOrigins()
+{
+ ASSERT(!m_originSetGuard.tryLock());
+
+ OriginSet::const_iterator end = m_originSet.end();
+ for (OriginSet::const_iterator it = m_originSet.begin(); it != end; ++it)
+ m_originsBeingDeleted.add((*it).threadsafeCopy());
+}
+
+void StorageTracker::willDeleteOrigin(const String& originIdentifier)
+{
+ ASSERT(isMainThread());
+ ASSERT(!m_originSetGuard.tryLock());
+
+ m_originsBeingDeleted.add(originIdentifier);
+}
+
+bool StorageTracker::canDeleteOrigin(const String& originIdentifier)
+{
+ ASSERT(!m_databaseGuard.tryLock());
+ MutexLocker lockOrigins(m_originSetGuard);
+ return m_originsBeingDeleted.contains(originIdentifier);
+}
+
+void StorageTracker::cancelDeletingOrigin(const String& originIdentifier)
+{
+ if (!m_isActive)
+ return;
+
+ MutexLocker lockDatabase(m_databaseGuard);
+ MutexLocker lockOrigins(m_originSetGuard);
+ if (!m_originsBeingDeleted.isEmpty())
+ m_originsBeingDeleted.remove(originIdentifier);
+}
+
+void StorageTracker::setClient(StorageTrackerClient* client)
+{
+ MutexLocker lockClient(m_clientGuard);
+ m_client = client;
+}
+
+void StorageTracker::syncLocalStorage()
+{
+ PageGroup::syncLocalStorage();
+}
+
+bool StorageTracker::isActive()
+{
+ return m_isActive;
+}
+
+void StorageTracker::setIsActive(bool flag)
+{
+ m_isActive = flag;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(DOM_STORAGE)
diff --git a/Source/WebCore/storage/StorageTracker.h b/Source/WebCore/storage/StorageTracker.h
new file mode 100644
index 0000000..04a821b
--- /dev/null
+++ b/Source/WebCore/storage/StorageTracker.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 Apple 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 INC. 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 INC. 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 StorageTracker_h
+#define StorageTracker_h
+
+#if ENABLE(DOM_STORAGE)
+
+#include "PlatformString.h"
+#include "SQLiteDatabase.h"
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+class LocalStorageTask;
+class LocalStorageThread;
+class SecurityOrigin;
+class StorageTrackerClient;
+
+class StorageTracker {
+ WTF_MAKE_NONCOPYABLE(StorageTracker);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ static void initializeTracker(const String& storagePath);
+ static StorageTracker& tracker();
+ static void scheduleTask(void*);
+
+ void importOriginIdentifiers();
+ void setOriginDetails(const String& originIdentifier, const String& databaseFile);
+
+ void deleteAllOrigins();
+ void deleteOrigin(SecurityOrigin*);
+ void deleteOrigin(const String& originIdentifier);
+ void origins(Vector<RefPtr<SecurityOrigin> >& result);
+
+ void cancelDeletingOrigin(const String& originIdentifier);
+
+ void setClient(StorageTrackerClient*);
+
+ bool isActive();
+
+ // Sync to disk on background thread.
+ void syncDeleteAllOrigins();
+ void syncDeleteOrigin(const String& originIdentifier);
+ void syncSetOriginDetails(const String& originIdentifier, const String& databaseFile);
+ void syncImportOriginIdentifiers();
+ void syncFileSystemAndTrackerDatabase();
+
+ void syncLocalStorage();
+
+private:
+ StorageTracker(const String& storagePath);
+
+ String trackerDatabasePath();
+ void openTrackerDatabase(bool createIfDoesNotExist);
+
+ void setStorageDirectoryPath(const String&);
+
+ void deleteTrackerFiles();
+
+ bool canDeleteOrigin(const String& originIdentifier);
+ void willDeleteOrigin(const String& originIdentifier);
+ void willDeleteAllOrigins();
+
+ void originFilePaths(Vector<String>& paths);
+
+ void setIsActive(bool);
+
+ // Guard for m_database, m_storageDirectoryPath and static Strings in syncFileSystemAndTrackerDatabase().
+ Mutex m_databaseGuard;
+ SQLiteDatabase m_database;
+ String m_storageDirectoryPath;
+
+ Mutex m_clientGuard;
+ StorageTrackerClient* m_client;
+
+ // Guard for m_originSet and m_originsBeingDeleted.
+ Mutex m_originSetGuard;
+ typedef HashSet<String> OriginSet;
+ OriginSet m_originSet;
+ OriginSet m_originsBeingDeleted;
+
+ OwnPtr<LocalStorageThread> m_thread;
+
+ bool m_isActive;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(DOM_STORAGE)
+
+#endif // StorageTracker_h
diff --git a/Source/WebCore/storage/StorageTrackerClient.h b/Source/WebCore/storage/StorageTrackerClient.h
new file mode 100644
index 0000000..9c2d53e
--- /dev/null
+++ b/Source/WebCore/storage/StorageTrackerClient.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 Apple 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 INC. 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 INC. 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 StorageTrackerClient_h
+#define StorageTrackerClient_h
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class StorageTrackerClient {
+public:
+ virtual ~StorageTrackerClient() { }
+ virtual void dispatchDidModifyOrigin(const String& originIdentifier) = 0;
+};
+
+} // namespace WebCore
+
+#endif // StorageTrackerClient_h