Diff
Modified: trunk/Source/WebCore/ChangeLog (124674 => 124675)
--- trunk/Source/WebCore/ChangeLog 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/ChangeLog 2012-08-04 00:28:25 UTC (rev 124675)
@@ -1,3 +1,98 @@
+2012-08-03 David Grogan <[email protected]>
+
+ IndexedDB: Core upgradeneeded logic
+ https://bugs.webkit.org/show_bug.cgi?id=92558
+
+ Reviewed by Ojan Vafai.
+
+ This is the backend webkit logic needed for integer versions. The rest
+ is in https://bugs.webkit.org/show_bug.cgi?id=89505.
+
+ I tried to make use of the existing processPendingCalls and added two
+ more queues, pendingOpenWithVersionCalls and
+ pendingSecondHalfOpenWithVersionCalls. The "second half" refers to
+ how there are two events that need to be fired in response to an
+ open-with-version call. The "second half" queue holds the open
+ requests that should immediately follow the caller's upgradeneeded
+ handler.
+
+ No new tests, there are so many they are in their own patch:
+ https://bugs.webkit.org/show_bug.cgi?id=92560
+
+ Though this patch doesn't change any expected behavior anyway, lack of
+ regressions is what we're hoping for here.
+
+ * Modules/indexeddb/IDBBackingStore.h:
+ (IDBBackingStore):
+ * Modules/indexeddb/IDBCallbacks.h:
+ (WebCore::IDBCallbacks::onBlocked):
+ (WebCore::IDBCallbacks::onUpgradeNeeded):
+ * Modules/indexeddb/IDBDatabaseBackendImpl.cpp:
+ (IDBDatabaseBackendImpl::PendingOpenCall):
+ (IDBDatabaseBackendImpl::PendingOpenWithVersionCall):
+ (WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::create):
+ (WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::callbacks):
+ (WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::version):
+ (WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::PendingOpenWithVersionCall):
+ (WebCore):
+ (WebCore::IDBDatabaseBackendImpl::IDBDatabaseBackendImpl):
+ (WebCore::IDBDatabaseBackendImpl::openInternal):
+ (WebCore::IDBDatabaseBackendImpl::metadata):
+ (WebCore::IDBDatabaseBackendImpl::setVersion):
+ (WebCore::IDBDatabaseBackendImpl::setIntVersionInternal):
+ (WebCore::IDBDatabaseBackendImpl::transactionFinished):
+ (WebCore::IDBDatabaseBackendImpl::transactionFinishedAndEventsFired):
+ When an upgradeneeded event is fired in response to an
+ open-with-version call, the version change transaction must receive its
+ complete event before processPendingCalls fires a success event at
+ IDBOpenDBRequest. In the future this should probably be changed
+ instead to transactionFinishedAndAbortFired and
+ transactionFinishedAndCompleteFired so that we'll know to fire a
+ success or error event at IDBOpenDBRequest. Currently, instead of
+ firing error when there's an abort, we don't fire anything.
+
+ (WebCore::IDBDatabaseBackendImpl::processPendingCalls):
+ Now that this is called after a connection is opened, we unfortunately
+ lose the invariant that there is only one existing connection when this
+ is called, but nothing inside this function actually relied on that.
+ Additionally, the secondHalfOpen calls only ever need to be serviced
+ in one place: right after a version change transaction completes, so
+ it could be moved out of here.
+
+ (WebCore::IDBDatabaseBackendImpl::registerFrontendCallbacks):
+ Now that setVersion and deleteDatabase calls are queued up behind
+ secondHalfOpen calls, we have to service those queues when
+ secondHalfOpen calls complete, which is here. So call
+ processPendingCalls().
+
+ (WebCore::IDBDatabaseBackendImpl::runIntVersionChangeTransaction):
+ (WebCore::IDBDatabaseBackendImpl::openConnectionWithVersion):
+ (WebCore::IDBDatabaseBackendImpl::deleteDatabase):
+ (WebCore::IDBDatabaseBackendImpl::close):
+ * Modules/indexeddb/IDBDatabaseBackendImpl.h:
+ (IDBDatabaseBackendImpl):
+ * Modules/indexeddb/IDBDatabaseCallbacks.h:
+ (WebCore::IDBDatabaseCallbacks::onVersionChange):
+ * Modules/indexeddb/IDBFactoryBackendImpl.cpp:
+ (WebCore::IDBFactoryBackendImpl::open):
+ This is refactored some so that the call to openConection{WithVersion}
+ happens once, at the end.
+
+ * Modules/indexeddb/IDBLevelDBBackingStore.cpp:
+ (WebCore::IDBLevelDBBackingStore::getIDBDatabaseMetaData):
+ (WebCore::IDBLevelDBBackingStore::createIDBDatabaseMetaData):
+ (WebCore::IDBLevelDBBackingStore::updateIDBDatabaseIntVersion):
+ (WebCore):
+ (WebCore::IDBLevelDBBackingStore::deleteDatabase):
+ * Modules/indexeddb/IDBLevelDBBackingStore.h:
+ (IDBLevelDBBackingStore):
+ * Modules/indexeddb/IDBTransactionBackendImpl.cpp:
+ (WebCore::IDBTransactionBackendImpl::commit):
+ See above comments about transactionFinishedAndEventsFired. I tried
+ moving the call to transactionFinished after the events were fired but
+ that failed some asserts. But changing those asserts is still an
+ alternative to splitting up transactionFinished as is done here.
+
2012-08-03 Rick Byers <[email protected]>
Double tap gesture should send dblclick event
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.h (124674 => 124675)
--- trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.h 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.h 2012-08-04 00:28:25 UTC (rev 124675)
@@ -47,8 +47,9 @@
virtual ~IDBBackingStore() {};
virtual void getDatabaseNames(Vector<String>& foundNames) = 0;
- virtual bool getIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId) = 0;
- virtual bool createIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId) = 0;
+ virtual bool getIDBDatabaseMetaData(const String& name, String& foundStringVersion, int64_t& foundIntVersion, int64_t& foundId) = 0;
+ virtual bool createIDBDatabaseMetaData(const String& name, const String& stringVersion, int64_t intVersion, int64_t& rowId) = 0;
+ virtual bool updateIDBDatabaseIntVersion(int64_t rowId, int64_t intVersion) = 0;
virtual bool updateIDBDatabaseMetaData(int64_t rowId, const String& version) = 0;
virtual bool deleteDatabase(const String& name) = 0;
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCallbacks.h (124674 => 124675)
--- trunk/Source/WebCore/Modules/indexeddb/IDBCallbacks.h 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCallbacks.h 2012-08-04 00:28:25 UTC (rev 124675)
@@ -30,9 +30,11 @@
#define IDBCallbacks_h
#include "DOMStringList.h"
+#include "IDBDatabaseBackendInterface.h"
#include "IDBDatabaseError.h"
#include "IDBKey.h"
#include "IDBKeyPath.h"
+#include "IDBTransactionBackendInterface.h"
#include "SerializedScriptValue.h"
#include <wtf/Threading.h>
@@ -40,9 +42,7 @@
namespace WebCore {
class IDBCursorBackendInterface;
-class IDBDatabaseBackendInterface;
class IDBObjectStoreBackendInterface;
-class IDBTransactionBackendInterface;
// FIXME: All child classes need to be made threadsafe.
class IDBCallbacks : public ThreadSafeRefCounted<IDBCallbacks> {
@@ -59,7 +59,9 @@
virtual void onSuccess(PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, const IDBKeyPath&) = 0;
virtual void onSuccessWithContinuation() = 0;
virtual void onSuccessWithPrefetch(const Vector<RefPtr<IDBKey> >& keys, const Vector<RefPtr<IDBKey> >& primaryKeys, const Vector<RefPtr<SerializedScriptValue> >& values) = 0;
- virtual void onBlocked() = 0;
+ virtual void onBlocked() { ASSERT_NOT_REACHED(); }
+ virtual void onBlocked(int64_t existingVersion) { ASSERT_NOT_REACHED(); }
+ virtual void onUpgradeNeeded(int64_t oldVersion, PassRefPtr<IDBTransactionBackendInterface>, PassRefPtr<IDBDatabaseBackendInterface>) { ASSERT_NOT_REACHED(); }
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp (124674 => 124675)
--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp 2012-08-04 00:28:25 UTC (rev 124675)
@@ -52,9 +52,29 @@
: m_callbacks(callbacks)
{
}
+
RefPtr<IDBCallbacks> m_callbacks;
};
+class IDBDatabaseBackendImpl::PendingOpenWithVersionCall : public RefCounted<PendingOpenWithVersionCall> {
+public:
+ static PassRefPtr<PendingOpenWithVersionCall> create(PassRefPtr<IDBCallbacks> callbacks, int64_t version)
+ {
+ return adoptRef(new PendingOpenWithVersionCall(callbacks, version));
+ }
+ PassRefPtr<IDBCallbacks> callbacks() { return m_callbacks; }
+ int64_t version() { return m_version; }
+
+private:
+ PendingOpenWithVersionCall(PassRefPtr<IDBCallbacks> callbacks, int64_t version)
+ : m_callbacks(callbacks)
+ , m_version(version)
+ {
+ }
+ RefPtr<IDBCallbacks> m_callbacks;
+ int64_t m_version;
+};
+
class IDBDatabaseBackendImpl::PendingDeleteCall : public RefCounted<PendingDeleteCall> {
public:
static PassRefPtr<PendingDeleteCall> create(PassRefPtr<IDBCallbacks> callbacks)
@@ -106,6 +126,7 @@
, m_id(InvalidId)
, m_name(name)
, m_version("")
+ , m_intVersion(IDBDatabaseMetadata::NoIntVersion)
, m_identifier(uniqueIdentifier)
, m_factory(factory)
, m_transactionCoordinator(coordinator)
@@ -116,13 +137,13 @@
bool IDBDatabaseBackendImpl::openInternal()
{
- bool success = m_backingStore->getIDBDatabaseMetaData(m_name, m_version, m_id);
- ASSERT(success == (m_id != InvalidId));
+ bool success = m_backingStore->getIDBDatabaseMetaData(m_name, m_version, m_intVersion, m_id);
+ ASSERT_WITH_MESSAGE(success == (m_id != InvalidId), "success = %s, m_id = %lld", success ? "true" : "false", static_cast<long long>(m_id));
if (success) {
loadObjectStores();
return true;
}
- return m_backingStore->createIDBDatabaseMetaData(m_name, m_version, m_id);
+ return m_backingStore->createIDBDatabaseMetaData(m_name, m_version, m_intVersion, m_id);
}
IDBDatabaseBackendImpl::~IDBDatabaseBackendImpl()
@@ -136,7 +157,7 @@
IDBDatabaseMetadata IDBDatabaseBackendImpl::metadata() const
{
- IDBDatabaseMetadata metadata(m_name, m_version, IDBDatabaseMetadata::NoIntVersion);
+ IDBDatabaseMetadata metadata(m_name, m_version, m_intVersion);
for (ObjectStoreMap::const_iterator it = m_objectStores.begin(); it != m_objectStores.end(); ++it)
metadata.objectStores.set(it->first, it->second->metadata());
return metadata;
@@ -214,6 +235,10 @@
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::IDB_ABORT_ERR, "Connection was closed before set version transaction was created"));
return;
}
+ if (m_intVersion != IDBDatabaseMetadata::NoIntVersion) {
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, String::format("You can't use the setVersion function if you've already set the version through an open call. The current integer version is %lld", static_cast<long long>(m_intVersion))));
+ return;
+ }
for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it) {
if (*it != databaseCallbacks)
(*it)->onVersionChange(version);
@@ -259,6 +284,20 @@
callbacks->onSuccess(PassRefPtr<IDBTransactionBackendInterface>(transaction));
}
+void IDBDatabaseBackendImpl::setIntVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, int64_t version, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
+{
+ int64_t databaseId = database->id();
+ int64_t oldVersion = database->m_intVersion;
+ ASSERT(version > oldVersion);
+ database->m_intVersion = version;
+ if (!database->m_backingStore->updateIDBDatabaseIntVersion(databaseId, database->m_intVersion)) {
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
+ transaction->abort();
+ return;
+ }
+ callbacks->onUpgradeNeeded(oldVersion, transaction, database);
+}
+
void IDBDatabaseBackendImpl::transactionStarted(PassRefPtr<IDBTransactionBackendImpl> prpTransaction)
{
RefPtr<IDBTransactionBackendImpl> transaction = prpTransaction;
@@ -276,6 +315,16 @@
if (transaction->mode() == IDBTransaction::VERSION_CHANGE) {
ASSERT(transaction.get() == m_runningVersionChangeTransaction.get());
m_runningVersionChangeTransaction.clear();
+ }
+}
+
+void IDBDatabaseBackendImpl::transactionFinishedAndEventsFired(PassRefPtr<IDBTransactionBackendImpl> prpTransaction)
+{
+ RefPtr<IDBTransactionBackendImpl> transaction = prpTransaction;
+ if (transaction->mode() == IDBTransaction::VERSION_CHANGE) {
+ // If this was an open-with-version call, there will be a "second
+ // half" open call waiting for us in processPendingCalls.
+ // FIXME: When we no longer support setVersion, assert such a thing.
processPendingCalls();
}
}
@@ -287,7 +336,16 @@
void IDBDatabaseBackendImpl::processPendingCalls()
{
- ASSERT(connectionCount() <= 1);
+ // FIXME: Change from queue to just a single place holder.
+ ASSERT(m_pendingSecondHalfOpenWithVersionCalls.size() <= 1);
+ while (!m_pendingSecondHalfOpenWithVersionCalls.isEmpty()) {
+ RefPtr<PendingOpenWithVersionCall> pendingOpenWithVersionCall = m_pendingSecondHalfOpenWithVersionCalls.takeFirst();
+ ASSERT(pendingOpenWithVersionCall->version() == m_intVersion);
+ ASSERT(m_id != InvalidId);
+ ++m_pendingConnectionCount;
+ pendingOpenWithVersionCall->callbacks()->onSuccess(this);
+ return;
+ }
// Pending calls may be requeued or aborted
Deque<RefPtr<PendingSetVersionCall> > pendingSetVersionCalls;
@@ -325,6 +383,13 @@
if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty() || !m_pendingDeleteCalls.isEmpty())
return;
+ Deque<RefPtr<PendingOpenWithVersionCall> > pendingOpenWithVersionCalls;
+ m_pendingOpenWithVersionCalls.swap(pendingOpenWithVersionCalls);
+ while (!pendingOpenWithVersionCalls.isEmpty()) {
+ RefPtr<PendingOpenWithVersionCall> pendingOpenWithVersionCall = pendingOpenWithVersionCalls.takeFirst();
+ openConnectionWithVersion(pendingOpenWithVersionCall->callbacks(), pendingOpenWithVersionCall->version());
+ }
+
// Given the check above, it appears that calls cannot be requeued by
// openConnection, but use a different queue for iteration to be safe.
Deque<RefPtr<PendingOpenCall> > pendingOpenCalls;
@@ -356,6 +421,10 @@
ASSERT(m_pendingConnectionCount);
--m_pendingConnectionCount;
m_databaseCallbacksSet.add(RefPtr<IDBDatabaseCallbacks>(callbacks));
+ // We give max priority to open calls that follow upgradeneeded
+ // events; trigger the rest of the queues to be serviced when those open
+ // calls are finished.
+ processPendingCalls();
}
void IDBDatabaseBackendImpl::openConnection(PassRefPtr<IDBCallbacks> callbacks)
@@ -373,6 +442,80 @@
}
}
+void IDBDatabaseBackendImpl::runIntVersionChangeTransaction(int64_t requestedVersion, PassRefPtr<IDBCallbacks> prpCallbacks)
+{
+ // FIXME: This function won't be reached until it's exposed to script in
+ // wbk.ug/92897.
+ ASSERT_NOT_REACHED();
+
+ RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+ ASSERT(callbacks);
+ for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it) {
+ // Note that some connections might close in the versionchange event
+ // handler for some other connection, after which its own versionchange
+ // event should not be fired. The backend doesn't worry about this, we
+ // just queue up a version change event for every connection. The
+ // frontend takes care to only dispatch to open connections.
+ (*it)->onVersionChange(m_intVersion, requestedVersion);
+ }
+ // The spec dictates we wait until all the version change events are
+ // delivered and then check m_databaseCallbacks.empty() before proceeding
+ // or firing a blocked event, but instead we should be consistent with how
+ // the old setVersion (incorrectly) did it.
+ // FIXME: Remove the call to onBlocked and instead wait until the frontend
+ // tells us that all the blocked events have been delivered. See
+ // https://bugs.webkit.org/show_bug.cgi?id=71130
+ if (connectionCount() > 0)
+ callbacks->onBlocked(m_intVersion);
+ // FIXME: Add test for m_runningVersionChangeTransaction.
+ if (m_runningVersionChangeTransaction || connectionCount() > 0) {
+ m_pendingOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, requestedVersion));
+ return;
+ }
+
+ RefPtr<DOMStringList> objectStoreNames = DOMStringList::create();
+ ExceptionCode ec = 0;
+ RefPtr<IDBTransactionBackendInterface> transactionInterface = transaction(objectStoreNames.get(), IDBTransaction::VERSION_CHANGE, ec);
+ RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionInterface.get());
+ ASSERT(!ec);
+
+ RefPtr<IDBDatabaseBackendImpl> database = this;
+ OwnPtr<ScriptExecutionContext::Task> intVersionTask = createCallbackTask(&IDBDatabaseBackendImpl::setIntVersionInternal, database, requestedVersion, callbacks, transaction);
+ // FIXME: Make this reset the integer version as well.
+ OwnPtr<ScriptExecutionContext::Task> resetVersionOnAbortTask = createCallbackTask(&IDBDatabaseBackendImpl::resetVersion, database, m_version);
+ if (!transaction->scheduleTask(intVersionTask.release(), resetVersionOnAbortTask.release()))
+ ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
+ m_pendingSecondHalfOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, requestedVersion));
+}
+
+void IDBDatabaseBackendImpl::openConnectionWithVersion(PassRefPtr<IDBCallbacks> prpCallbacks, int64_t version)
+{
+ RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+ if (!m_pendingDeleteCalls.isEmpty() || m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty()) {
+ m_pendingOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, version));
+ return;
+ }
+ if (m_id == InvalidId) {
+ if (openInternal())
+ ASSERT(m_intVersion == IDBDatabaseMetadata::NoIntVersion);
+ else {
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
+ return;
+ }
+ }
+ if (version > m_intVersion) {
+ runIntVersionChangeTransaction(version, callbacks);
+ return;
+ }
+ if (version < m_intVersion) {
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::VER_ERR, String::format("The requested version (%lld) is less than the existing version (%lld).", static_cast<long long>(version), static_cast<long long>(m_intVersion))));
+ return;
+ }
+ ASSERT(version == m_intVersion);
+ ++m_pendingConnectionCount;
+ callbacks->onSuccess(this);
+}
+
void IDBDatabaseBackendImpl::deleteDatabase(PassRefPtr<IDBCallbacks> prpCallbacks)
{
if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty()) {
@@ -388,17 +531,19 @@
// FIXME: Only fire onBlocked if there are open connections after the
// VersionChangeEvents are received, not just set up to fire.
// https://bugs.webkit.org/show_bug.cgi?id=71130
- if (!m_databaseCallbacksSet.isEmpty()) {
+ if (connectionCount() >= 1) {
m_pendingDeleteCalls.append(PendingDeleteCall::create(callbacks));
callbacks->onBlocked();
return;
}
+ ASSERT(m_backingStore);
if (!m_backingStore->deleteDatabase(m_name)) {
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
return;
}
m_version = "";
m_id = InvalidId;
+ m_intVersion = IDBDatabaseMetadata::NoIntVersion;
m_objectStores.clear();
callbacks->onSuccess(SerializedScriptValue::nullValue());
}
@@ -411,12 +556,17 @@
if (connectionCount() > 1)
return;
+ TransactionSet transactions(m_transactions);
processPendingCalls();
- if (!connectionCount()) {
- TransactionSet transactions(m_transactions);
+ ASSERT(m_transactions.size() - transactions.size() <= 1);
+ // FIXME: Instead of relying on transactions.size(), make connectionCount
+ // aware of in-flight upgradeneeded events as well as in-flight success
+ // events.
+ if (!connectionCount() && !m_pendingDeleteCalls.size() && m_transactions.size() == transactions.size()) {
for (TransactionSet::const_iterator it = transactions.begin(); it != transactions.end(); ++it)
(*it)->abort();
+
ASSERT(m_transactions.isEmpty());
m_backingStore.clear();
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.h (124674 => 124675)
--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.h 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.h 2012-08-04 00:28:25 UTC (rev 124675)
@@ -57,6 +57,7 @@
void registerFrontendCallbacks(PassRefPtr<IDBDatabaseCallbacks>);
void openConnection(PassRefPtr<IDBCallbacks>);
+ void openConnectionWithVersion(PassRefPtr<IDBCallbacks>, int64_t version);
void deleteDatabase(PassRefPtr<IDBCallbacks>);
// IDBDatabaseBackendInterface
@@ -71,11 +72,13 @@
IDBTransactionCoordinator* transactionCoordinator() const { return m_transactionCoordinator.get(); }
void transactionStarted(PassRefPtr<IDBTransactionBackendImpl>);
void transactionFinished(PassRefPtr<IDBTransactionBackendImpl>);
+ void transactionFinishedAndEventsFired(PassRefPtr<IDBTransactionBackendImpl>);
private:
IDBDatabaseBackendImpl(const String& name, IDBBackingStore* database, IDBTransactionCoordinator*, IDBFactoryBackendImpl*, const String& uniqueIdentifier);
bool openInternal();
+ void runIntVersionChangeTransaction(int64_t requestedVersion, PassRefPtr<IDBCallbacks>);
void loadObjectStores();
int32_t connectionCount();
void processPendingCalls();
@@ -83,6 +86,7 @@
static void createObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBTransactionBackendImpl>);
static void deleteObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBTransactionBackendImpl>);
static void setVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, const String& version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendImpl>);
+ static void setIntVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, int64_t version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>);
// These are used as setVersion transaction abort tasks.
static void removeObjectStoreFromMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>);
@@ -93,6 +97,7 @@
int64_t m_id;
String m_name;
String m_version;
+ int64_t m_intVersion;
String m_identifier;
// This might not need to be a RefPtr since the factory's lifetime is that of the page group, but it's better to be conservitive than sorry.
@@ -113,6 +118,10 @@
class PendingOpenCall;
Deque<RefPtr<PendingOpenCall> > m_pendingOpenCalls;
+ class PendingOpenWithVersionCall;
+ Deque<RefPtr<PendingOpenWithVersionCall> > m_pendingOpenWithVersionCalls;
+ Deque<RefPtr<PendingOpenWithVersionCall> > m_pendingSecondHalfOpenWithVersionCalls;
+
class PendingDeleteCall;
Deque<RefPtr<PendingDeleteCall> > m_pendingDeleteCalls;
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseCallbacks.h (124674 => 124675)
--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseCallbacks.h 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseCallbacks.h 2012-08-04 00:28:25 UTC (rev 124675)
@@ -38,6 +38,7 @@
virtual ~IDBDatabaseCallbacks() { }
virtual void onVersionChange(const String& version) = 0;
+ virtual void onVersionChange(int64_t currentVersion, int64_t requestedVersion) { ASSERT_NOT_REACHED(); }
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBFactoryBackendImpl.cpp (124674 => 124675)
--- trunk/Source/WebCore/Modules/indexeddb/IDBFactoryBackendImpl.cpp 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBFactoryBackendImpl.cpp 2012-08-04 00:28:25 UTC (rev 124675)
@@ -35,6 +35,7 @@
#include "IDBDatabaseException.h"
#include "IDBLevelDBBackingStore.h"
#include "IDBTransactionCoordinator.h"
+#include "SecurityOrigin.h"
#include <wtf/Threading.h>
#include <wtf/UnusedParam.h>
@@ -151,30 +152,34 @@
void IDBFactoryBackendImpl::open(const String& name, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> prpSecurityOrigin, ScriptExecutionContext*, const String& dataDirectory)
{
+ // FIXME: Make this a parameter and plumb through from _javascript_.
+ int64_t version = IDBDatabaseMetadata::NoIntVersion;
RefPtr<SecurityOrigin> securityOrigin = prpSecurityOrigin;
const String uniqueIdentifier = computeUniqueIdentifier(name, securityOrigin.get());
+ RefPtr<IDBDatabaseBackendImpl> databaseBackend;
IDBDatabaseBackendMap::iterator it = m_databaseBackendMap.find(uniqueIdentifier);
- if (it != m_databaseBackendMap.end()) {
- // If it's already been opened, we have to wait for any pending
- // setVersion calls to complete.
- it->second->openConnection(callbacks);
- return;
- }
+ if (it == m_databaseBackendMap.end()) {
+ RefPtr<IDBBackingStore> backingStore = openBackingStore(securityOrigin, dataDirectory);
+ if (!backingStore) {
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
+ return;
+ }
- // FIXME: Everything from now on should be done on another thread.
- RefPtr<IDBBackingStore> backingStore = openBackingStore(securityOrigin, dataDirectory);
- if (!backingStore) {
- callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
- return;
- }
+ databaseBackend = IDBDatabaseBackendImpl::create(name, backingStore.get(), m_transactionCoordinator.get(), this, uniqueIdentifier);
+ if (databaseBackend)
+ m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.get());
+ else {
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
+ return;
+ }
+ } else
+ databaseBackend = it->second;
- RefPtr<IDBDatabaseBackendImpl> databaseBackend = IDBDatabaseBackendImpl::create(name, backingStore.get(), m_transactionCoordinator.get(), this, uniqueIdentifier);
- if (databaseBackend) {
- m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.get());
+ if (version == IDBDatabaseMetadata::NoIntVersion)
databaseBackend->openConnection(callbacks);
- } else
- callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
+ else
+ databaseBackend->openConnectionWithVersion(callbacks, version);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp (124674 => 124675)
--- trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp 2012-08-04 00:28:25 UTC (rev 124675)
@@ -234,7 +234,7 @@
}
}
-bool IDBLevelDBBackingStore::getIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId)
+bool IDBLevelDBBackingStore::getIDBDatabaseMetaData(const String& name, String& foundStringVersion, int64_t& foundIntVersion, int64_t& foundId)
{
const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
@@ -242,7 +242,7 @@
if (!ok)
return false;
- ok = getString(m_db.get(), DatabaseMetaDataKey::encode(foundId, DatabaseMetaDataKey::UserVersion), foundVersion);
+ ok = getString(m_db.get(), DatabaseMetaDataKey::encode(foundId, DatabaseMetaDataKey::UserVersion), foundStringVersion);
if (!ok)
return false;
@@ -264,7 +264,7 @@
return databaseId;
}
-bool IDBLevelDBBackingStore::createIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId)
+bool IDBLevelDBBackingStore::createIDBDatabaseMetaData(const String& name, const String& version, int64_t intVersion, int64_t& rowId)
{
rowId = getNewDatabaseId(m_db.get());
if (rowId < 0)
@@ -278,6 +278,12 @@
return true;
}
+bool IDBLevelDBBackingStore::updateIDBDatabaseIntVersion(int64_t rowId, int64_t intVersion)
+{
+ // FIXME: Make this actually do something. http://wkb.ug/92883
+ return true;
+}
+
bool IDBLevelDBBackingStore::updateIDBDatabaseMetaData(int64_t rowId, const String& version)
{
ASSERT(m_currentTransaction);
@@ -305,7 +311,8 @@
int64_t databaseId;
String version;
- if (!getIDBDatabaseMetaData(name, version, databaseId)) {
+ int64_t intVersion;
+ if (!getIDBDatabaseMetaData(name, version, intVersion, databaseId)) {
transaction->rollback();
return true;
}
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.h (124674 => 124675)
--- trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.h 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.h 2012-08-04 00:28:25 UTC (rev 124675)
@@ -45,9 +45,10 @@
virtual ~IDBLevelDBBackingStore();
virtual void getDatabaseNames(Vector<String>& foundNames);
- virtual bool getIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId);
- virtual bool createIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId);
+ virtual bool getIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundIntVersion, int64_t& foundId);
+ virtual bool createIDBDatabaseMetaData(const String& name, const String& version, int64_t intVersion, int64_t& rowId);
virtual bool updateIDBDatabaseMetaData(int64_t rowId, const String& version);
+ virtual bool updateIDBDatabaseIntVersion(int64_t rowId, int64_t intVersion);
virtual bool deleteDatabase(const String& name);
virtual void getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<IDBKeyPath>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags);
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp (124674 => 124675)
--- trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp 2012-08-04 00:28:25 UTC (rev 124675)
@@ -227,6 +227,8 @@
else
m_callbacks->onAbort();
+ m_database->transactionFinishedAndEventsFired(this);
+
m_database = 0;
}
Modified: trunk/Source/WebKit/chromium/ChangeLog (124674 => 124675)
--- trunk/Source/WebKit/chromium/ChangeLog 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebKit/chromium/ChangeLog 2012-08-04 00:28:25 UTC (rev 124675)
@@ -1,3 +1,16 @@
+2012-08-03 David Grogan <[email protected]>
+
+ IndexedDB: Core upgradeneeded logic
+ https://bugs.webkit.org/show_bug.cgi?id=92558
+
+ Reviewed by Ojan Vafai.
+
+ Update overridden methods to match new signatures.
+
+ * tests/IDBAbortOnCorruptTest.cpp:
+ (WebCore::FailingBackingStore::createIDBDatabaseMetaData):
+ * tests/IDBFakeBackingStore.h:
+
2012-08-03 Rick Byers <[email protected]>
Double tap gesture should send dblclick event
Modified: trunk/Source/WebKit/chromium/tests/IDBAbortOnCorruptTest.cpp (124674 => 124675)
--- trunk/Source/WebKit/chromium/tests/IDBAbortOnCorruptTest.cpp 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebKit/chromium/tests/IDBAbortOnCorruptTest.cpp 2012-08-04 00:28:25 UTC (rev 124675)
@@ -74,7 +74,7 @@
{
return adoptRef(new FailingBackingStore);
}
- virtual bool createIDBDatabaseMetaData(const String&, const String&, int64_t&)
+ virtual bool createIDBDatabaseMetaData(const String&, const String&, int64_t, int64_t&)
{
return false;
}
Modified: trunk/Source/WebKit/chromium/tests/IDBFakeBackingStore.h (124674 => 124675)
--- trunk/Source/WebKit/chromium/tests/IDBFakeBackingStore.h 2012-08-04 00:10:30 UTC (rev 124674)
+++ trunk/Source/WebKit/chromium/tests/IDBFakeBackingStore.h 2012-08-04 00:28:25 UTC (rev 124675)
@@ -33,9 +33,10 @@
class IDBFakeBackingStore : public IDBBackingStore {
public:
virtual void getDatabaseNames(Vector<String>& foundNames) OVERRIDE { }
- virtual bool getIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId) OVERRIDE { return false; }
- virtual bool createIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId) OVERRIDE { return true; }
+ virtual bool getIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundIntVersion, int64_t& foundId) OVERRIDE { return false; }
+ virtual bool createIDBDatabaseMetaData(const String& name, const String& version, int64_t intVersion, int64_t& rowId) OVERRIDE { return true; }
virtual bool updateIDBDatabaseMetaData(int64_t rowId, const String& version) OVERRIDE { return false; }
+ virtual bool updateIDBDatabaseIntVersion(int64_t rowId, int64_t version) OVERRIDE { return false; }
virtual bool deleteDatabase(const String& name) OVERRIDE { return false; }
virtual void getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<IDBKeyPath>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags) OVERRIDE { }