[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

jorlow at chromium.org jorlow at chromium.org
Wed Dec 22 13:57:59 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 4e087e04f8f43aeed71fc037a219666906cd066f
Author: jorlow at chromium.org <jorlow at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Sep 30 16:55:46 2010 +0000

    2010-09-29  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Finished IDBTransaction for IndexedDB
            https://bugs.webkit.org/show_bug.cgi?id=46823
    
            A bit of cleanup + use setVersion transactions for all of our work.
    
            * storage/indexeddb/database-basics.html:
            * storage/indexeddb/index-basics.html:
            * storage/indexeddb/index-cursor.html:
            * storage/indexeddb/objectstore-basics.html:
            * storage/indexeddb/objectstore-cursor.html:
            * storage/indexeddb/objectstore-removeobjectstore.html:
            * storage/indexeddb/open-cursor.html:
            * storage/indexeddb/transaction-basics.html:
    2010-09-29  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Finished IDBTransaction for IndexedDB
            https://bugs.webkit.org/show_bug.cgi?id=46823
    
            Switch the rest of IndexedDB to use transactions.
            Implement most of setVersion.
            Add IDBTransactions to IDBAny, IDBCursor, IDBRequest, etc.
            Switch to using the standard cross thread task stuff.
            Make everything threadsafe so it works with cross thread copy
                (will be useful in the future).
            Fix some subtle bugs in transactions.
    
            Various bits of clean up (when I couldn't resist).
    
            * bindings/js/JSIDBAnyCustom.cpp:
            (WebCore::toJS):
            * bindings/v8/IDBBindingUtilities.cpp:
            (WebCore::LocalContext::LocalContext):
            (WebCore::LocalContext::~LocalContext):
            (WebCore::createIDBKeyFromSerializedValueAndKeyPath):
            * bindings/v8/SerializedScriptValue.cpp:
            (WebCore::SerializedScriptValue::release):
            (WebCore::SerializedScriptValue::SerializedScriptValue):
            * bindings/v8/SerializedScriptValue.h:
            * bindings/v8/custom/V8IDBAnyCustom.cpp:
            (WebCore::toV8):
            * platform/CrossThreadCopier.cpp:
            * storage/IDBAny.cpp:
            (WebCore::IDBAny::idbFactory):
            (WebCore::IDBAny::idbTransaction):
            (WebCore::IDBAny::set):
            * storage/IDBAny.h:
            * storage/IDBCallbacks.h:
            * storage/IDBCursor.cpp:
            (WebCore::IDBCursor::IDBCursor):
            (WebCore::IDBCursor::update):
            (WebCore::IDBCursor::continueFunction):
            (WebCore::IDBCursor::remove):
            * storage/IDBCursor.h:
            (WebCore::IDBCursor::create):
            * storage/IDBCursorBackendImpl.cpp:
            (WebCore::IDBCursorBackendImpl::IDBCursorBackendImpl):
            (WebCore::IDBCursorBackendImpl::update):
            (WebCore::IDBCursorBackendImpl::updateInternal):
            (WebCore::IDBCursorBackendImpl::continueFunction):
            (WebCore::IDBCursorBackendImpl::continueFunctionInternal):
            (WebCore::IDBCursorBackendImpl::remove):
            (WebCore::IDBCursorBackendImpl::removeInternal):
            * storage/IDBCursorBackendImpl.h:
            (WebCore::IDBCursorBackendImpl::create):
            * storage/IDBDatabase.cpp:
            (WebCore::IDBDatabase::setSetVersionTransaction):
            (WebCore::IDBDatabase::createObjectStore):
            (WebCore::IDBDatabase::removeObjectStore):
            (WebCore::IDBDatabase::setVersion):
            (WebCore::IDBDatabase::close):
            * storage/IDBDatabase.h:
            * storage/IDBDatabase.idl:
            * storage/IDBDatabaseBackendImpl.cpp:
            (WebCore::IDBDatabaseBackendImpl::createObjectStore):
            (WebCore::IDBDatabaseBackendImpl::createObjectStoreInternal):
            (WebCore::IDBDatabaseBackendImpl::removeObjectStore):
            (WebCore::IDBDatabaseBackendImpl::removeObjectStoreInternal):
            (WebCore::IDBDatabaseBackendImpl::setVersion):
            (WebCore::IDBDatabaseBackendImpl::setVersionInternal):
            (WebCore::IDBDatabaseBackendImpl::close):
            * storage/IDBDatabaseBackendImpl.h:
            * storage/IDBDatabaseBackendInterface.h:
            * storage/IDBFactory.cpp:
            (WebCore::IDBFactory::open):
            * storage/IDBIndex.cpp:
            (WebCore::IDBIndex::IDBIndex):
            (WebCore::IDBIndex::openObjectCursor):
            (WebCore::IDBIndex::openCursor):
            (WebCore::IDBIndex::getObject):
            (WebCore::IDBIndex::get):
            * storage/IDBIndex.h:
            (WebCore::IDBIndex::create):
            * storage/IDBIndexBackendImpl.cpp:
            (WebCore::IDBIndexBackendImpl::openCursorInternal):
            (WebCore::IDBIndexBackendImpl::openObjectCursor):
            (WebCore::IDBIndexBackendImpl::openCursor):
            (WebCore::IDBIndexBackendImpl::getInternal):
            (WebCore::IDBIndexBackendImpl::getObject):
            (WebCore::IDBIndexBackendImpl::get):
            * storage/IDBIndexBackendImpl.h:
            * storage/IDBIndexBackendInterface.h:
            * storage/IDBKey.cpp:
            (WebCore::IDBKey::IDBKey):
            * storage/IDBKey.h:
            * storage/IDBKeyRange.h:
            * storage/IDBObjectStore.cpp:
            (WebCore::IDBObjectStore::IDBObjectStore):
            (WebCore::IDBObjectStore::add):
            (WebCore::IDBObjectStore::put):
            (WebCore::IDBObjectStore::remove):
            (WebCore::IDBObjectStore::createIndex):
            (WebCore::IDBObjectStore::index):
            (WebCore::IDBObjectStore::removeIndex):
            (WebCore::IDBObjectStore::openCursor):
            * storage/IDBObjectStore.idl:
            * storage/IDBObjectStoreBackendImpl.cpp:
            (WebCore::IDBObjectStoreBackendImpl::get):
            (WebCore::IDBObjectStoreBackendImpl::getInternal):
            (WebCore::IDBObjectStoreBackendImpl::put):
            (WebCore::IDBObjectStoreBackendImpl::putInternal):
            (WebCore::IDBObjectStoreBackendImpl::remove):
            (WebCore::IDBObjectStoreBackendImpl::removeInternal):
            (WebCore::IDBObjectStoreBackendImpl::createIndex):
            (WebCore::IDBObjectStoreBackendImpl::createIndexInternal):
            (WebCore::IDBObjectStoreBackendImpl::removeIndex):
            (WebCore::IDBObjectStoreBackendImpl::removeIndexInternal):
            (WebCore::IDBObjectStoreBackendImpl::openCursor):
            (WebCore::IDBObjectStoreBackendImpl::openCursorInternal):
            * storage/IDBObjectStoreBackendImpl.h:
            * storage/IDBObjectStoreBackendInterface.h:
            * storage/IDBRequest.cpp:
            (WebCore::IDBRequest::IDBRequest):
            (WebCore::IDBRequest::resetReadyState):
            (WebCore::IDBRequest::onSuccess):
            (WebCore::IDBRequest::timerFired):
            * storage/IDBRequest.h:
            (WebCore::IDBRequest::create):
            * storage/IDBTransactionBackendImpl.cpp:
            (WebCore::IDBTransactionBackendImpl::IDBTransactionBackendImpl):
            (WebCore::IDBTransactionBackendImpl::scheduleTask):
            (WebCore::IDBTransactionBackendImpl::didCompleteTaskEvents):
            (WebCore::IDBTransactionBackendImpl::run):
            (WebCore::IDBTransactionBackendImpl::start):
            (WebCore::IDBTransactionBackendImpl::commit):
            (WebCore::IDBTransactionBackendImpl::timerFired):
            * storage/IDBTransactionBackendImpl.h:
    2010-09-29  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Finished IDBTransaction for IndexedDB
            https://bugs.webkit.org/show_bug.cgi?id=46823
    
            Plumbing.
    
            * public/WebIDBCallbacks.h:
            (WebKit::WebIDBCallbacks::onSuccess):
            * public/WebIDBDatabase.h:
            (WebKit::WebIDBDatabase::createObjectStore):
            (WebKit::WebIDBDatabase::removeObjectStore):
            (WebKit::WebIDBDatabase::close):
            * public/WebIDBIndex.h:
            (WebKit::WebIDBIndex::openObjectCursor):
            (WebKit::WebIDBIndex::openCursor):
            (WebKit::WebIDBIndex::getObject):
            (WebKit::WebIDBIndex::get):
            * public/WebIDBObjectStore.h:
            (WebKit::WebIDBObjectStore::get):
            (WebKit::WebIDBObjectStore::put):
            (WebKit::WebIDBObjectStore::remove):
            (WebKit::WebIDBObjectStore::createIndex):
            (WebKit::WebIDBObjectStore::removeIndex):
            (WebKit::WebIDBObjectStore::openCursor):
            * public/WebIDBTransaction.h:
            (WebKit::WebIDBTransaction::id):
            (WebKit::WebIDBTransaction::getIDBTransactionBackendInterface):
            * src/IDBCallbacksProxy.cpp:
            (WebCore::IDBCallbacksProxy::onSuccess):
            * src/IDBCallbacksProxy.h:
            * src/IDBDatabaseProxy.cpp:
            (WebCore::IDBDatabaseProxy::createObjectStore):
            (WebCore::IDBDatabaseProxy::removeObjectStore):
            (WebCore::IDBDatabaseProxy::close):
            * src/IDBDatabaseProxy.h:
            * src/IDBIndexBackendProxy.cpp:
            (WebCore::IDBIndexBackendProxy::openObjectCursor):
            (WebCore::IDBIndexBackendProxy::openCursor):
            (WebCore::IDBIndexBackendProxy::getObject):
            (WebCore::IDBIndexBackendProxy::get):
            * src/IDBIndexBackendProxy.h:
            * src/IDBObjectStoreProxy.cpp:
            (WebCore::IDBObjectStoreProxy::put):
            (WebCore::IDBObjectStoreProxy::remove):
            (WebCore::IDBObjectStoreProxy::createIndex):
            (WebCore::IDBObjectStoreProxy::removeIndex):
            (WebCore::IDBObjectStoreProxy::openCursor):
            * src/IDBObjectStoreProxy.h:
            * src/IDBTransactionBackendProxy.cpp:
            (WebCore::IDBTransactionBackendProxy::IDBTransactionBackendProxy):
            * src/WebIDBCallbacksImpl.cpp:
            (WebCore::WebIDBCallbacksImpl::onSuccess):
            * src/WebIDBCallbacksImpl.h:
            * src/WebIDBDatabaseImpl.cpp:
            (WebKit::WebIDBDatabaseImpl::createObjectStore):
            (WebKit::WebIDBDatabaseImpl::removeObjectStore):
            (WebKit::WebIDBDatabaseImpl::close):
            * src/WebIDBDatabaseImpl.h:
            * src/WebIDBIndexImpl.cpp:
            (WebKit::WebIDBIndexImpl::openCursor):
            (WebKit::WebIDBIndexImpl::openObjectCursor):
            (WebKit::WebIDBIndexImpl::getObject):
            (WebKit::WebIDBIndexImpl::get):
            * src/WebIDBIndexImpl.h:
            * src/WebIDBObjectStoreImpl.cpp:
            (WebKit::WebIDBObjectStoreImpl::put):
            (WebKit::WebIDBObjectStoreImpl::remove):
            (WebKit::WebIDBObjectStoreImpl::createIndex):
            (WebKit::WebIDBObjectStoreImpl::removeIndex):
            (WebKit::WebIDBObjectStoreImpl::openCursor):
            * src/WebIDBObjectStoreImpl.h:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@68795 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 4f42684..e24c528 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,21 @@
+2010-09-29  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
+        Finished IDBTransaction for IndexedDB
+        https://bugs.webkit.org/show_bug.cgi?id=46823
+
+        A bit of cleanup + use setVersion transactions for all of our work.
+
+        * storage/indexeddb/database-basics.html:
+        * storage/indexeddb/index-basics.html:
+        * storage/indexeddb/index-cursor.html:
+        * storage/indexeddb/objectstore-basics.html:
+        * storage/indexeddb/objectstore-cursor.html:
+        * storage/indexeddb/objectstore-removeobjectstore.html:
+        * storage/indexeddb/open-cursor.html:
+        * storage/indexeddb/transaction-basics.html:
+
 2010-09-30  Adam Roben  <aroben at apple.com>
 
         Skip a crashing test on Windows
diff --git a/LayoutTests/storage/indexeddb/database-basics-expected.txt b/LayoutTests/storage/indexeddb/database-basics-expected.txt
index 42c9879..97ec721 100644
--- a/LayoutTests/storage/indexeddb/database-basics-expected.txt
+++ b/LayoutTests/storage/indexeddb/database-basics-expected.txt
@@ -21,6 +21,26 @@ PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
 db = event.result
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+setVersionSuccess():
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
 Testing setVersion.
 db.setVersion("version a")
 PASS 'onsuccess' in result is true
diff --git a/LayoutTests/storage/indexeddb/database-basics.html b/LayoutTests/storage/indexeddb/database-basics.html
index b099a49..850d30d 100644
--- a/LayoutTests/storage/indexeddb/database-basics.html
+++ b/LayoutTests/storage/indexeddb/database-basics.html
@@ -14,18 +14,38 @@ description("Test the basics of IndexedDB's IDBDatabase.");
 if (window.layoutTestController) 
     layoutTestController.waitUntilDone();
 
+function test()
+{
+    result = evalAndLog("indexedDB.open('name', 'description')");
+    verifyResult(result);
+    result.onsuccess = openSuccess;
+    result.onerror = unexpectedErrorCallback;
+}
+
 function openSuccess()
 {
     verifySuccessEvent(event);
+    window.db = evalAndLog("db = event.result");
+
+    result = evalAndLog("db.setVersion('new version')");
+    verifyResult(result);
+    result.onsuccess = setVersionSuccess;
+    result.onerror = unexpectedErrorCallback;
+}
 
-    var db = evalAndLog("db = event.result");
-    deleteAllObjectStores(db);
+function setVersionSuccess()
+{
+    debug("setVersionSuccess():");
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
 
-    // We must do something asynchronous before anything synchronous since
-    // deleteAllObjectStores only schedules the object stores to be removed.
-    // We don't know for sure whether it's happened until an IDBRequest object
-    // that was created after the removes fires.
+    deleteAllObjectStores(db, testSetVersion);
+}
 
+function testSetVersion()
+{
     debug("Testing setVersion.");
     result = evalAndLog('db.setVersion("version a")');
     verifyResult(result);
@@ -70,14 +90,6 @@ function checkObjectStore()
     done();
 }
 
-function test()
-{
-    result = evalAndLog("indexedDB.open('name', 'description')");
-    verifyResult(result);
-    result.onsuccess = openSuccess;
-    result.onerror = unexpectedErrorCallback;
-}
-
 test();
 
 var successfullyParsed = true;
diff --git a/LayoutTests/storage/indexeddb/index-basics-expected.txt b/LayoutTests/storage/indexeddb/index-basics-expected.txt
index 564bdc8..d8d6dcc 100644
--- a/LayoutTests/storage/indexeddb/index-basics-expected.txt
+++ b/LayoutTests/storage/indexeddb/index-basics-expected.txt
@@ -21,6 +21,26 @@ PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
 db = event.result
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+setVersionSuccess():
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
 db.createObjectStore('storeName', null)
 PASS 'onsuccess' in result is true
 PASS 'onerror' in result is true
diff --git a/LayoutTests/storage/indexeddb/index-basics.html b/LayoutTests/storage/indexeddb/index-basics.html
index c23f141..3c8a601 100644
--- a/LayoutTests/storage/indexeddb/index-basics.html
+++ b/LayoutTests/storage/indexeddb/index-basics.html
@@ -18,17 +18,34 @@ function test()
 {
     result = evalAndLog("indexedDB.open('name', 'description')");
     verifyResult(result);
-    result.onsuccess = createObjectStore;
+    result.onsuccess = setVersion;
     result.onerror = unexpectedErrorCallback;
 }
 
-function createObjectStore()
+function setVersion()
 {
     verifySuccessEvent(event);
     db = evalAndLog("db = event.result");
 
-    deleteAllObjectStores(db);
+    result = evalAndLog("db.setVersion('new version')");
+    verifyResult(result);
+    result.onsuccess = deleteExisting;
+    result.onerror = unexpectedErrorCallback;
+}
 
+function deleteExisting()
+{
+    debug("setVersionSuccess():");
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
+
+    deleteAllObjectStores(db, createObjectStore);
+}
+
+function createObjectStore()
+{
     result = evalAndLog("db.createObjectStore('storeName', null)");
     verifyResult(result);
     result.onsuccess = createIndex;
diff --git a/LayoutTests/storage/indexeddb/index-cursor-expected.txt b/LayoutTests/storage/indexeddb/index-cursor-expected.txt
index 6d1417f..9724fd0 100644
--- a/LayoutTests/storage/indexeddb/index-cursor-expected.txt
+++ b/LayoutTests/storage/indexeddb/index-cursor-expected.txt
@@ -21,6 +21,25 @@ PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
 db = event.result
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
 db.createObjectStore('someObjectStore')
 PASS 'onsuccess' in result is true
 PASS 'onerror' in result is true
diff --git a/LayoutTests/storage/indexeddb/index-cursor.html b/LayoutTests/storage/indexeddb/index-cursor.html
index 9541d60..66b6dc6 100644
--- a/LayoutTests/storage/indexeddb/index-cursor.html
+++ b/LayoutTests/storage/indexeddb/index-cursor.html
@@ -31,17 +31,33 @@ function openDatabase()
 {
     result = evalAndLog("indexedDB.open('someDB', 'some description')");
     verifyResult(result);
-    result.onsuccess = openObjectStore;
+    result.onsuccess = setVersion;
     result.onerror = unexpectedErrorCallback;
 }
  
-function openObjectStore()
+function setVersion()
 {
     verifySuccessEvent(event);
     window.db = evalAndLog("db = event.result");
 
-    deleteAllObjectStores(db);
+    result = evalAndLog("db.setVersion('new version')");
+    verifyResult(result);
+    result.onsuccess = deleteExisting;
+    result.onerror = unexpectedErrorCallback;
+}
 
+function deleteExisting()
+{
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
+
+    deleteAllObjectStores(db, createObjectStores);
+}
+
+function createObjectStores()
+{
     result = evalAndLog("db.createObjectStore('someObjectStore')");
     verifyResult(result);
     result.onsuccess = openIndex;
@@ -105,7 +121,7 @@ function scheduleTests()
     }
  
     debug("Running tests...");
-    setTimeout(runNextTest, 0);
+    runNextTest();
 }
  
 function runNextTest()
@@ -213,12 +229,12 @@ function cursorIteration()
 {
     if (expectedIndex === null) {
         shouldBeNull("event.result");
-        setTimeout(runNextTest, 0);
+        runNextTest();
         return;
     }
     if (event.result === null) {
-        testFailed("Event.result should not be null.")
-        setTimeout(runNextTest, 0);
+        testFailed("Event.result should not be null.");
+        runNextTest();
         return;
     }
  
diff --git a/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt b/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt
index 7b5439a..1df5a4e 100644
--- a/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt
+++ b/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt
@@ -22,6 +22,26 @@ PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
 db = event.result
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+setVersionSuccess():
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
 db.createObjectStore('storeName', null)
 PASS 'onsuccess' in result is true
 PASS 'onerror' in result is true
diff --git a/LayoutTests/storage/indexeddb/objectstore-basics.html b/LayoutTests/storage/indexeddb/objectstore-basics.html
index b2d383a..9b00946 100644
--- a/LayoutTests/storage/indexeddb/objectstore-basics.html
+++ b/LayoutTests/storage/indexeddb/objectstore-basics.html
@@ -26,10 +26,27 @@ function openSuccess()
 {
     debug("openSuccess():");
     verifySuccessEvent(event);
-    db = evalAndLog("db = event.result");
+    window.db = evalAndLog("db = event.result");
 
-    deleteAllObjectStores(db);
+    result = evalAndLog("db.setVersion('new version')");
+    verifyResult(result);
+    result.onsuccess = setVersionSuccess;
+    result.onerror = unexpectedErrorCallback;
+}
 
+function setVersionSuccess()
+{
+    debug("setVersionSuccess():");
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
+
+    deleteAllObjectStores(db, deleteSuccess);
+}
+
+function deleteSuccess()
+{
     result = evalAndLog("db.createObjectStore('storeName', null)");
     verifyResult(result);
     result.onsuccess = createSuccess;
diff --git a/LayoutTests/storage/indexeddb/objectstore-cursor-expected.txt b/LayoutTests/storage/indexeddb/objectstore-cursor-expected.txt
index e7211f6..f1f13ae 100644
--- a/LayoutTests/storage/indexeddb/objectstore-cursor-expected.txt
+++ b/LayoutTests/storage/indexeddb/objectstore-cursor-expected.txt
@@ -21,6 +21,25 @@ PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
 db = event.result
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
 db.createObjectStore('someObjectStore')
 PASS 'onsuccess' in result is true
 PASS 'onerror' in result is true
diff --git a/LayoutTests/storage/indexeddb/objectstore-cursor.html b/LayoutTests/storage/indexeddb/objectstore-cursor.html
index 25e9456..702076f 100644
--- a/LayoutTests/storage/indexeddb/objectstore-cursor.html
+++ b/LayoutTests/storage/indexeddb/objectstore-cursor.html
@@ -30,17 +30,33 @@ function openDatabase()
 {
     result = evalAndLog("indexedDB.open('someDB', 'some description')");
     verifyResult(result);
-    result.onsuccess = openObjectStore;
+    result.onsuccess = setVersion;
     result.onerror = unexpectedErrorCallback;
 }
  
-function openObjectStore()
+function setVersion()
 {
     verifySuccessEvent(event);
     window.db = evalAndLog("db = event.result");
 
-    deleteAllObjectStores(db);
+    result = evalAndLog("db.setVersion('new version')");
+    verifyResult(result);
+    result.onsuccess = deleteExisting;
+    result.onerror = unexpectedErrorCallback;
+}
 
+function deleteExisting()
+{
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
+
+    deleteAllObjectStores(db, openObjectStore);
+}
+
+function openObjectStore()
+{
     result = evalAndLog("db.createObjectStore('someObjectStore')");
     verifyResult(result);
     result.onsuccess = startAddingData;
@@ -93,7 +109,7 @@ function scheduleTests()
     }
  
     debug("Running tests...");
-    setTimeout(runNextTest, 0);
+    runNextTest();
 }
  
 function runNextTest()
@@ -182,12 +198,12 @@ function cursorIteration()
 {
     if (expectedIndex === null) {
         shouldBeNull("event.result");
-        setTimeout(runNextTest, 0);
+        runNextTest();
         return;
     }
     if (event.result === null) {
-        testFailed("Event.result should not be null.")
-        setTimeout(runNextTest, 0);
+        testFailed("Event.result should not be null.");
+        runNextTest();
         return;
     }
  
diff --git a/LayoutTests/storage/indexeddb/objectstore-removeobjectstore-expected.txt b/LayoutTests/storage/indexeddb/objectstore-removeobjectstore-expected.txt
index b7ba473..b53e47d 100644
--- a/LayoutTests/storage/indexeddb/objectstore-removeobjectstore-expected.txt
+++ b/LayoutTests/storage/indexeddb/objectstore-removeobjectstore-expected.txt
@@ -21,6 +21,25 @@ PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
 db = event.result
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
 db.createObjectStore('storeName', null)
 PASS 'onsuccess' in result is true
 PASS 'onerror' in result is true
@@ -93,6 +112,25 @@ PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
 PASS event.source.indexNames.contains('indexName') is true
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
 db.removeObjectStore('storeName')
 PASS 'onsuccess' in result is true
 PASS 'onerror' in result is true
diff --git a/LayoutTests/storage/indexeddb/objectstore-removeobjectstore.html b/LayoutTests/storage/indexeddb/objectstore-removeobjectstore.html
index 7878c7f..93dcbf6 100644
--- a/LayoutTests/storage/indexeddb/objectstore-removeobjectstore.html
+++ b/LayoutTests/storage/indexeddb/objectstore-removeobjectstore.html
@@ -18,17 +18,32 @@ function test()
 {
     result = evalAndLog("indexedDB.open('name', 'description')");
     verifyResult(result);
-    result.onsuccess = createObjectStore;
+    result.onsuccess = startSetVersion;
     result.onerror = unexpectedErrorCallback;
 }
 
-function createObjectStore()
+function startSetVersion()
 {
     verifySuccessEvent(event);
     db = evalAndLog("db = event.result");
 
-    deleteAllObjectStores(db);
+    result = evalAndLog("db.setVersion('new version')");
+    verifyResult(result);
+    result.onsuccess = deleteExisting;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function deleteExisting()
+{
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+
+    deleteAllObjectStores(db, createObjectStore);
+}
 
+function createObjectStore()
+{
     result = evalAndLog("db.createObjectStore('storeName', null)");
     verifyResult(result);
     result.onsuccess = addValue;
@@ -75,11 +90,24 @@ function commitTransaction()
     verifySuccessEvent(event);
     shouldBeTrue("event.source.indexNames.contains('indexName')");
     // Let the transaction commit.
-    window.setTimeout('removeObjectStore()', 0);
+    window.setTimeout('secondSetVersion()', 0);
+}
+
+function secondSetVersion()
+{
+    result = evalAndLog("db.setVersion('new version')");
+    verifyResult(result);
+    result.onsuccess = removeObjectStore;
+    result.onerror = unexpectedErrorCallback;
 }
 
 function removeObjectStore()
 {
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
+
     result = evalAndLog("db.removeObjectStore('storeName')");
     verifyResult(result);
     result.onsuccess = createObjectStoreAgain;
diff --git a/LayoutTests/storage/indexeddb/open-cursor-expected.txt b/LayoutTests/storage/indexeddb/open-cursor-expected.txt
index bda103f..48a689f 100644
--- a/LayoutTests/storage/indexeddb/open-cursor-expected.txt
+++ b/LayoutTests/storage/indexeddb/open-cursor-expected.txt
@@ -21,6 +21,26 @@ PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
 db = event.result
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+setVersionSuccess():
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
 db.createObjectStore('test')
 PASS 'onsuccess' in result is true
 PASS 'onerror' in result is true
diff --git a/LayoutTests/storage/indexeddb/open-cursor.html b/LayoutTests/storage/indexeddb/open-cursor.html
index 03d1da0..47c7e89 100644
--- a/LayoutTests/storage/indexeddb/open-cursor.html
+++ b/LayoutTests/storage/indexeddb/open-cursor.html
@@ -69,16 +69,33 @@ function createObjectStoreSuccess()
     populateObjectStore(objectStore);
 }
 
+function deleteSuccess()
+{
+    result = evalAndLog("db.createObjectStore('test')");
+    verifyResult(result);
+    result.onsuccess = createObjectStoreSuccess;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function setVersionSuccess()
+{
+    debug("setVersionSuccess():");
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
+
+    deleteAllObjectStores(db, deleteSuccess);
+}
+
 function openSuccess()
 {
     verifySuccessEvent(event);
     var db = evalAndLog("db = event.result");
 
-    deleteAllObjectStores(db);
-
-    result = evalAndLog("db.createObjectStore('test')");
+    result = evalAndLog("db.setVersion('new version')");
     verifyResult(result);
-    result.onsuccess = createObjectStoreSuccess;
+    result.onsuccess = setVersionSuccess;
     result.onerror = unexpectedErrorCallback;
 }
 
diff --git a/LayoutTests/storage/indexeddb/resources/shared.js b/LayoutTests/storage/indexeddb/resources/shared.js
index 65da3bf..ea4a525 100644
--- a/LayoutTests/storage/indexeddb/resources/shared.js
+++ b/LayoutTests/storage/indexeddb/resources/shared.js
@@ -65,9 +65,23 @@ function unexpectedErrorCallback()
     done();
 }
 
-function deleteAllObjectStores(db)
+function unexpectedAbortCallback()
+{
+    testFailed("Abort function called unexpectedly!");
+    debug("");
+    verifyAbortEvent(event);
+    done();
+}
+
+function deleteAllObjectStores(db, onfinished)
 {
     objectStores = db.objectStores;
-    for (var i = 0; i < objectStores.length; ++i)
-        db.removeObjectStore(objectStores[i]);
+    if (!objectStores.length) {
+        onfinished();
+        return;
+    }
+
+    var request = db.removeObjectStore(objectStores[0]);
+    request.onerror = unexpectedErrorCallback;
+    request.onsuccess = function() { deleteAllObjectStores(db, onfinished); };
 }
diff --git a/LayoutTests/storage/indexeddb/transaction-basics-expected.txt b/LayoutTests/storage/indexeddb/transaction-basics-expected.txt
index bba62f0..fce593b 100644
--- a/LayoutTests/storage/indexeddb/transaction-basics-expected.txt
+++ b/LayoutTests/storage/indexeddb/transaction-basics-expected.txt
@@ -24,6 +24,26 @@ PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
 db = event.result
+db.setVersion('new version')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+setVersionSuccess():
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+trans = event.result
+PASS trans !== null is true
 db.createObjectStore('storeName', null)
 PASS 'onsuccess' in result is true
 PASS 'onerror' in result is true
diff --git a/LayoutTests/storage/indexeddb/transaction-basics.html b/LayoutTests/storage/indexeddb/transaction-basics.html
index cea5d5d..8fb6493 100644
--- a/LayoutTests/storage/indexeddb/transaction-basics.html
+++ b/LayoutTests/storage/indexeddb/transaction-basics.html
@@ -31,8 +31,25 @@ function openSuccess()
     verifySuccessEvent(event);
     db = evalAndLog("db = event.result");
 
-    deleteAllObjectStores(db);
+    result = evalAndLog("db.setVersion('new version')");
+    verifyResult(result);
+    result.onsuccess = setVersionSuccess;
+    result.onerror = unexpectedErrorCallback;
+}
 
+function setVersionSuccess()
+{
+    debug("setVersionSuccess():");
+    verifySuccessEvent(event);
+    window.trans = evalAndLog("trans = event.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
+
+    deleteAllObjectStores(db, finishedDeleting);
+}
+
+function finishedDeleting()
+{
     result = evalAndLog("db.createObjectStore('storeName', null)");
     verifyResult(result);
     result.onsuccess = createSuccess;
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 3e0b259..847c4ce 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,139 @@
+2010-09-29  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
+        Finished IDBTransaction for IndexedDB
+        https://bugs.webkit.org/show_bug.cgi?id=46823
+
+        Switch the rest of IndexedDB to use transactions.
+        Implement most of setVersion.
+        Add IDBTransactions to IDBAny, IDBCursor, IDBRequest, etc.
+        Switch to using the standard cross thread task stuff.
+        Make everything threadsafe so it works with cross thread copy
+            (will be useful in the future).
+        Fix some subtle bugs in transactions.
+        
+        Various bits of clean up (when I couldn't resist).
+
+        * bindings/js/JSIDBAnyCustom.cpp:
+        (WebCore::toJS):
+        * bindings/v8/IDBBindingUtilities.cpp:
+        (WebCore::LocalContext::LocalContext):
+        (WebCore::LocalContext::~LocalContext):
+        (WebCore::createIDBKeyFromSerializedValueAndKeyPath):
+        * bindings/v8/SerializedScriptValue.cpp:
+        (WebCore::SerializedScriptValue::release):
+        (WebCore::SerializedScriptValue::SerializedScriptValue):
+        * bindings/v8/SerializedScriptValue.h:
+        * bindings/v8/custom/V8IDBAnyCustom.cpp:
+        (WebCore::toV8):
+        * platform/CrossThreadCopier.cpp:
+        * storage/IDBAny.cpp:
+        (WebCore::IDBAny::idbFactory):
+        (WebCore::IDBAny::idbTransaction):
+        (WebCore::IDBAny::set):
+        * storage/IDBAny.h:
+        * storage/IDBCallbacks.h:
+        * storage/IDBCursor.cpp:
+        (WebCore::IDBCursor::IDBCursor):
+        (WebCore::IDBCursor::update):
+        (WebCore::IDBCursor::continueFunction):
+        (WebCore::IDBCursor::remove):
+        * storage/IDBCursor.h:
+        (WebCore::IDBCursor::create):
+        * storage/IDBCursorBackendImpl.cpp:
+        (WebCore::IDBCursorBackendImpl::IDBCursorBackendImpl):
+        (WebCore::IDBCursorBackendImpl::update):
+        (WebCore::IDBCursorBackendImpl::updateInternal):
+        (WebCore::IDBCursorBackendImpl::continueFunction):
+        (WebCore::IDBCursorBackendImpl::continueFunctionInternal):
+        (WebCore::IDBCursorBackendImpl::remove):
+        (WebCore::IDBCursorBackendImpl::removeInternal):
+        * storage/IDBCursorBackendImpl.h:
+        (WebCore::IDBCursorBackendImpl::create):
+        * storage/IDBDatabase.cpp:
+        (WebCore::IDBDatabase::setSetVersionTransaction):
+        (WebCore::IDBDatabase::createObjectStore):
+        (WebCore::IDBDatabase::removeObjectStore):
+        (WebCore::IDBDatabase::setVersion):
+        (WebCore::IDBDatabase::close):
+        * storage/IDBDatabase.h:
+        * storage/IDBDatabase.idl:
+        * storage/IDBDatabaseBackendImpl.cpp:
+        (WebCore::IDBDatabaseBackendImpl::createObjectStore):
+        (WebCore::IDBDatabaseBackendImpl::createObjectStoreInternal):
+        (WebCore::IDBDatabaseBackendImpl::removeObjectStore):
+        (WebCore::IDBDatabaseBackendImpl::removeObjectStoreInternal):
+        (WebCore::IDBDatabaseBackendImpl::setVersion):
+        (WebCore::IDBDatabaseBackendImpl::setVersionInternal):
+        (WebCore::IDBDatabaseBackendImpl::close):
+        * storage/IDBDatabaseBackendImpl.h:
+        * storage/IDBDatabaseBackendInterface.h:
+        * storage/IDBFactory.cpp:
+        (WebCore::IDBFactory::open):
+        * storage/IDBIndex.cpp:
+        (WebCore::IDBIndex::IDBIndex):
+        (WebCore::IDBIndex::openObjectCursor):
+        (WebCore::IDBIndex::openCursor):
+        (WebCore::IDBIndex::getObject):
+        (WebCore::IDBIndex::get):
+        * storage/IDBIndex.h:
+        (WebCore::IDBIndex::create):
+        * storage/IDBIndexBackendImpl.cpp:
+        (WebCore::IDBIndexBackendImpl::openCursorInternal):
+        (WebCore::IDBIndexBackendImpl::openObjectCursor):
+        (WebCore::IDBIndexBackendImpl::openCursor):
+        (WebCore::IDBIndexBackendImpl::getInternal):
+        (WebCore::IDBIndexBackendImpl::getObject):
+        (WebCore::IDBIndexBackendImpl::get):
+        * storage/IDBIndexBackendImpl.h:
+        * storage/IDBIndexBackendInterface.h:
+        * storage/IDBKey.cpp:
+        (WebCore::IDBKey::IDBKey):
+        * storage/IDBKey.h:
+        * storage/IDBKeyRange.h:
+        * storage/IDBObjectStore.cpp:
+        (WebCore::IDBObjectStore::IDBObjectStore):
+        (WebCore::IDBObjectStore::add):
+        (WebCore::IDBObjectStore::put):
+        (WebCore::IDBObjectStore::remove):
+        (WebCore::IDBObjectStore::createIndex):
+        (WebCore::IDBObjectStore::index):
+        (WebCore::IDBObjectStore::removeIndex):
+        (WebCore::IDBObjectStore::openCursor):
+        * storage/IDBObjectStore.idl:
+        * storage/IDBObjectStoreBackendImpl.cpp:
+        (WebCore::IDBObjectStoreBackendImpl::get):
+        (WebCore::IDBObjectStoreBackendImpl::getInternal):
+        (WebCore::IDBObjectStoreBackendImpl::put):
+        (WebCore::IDBObjectStoreBackendImpl::putInternal):
+        (WebCore::IDBObjectStoreBackendImpl::remove):
+        (WebCore::IDBObjectStoreBackendImpl::removeInternal):
+        (WebCore::IDBObjectStoreBackendImpl::createIndex):
+        (WebCore::IDBObjectStoreBackendImpl::createIndexInternal):
+        (WebCore::IDBObjectStoreBackendImpl::removeIndex):
+        (WebCore::IDBObjectStoreBackendImpl::removeIndexInternal):
+        (WebCore::IDBObjectStoreBackendImpl::openCursor):
+        (WebCore::IDBObjectStoreBackendImpl::openCursorInternal):
+        * storage/IDBObjectStoreBackendImpl.h:
+        * storage/IDBObjectStoreBackendInterface.h:
+        * storage/IDBRequest.cpp:
+        (WebCore::IDBRequest::IDBRequest):
+        (WebCore::IDBRequest::resetReadyState):
+        (WebCore::IDBRequest::onSuccess):
+        (WebCore::IDBRequest::timerFired):
+        * storage/IDBRequest.h:
+        (WebCore::IDBRequest::create):
+        * storage/IDBTransactionBackendImpl.cpp:
+        (WebCore::IDBTransactionBackendImpl::IDBTransactionBackendImpl):
+        (WebCore::IDBTransactionBackendImpl::scheduleTask):
+        (WebCore::IDBTransactionBackendImpl::didCompleteTaskEvents):
+        (WebCore::IDBTransactionBackendImpl::run):
+        (WebCore::IDBTransactionBackendImpl::start):
+        (WebCore::IDBTransactionBackendImpl::commit):
+        (WebCore::IDBTransactionBackendImpl::timerFired):
+        * storage/IDBTransactionBackendImpl.h:
+
 2010-09-30  Csaba Osztrogonác  <ossy at webkit.org>
 
         Reviewed by Martin Robinson.
diff --git a/WebCore/bindings/js/JSIDBAnyCustom.cpp b/WebCore/bindings/js/JSIDBAnyCustom.cpp
index e428bf6..506f15f 100644
--- a/WebCore/bindings/js/JSIDBAnyCustom.cpp
+++ b/WebCore/bindings/js/JSIDBAnyCustom.cpp
@@ -44,6 +44,7 @@
 #include "JSIDBIndex.h"
 #include "JSIDBKey.h"
 #include "JSIDBObjectStore.h"
+#include "JSIDBTransaction.h"
 #include "SerializedScriptValue.h"
 
 using namespace JSC;
@@ -64,14 +65,16 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, IDBAny* idbAny)
         return toJS(exec, globalObject, idbAny->idbCursor());
     case IDBAny::IDBDatabaseType:
         return toJS(exec, globalObject, idbAny->idbDatabase());
+    case IDBAny::IDBFactoryType:
+        return toJS(exec, globalObject, idbAny->idbFactory());
     case IDBAny::IDBIndexType:
         return toJS(exec, globalObject, idbAny->idbIndex());
     case IDBAny::IDBKeyType:
         return toJS(exec, globalObject, idbAny->idbKey());
     case IDBAny::IDBObjectStoreType:
         return toJS(exec, globalObject, idbAny->idbObjectStore());
-    case IDBAny::IDBFactoryType:
-        return toJS(exec, globalObject, idbAny->idbFactory());
+    case IDBAny::IDBTransactionType:
+        return toJS(exec, globalObject, idbAny->idbTransaction());
     case IDBAny::SerializedScriptValueType:
         return idbAny->serializedScriptValue()->deserialize(exec, globalObject);
     }
diff --git a/WebCore/bindings/v8/IDBBindingUtilities.cpp b/WebCore/bindings/v8/IDBBindingUtilities.cpp
index a000a7d..4a58853 100644
--- a/WebCore/bindings/v8/IDBBindingUtilities.cpp
+++ b/WebCore/bindings/v8/IDBBindingUtilities.cpp
@@ -58,9 +58,28 @@ bool getValueFrom(T indexOrName, v8::Handle<v8::Value>& v8Value)
     return true;
 }
 
+class LocalContext {
+public:
+    LocalContext()
+        : m_context(v8::Context::New())
+    {
+        m_context->Enter();
+    }
+
+    ~LocalContext()
+    {
+        m_context->Exit();
+        m_context.Dispose();
+    }
+
+private:
+    v8::HandleScope m_scope;
+    v8::Persistent<v8::Context> m_context;
+};
+
 PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<SerializedScriptValue> value, const Vector<IDBKeyPathElement>& keyPath)
 {
-    v8::HandleScope scope;
+    LocalContext localContext;
     v8::Handle<v8::Value> v8Value(value->deserialize());
     for (size_t i = 0; i < keyPath.size(); ++i) {
         switch (keyPath[i].type) {
diff --git a/WebCore/bindings/v8/SerializedScriptValue.cpp b/WebCore/bindings/v8/SerializedScriptValue.cpp
index 4e5354e..ff92167 100644
--- a/WebCore/bindings/v8/SerializedScriptValue.cpp
+++ b/WebCore/bindings/v8/SerializedScriptValue.cpp
@@ -1105,7 +1105,7 @@ SerializedScriptValue* SerializedScriptValue::nullValue()
 PassRefPtr<SerializedScriptValue> SerializedScriptValue::release()
 {
     RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data, WireData));
-    m_data = String();
+    m_data = String().crossThreadString();
     return result.release();
 }
 
@@ -1123,18 +1123,18 @@ SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, bool&
         didThrow = true;
         return;
     }
-    m_data = StringImpl::adopt(writer.data());
+    m_data = String(StringImpl::adopt(writer.data())).crossThreadString();
 }
 
 SerializedScriptValue::SerializedScriptValue(String data, StringDataMode mode)
 {
     if (mode == WireData)
-        m_data = data;
+        m_data = data.crossThreadString();
     else {
         ASSERT(mode == StringValue);
         Writer writer;
         writer.writeWebCoreString(data);
-        m_data = StringImpl::adopt(writer.data());
+        m_data = String(StringImpl::adopt(writer.data())).crossThreadString();
     }
 }
 
diff --git a/WebCore/bindings/v8/SerializedScriptValue.h b/WebCore/bindings/v8/SerializedScriptValue.h
index 275e5f2..b534a57 100644
--- a/WebCore/bindings/v8/SerializedScriptValue.h
+++ b/WebCore/bindings/v8/SerializedScriptValue.h
@@ -33,11 +33,11 @@
 
 #include "ScriptValue.h"
 #include <v8.h>
-#include <wtf/RefCounted.h>
+#include <wtf/Threading.h>
 
 namespace WebCore {
 
-class SerializedScriptValue : public RefCounted<SerializedScriptValue> {
+class SerializedScriptValue : public ThreadSafeShared<SerializedScriptValue> {
 public:
     static void deserializeAndSetProperty(v8::Handle<v8::Object> object, const char* propertyName,
                                           v8::PropertyAttribute, SerializedScriptValue*);
diff --git a/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp b/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp
index 3dffeb5..fd6f1a5 100644
--- a/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp
@@ -38,6 +38,7 @@
 #include "V8IDBIndex.h"
 #include "V8IDBKey.h"
 #include "V8IDBObjectStore.h"
+#include "V8IDBTransaction.h"
 
 namespace WebCore {
 
@@ -55,14 +56,16 @@ v8::Handle<v8::Value> toV8(IDBAny* impl)
         return toV8(impl->idbCursor());
     case IDBAny::IDBDatabaseType:
         return toV8(impl->idbDatabase());
+    case IDBAny::IDBFactoryType:
+        return toV8(impl->idbFactory());
     case IDBAny::IDBIndexType:
         return toV8(impl->idbIndex());
     case IDBAny::IDBKeyType:
         return toV8(impl->idbKey());
     case IDBAny::IDBObjectStoreType:
         return toV8(impl->idbObjectStore());
-    case IDBAny::IDBFactoryType:
-        return toV8(impl->idbFactory());
+    case IDBAny::IDBTransactionType:
+        return toV8(impl->idbTransaction());
     case IDBAny::SerializedScriptValueType:
         return impl->serializedScriptValue()->deserialize();
     }
diff --git a/WebCore/platform/CrossThreadCopier.cpp b/WebCore/platform/CrossThreadCopier.cpp
index 683ba54..4280486 100644
--- a/WebCore/platform/CrossThreadCopier.cpp
+++ b/WebCore/platform/CrossThreadCopier.cpp
@@ -37,6 +37,7 @@
 #include "ResourceError.h"
 #include "ResourceRequest.h"
 #include "ResourceResponse.h"
+#include "SerializedScriptValue.h"
 
 namespace WebCore {
 
diff --git a/WebCore/storage/IDBAny.cpp b/WebCore/storage/IDBAny.cpp
index 45b166d..3a049c0 100644
--- a/WebCore/storage/IDBAny.cpp
+++ b/WebCore/storage/IDBAny.cpp
@@ -70,6 +70,12 @@ PassRefPtr<IDBDatabase> IDBAny::idbDatabase()
     return m_idbDatabase;
 }
 
+PassRefPtr<IDBFactory> IDBAny::idbFactory()
+{
+    ASSERT(m_type == IDBFactoryType);
+    return m_idbFactory;
+}
+
 PassRefPtr<IDBIndex> IDBAny::idbIndex()
 {
     ASSERT(m_type == IDBIndexType);
@@ -88,10 +94,10 @@ PassRefPtr<IDBObjectStore> IDBAny::idbObjectStore()
     return m_idbObjectStore;
 }
 
-PassRefPtr<IDBFactory> IDBAny::idbFactory()
+PassRefPtr<IDBTransaction> IDBAny::idbTransaction()
 {
-    ASSERT(m_type == IDBFactoryType);
-    return m_idbFactory;
+    ASSERT(m_type == IDBTransactionType);
+    return m_idbTransaction;
 }
 
 PassRefPtr<SerializedScriptValue> IDBAny::serializedScriptValue()
@@ -120,6 +126,13 @@ void IDBAny::set(PassRefPtr<IDBDatabase> value)
     m_idbDatabase = value;
 }
 
+void IDBAny::set(PassRefPtr<IDBFactory> value)
+{
+    ASSERT(m_type == UndefinedType);
+    m_type = IDBFactoryType;
+    m_idbFactory = value;
+}
+
 void IDBAny::set(PassRefPtr<IDBIndex> value)
 {
     ASSERT(m_type == UndefinedType);
@@ -134,18 +147,18 @@ void IDBAny::set(PassRefPtr<IDBKey> value)
     m_idbKey = value;
 }
 
-void IDBAny::set(PassRefPtr<IDBObjectStore> value)
+void IDBAny::set(PassRefPtr<IDBTransaction> value)
 {
     ASSERT(m_type == UndefinedType);
-    m_type = IDBObjectStoreType;
-    m_idbObjectStore = value;
+    m_type = IDBTransactionType;
+    m_idbTransaction = value;
 }
 
-void IDBAny::set(PassRefPtr<IDBFactory> value)
+void IDBAny::set(PassRefPtr<IDBObjectStore> value)
 {
     ASSERT(m_type == UndefinedType);
-    m_type = IDBFactoryType;
-    m_idbFactory = value;
+    m_type = IDBObjectStoreType;
+    m_idbObjectStore = value;
 }
 
 void IDBAny::set(PassRefPtr<SerializedScriptValue> value)
diff --git a/WebCore/storage/IDBAny.h b/WebCore/storage/IDBAny.h
index 9066e13..8e3f83e 100644
--- a/WebCore/storage/IDBAny.h
+++ b/WebCore/storage/IDBAny.h
@@ -36,10 +36,11 @@ namespace WebCore {
 
 class IDBCursor;
 class IDBDatabase;
+class IDBFactory;
 class IDBIndex;
 class IDBKey;
 class IDBObjectStore;
-class IDBFactory;
+class IDBTransaction;
 class SerializedScriptValue;
 
 class IDBAny : public RefCounted<IDBAny> {
@@ -71,6 +72,7 @@ public:
         IDBIndexType,
         IDBKeyType,
         IDBObjectStoreType,
+        IDBTransactionType,
         SerializedScriptValueType
     };
 
@@ -82,6 +84,7 @@ public:
     PassRefPtr<IDBIndex> idbIndex();
     PassRefPtr<IDBKey> idbKey();
     PassRefPtr<IDBObjectStore> idbObjectStore();
+    PassRefPtr<IDBTransaction> idbTransaction();
     PassRefPtr<SerializedScriptValue> serializedScriptValue();
 
     // Set can only be called once.
@@ -92,6 +95,7 @@ public:
     void set(PassRefPtr<IDBIndex>);
     void set(PassRefPtr<IDBKey>);
     void set(PassRefPtr<IDBObjectStore>);
+    void set(PassRefPtr<IDBTransaction>);
     void set(PassRefPtr<SerializedScriptValue>);
 
 private:
@@ -106,6 +110,7 @@ private:
     RefPtr<IDBIndex> m_idbIndex;
     RefPtr<IDBKey> m_idbKey;
     RefPtr<IDBObjectStore> m_idbObjectStore;
+    RefPtr<IDBTransaction> m_idbTransaction;
     RefPtr<SerializedScriptValue> m_serializedScriptValue;
 };
 
diff --git a/WebCore/storage/IDBCallbacks.h b/WebCore/storage/IDBCallbacks.h
index bc48477..e62c085 100644
--- a/WebCore/storage/IDBCallbacks.h
+++ b/WebCore/storage/IDBCallbacks.h
@@ -35,14 +35,16 @@
 #include "IDBIndexBackendInterface.h"
 #include "IDBKey.h"
 #include "IDBObjectStoreBackendInterface.h"
+#include "IDBTransactionBackendInterface.h"
 #include "SerializedScriptValue.h"
-#include <wtf/RefCounted.h>
+#include <wtf/Threading.h>
 
 #if ENABLE(INDEXED_DATABASE)
 
 namespace WebCore {
 
-class IDBCallbacks : public RefCounted<IDBCallbacks> {
+// FIXME: All child classes need to be made threadsafe.
+class IDBCallbacks : public ThreadSafeShared<IDBCallbacks> {
 public:
     virtual ~IDBCallbacks() { }
 
@@ -53,6 +55,7 @@ public:
     virtual void onSuccess(PassRefPtr<IDBIndexBackendInterface>) = 0;
     virtual void onSuccess(PassRefPtr<IDBKey>) = 0;
     virtual void onSuccess(PassRefPtr<IDBObjectStoreBackendInterface>) = 0;
+    virtual void onSuccess(PassRefPtr<IDBTransactionBackendInterface>) = 0;
     virtual void onSuccess(PassRefPtr<SerializedScriptValue>) = 0;
 };
 
diff --git a/WebCore/storage/IDBCursor.cpp b/WebCore/storage/IDBCursor.cpp
index c1c077b..078a551 100644
--- a/WebCore/storage/IDBCursor.cpp
+++ b/WebCore/storage/IDBCursor.cpp
@@ -33,15 +33,20 @@
 #include "IDBCursorBackendInterface.h"
 #include "IDBKey.h"
 #include "IDBRequest.h"
+#include "IDBTransactionBackendInterface.h"
 #include "ScriptExecutionContext.h"
 #include "SerializedScriptValue.h"
 
 namespace WebCore {
 
-IDBCursor::IDBCursor(PassRefPtr<IDBCursorBackendInterface> backend, IDBRequest* request)
+IDBCursor::IDBCursor(PassRefPtr<IDBCursorBackendInterface> backend, IDBRequest* request, IDBTransactionBackendInterface* transaction)
     : m_backend(backend)
     , m_request(request)
+    , m_transaction(transaction)
 {
+    ASSERT(m_backend);
+    ASSERT(m_request);
+    ASSERT(m_transaction);
 }
 
 IDBCursor::~IDBCursor()
@@ -65,7 +70,7 @@ PassRefPtr<IDBAny> IDBCursor::value() const
 
 PassRefPtr<IDBRequest> IDBCursor::update(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
     m_backend->update(value, request);
     return request.release();
 }
@@ -74,14 +79,14 @@ void IDBCursor::continueFunction(PassRefPtr<IDBKey> key)
 {
     // FIXME: We're not using the context from when continue was called, which means the callback
     //        will be on the original context openCursor was called on. Is this right?
-    if (m_request->resetReadyState())
+    if (m_request->resetReadyState(m_transaction.get()))
         m_backend->continueFunction(key, m_request);
     // FIXME: Else throw?
 }
 
 PassRefPtr<IDBRequest> IDBCursor::remove(ScriptExecutionContext* context)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
     m_backend->remove(request);
     return request.release();
 }
diff --git a/WebCore/storage/IDBCursor.h b/WebCore/storage/IDBCursor.h
index 0c438c4..5ad2d61 100644
--- a/WebCore/storage/IDBCursor.h
+++ b/WebCore/storage/IDBCursor.h
@@ -41,6 +41,7 @@ class IDBKey;
 class IDBRequest;
 class ScriptExecutionContext;
 class SerializedScriptValue;
+class IDBTransactionBackendInterface;
 
 class IDBCursor : public RefCounted<IDBCursor> {
 public:
@@ -50,9 +51,9 @@ public:
         PREV = 2,
         PREV_NO_DUPLICATE = 3,
     };
-    static PassRefPtr<IDBCursor> create(PassRefPtr<IDBCursorBackendInterface> backend, IDBRequest* request)
+    static PassRefPtr<IDBCursor> create(PassRefPtr<IDBCursorBackendInterface> backend, IDBRequest* request, IDBTransactionBackendInterface* transaction)
     {
-        return adoptRef(new IDBCursor(backend, request));
+        return adoptRef(new IDBCursor(backend, request, transaction));
     }
     ~IDBCursor();
 
@@ -65,10 +66,11 @@ public:
     PassRefPtr<IDBRequest> remove(ScriptExecutionContext*);
 
 private:
-    explicit IDBCursor(PassRefPtr<IDBCursorBackendInterface>, IDBRequest*);
+    explicit IDBCursor(PassRefPtr<IDBCursorBackendInterface>, IDBRequest*, IDBTransactionBackendInterface*);
 
     RefPtr<IDBCursorBackendInterface> m_backend;
     RefPtr<IDBRequest> m_request;
+    RefPtr<IDBTransactionBackendInterface> m_transaction;
 };
 
 } // namespace WebCore
diff --git a/WebCore/storage/IDBCursorBackendImpl.cpp b/WebCore/storage/IDBCursorBackendImpl.cpp
index 13df5f0..fa2855c 100644
--- a/WebCore/storage/IDBCursorBackendImpl.cpp
+++ b/WebCore/storage/IDBCursorBackendImpl.cpp
@@ -28,6 +28,7 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "CrossThreadTask.h"
 #include "IDBCallbacks.h"
 #include "IDBDatabaseBackendImpl.h"
 #include "IDBDatabaseError.h"
@@ -43,22 +44,24 @@
 
 namespace WebCore {
 
-IDBCursorBackendImpl::IDBCursorBackendImpl(PassRefPtr<IDBObjectStoreBackendImpl> idbObjectStore, PassRefPtr<IDBKeyRange> keyRange, IDBCursor::Direction direction, PassOwnPtr<SQLiteStatement> query)
+IDBCursorBackendImpl::IDBCursorBackendImpl(PassRefPtr<IDBObjectStoreBackendImpl> idbObjectStore, PassRefPtr<IDBKeyRange> keyRange, IDBCursor::Direction direction, PassOwnPtr<SQLiteStatement> query, IDBTransactionBackendInterface* transaction)
     : m_idbObjectStore(idbObjectStore)
     , m_keyRange(keyRange)
     , m_direction(direction)
     , m_query(query)
     , m_isSerializedScriptValueCursor(true)
+    , m_transaction(transaction)
 {
     loadCurrentRow();
 }
 
-IDBCursorBackendImpl::IDBCursorBackendImpl(PassRefPtr<IDBIndexBackendImpl> idbIndex, PassRefPtr<IDBKeyRange> keyRange, IDBCursor::Direction direction, PassOwnPtr<SQLiteStatement> query, bool isSerializedScriptValueCursor)
+IDBCursorBackendImpl::IDBCursorBackendImpl(PassRefPtr<IDBIndexBackendImpl> idbIndex, PassRefPtr<IDBKeyRange> keyRange, IDBCursor::Direction direction, PassOwnPtr<SQLiteStatement> query, bool isSerializedScriptValueCursor, IDBTransactionBackendInterface* transaction)
     : m_idbIndex(idbIndex)
     , m_keyRange(keyRange)
     , m_direction(direction)
     , m_query(query)
     , m_isSerializedScriptValueCursor(isSerializedScriptValueCursor)
+    , m_transaction(transaction)
 {
     loadCurrentRow();
 }
@@ -85,7 +88,16 @@ PassRefPtr<IDBAny> IDBCursorBackendImpl::value() const
     return IDBAny::create(m_currentIDBKeyValue.get());
 }
 
-void IDBCursorBackendImpl::update(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBCallbacks> callbacks)
+void IDBCursorBackendImpl::update(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBCallbacks> prpCallbacks)
+{
+    RefPtr<IDBCursorBackendImpl> cursor = this;
+    RefPtr<SerializedScriptValue> value = prpValue;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!m_transaction->scheduleTask(createCallbackTask(&IDBCursorBackendImpl::updateInternal, cursor, value, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "update must be called in the context of a transaction."));
+}
+
+void IDBCursorBackendImpl::updateInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl> cursor, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBCallbacks> callbacks)
 {
     // FIXME: This method doesn't update indexes. It's dangerous to call in its current state.
     callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Not implemented."));
@@ -93,82 +105,100 @@ void IDBCursorBackendImpl::update(PassRefPtr<SerializedScriptValue> prpValue, Pa
 
     RefPtr<SerializedScriptValue> value = prpValue;
 
-    if (!m_query || m_currentId == InvalidId) {
+    if (!cursor->m_query || cursor->m_currentId == InvalidId) {
         // FIXME: Use the proper error code when it's specced.
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Operation not possible."));
         return;
     }
 
     String sql = "UPDATE ObjectStoreData SET value = ? WHERE id = ?";
-    SQLiteStatement updateQuery(database()->sqliteDatabase(), sql);
+    SQLiteStatement updateQuery(cursor->database()->sqliteDatabase(), sql);
     
     bool ok = updateQuery.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
     updateQuery.bindText(1, value->toWireString());
-    updateQuery.bindInt64(2, m_currentId);
+    updateQuery.bindInt64(2, cursor->m_currentId);
     ok = updateQuery.step() == SQLResultDone;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
 
-    if (m_isSerializedScriptValueCursor)
-        m_currentSerializedScriptValue = value.release();
+    if (cursor->m_isSerializedScriptValueCursor)
+        cursor->m_currentSerializedScriptValue = value.release();
     callbacks->onSuccess();
 }
 
-void IDBCursorBackendImpl::continueFunction(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> callbacks)
+void IDBCursorBackendImpl::continueFunction(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks)
+{
+    RefPtr<IDBCursorBackendImpl> cursor = this;
+    RefPtr<IDBKey> key = prpKey;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!m_transaction->scheduleTask(createCallbackTask(&IDBCursorBackendImpl::continueFunctionInternal, cursor, key, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "continue must be called in the context of a transaction."));
+}
+
+void IDBCursorBackendImpl::continueFunctionInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl> prpCursor, PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> callbacks)
 {
+    RefPtr<IDBCursorBackendImpl> cursor = prpCursor;
     RefPtr<IDBKey> key = prpKey;
     while (true) {
-        if (!m_query || m_query->step() != SQLResultRow) {
-            m_query = 0;
-            m_currentId = InvalidId;
-            m_currentKey = 0;
-            m_currentSerializedScriptValue = 0;
-            m_currentIDBKeyValue = 0;
+        if (!cursor->m_query || cursor->m_query->step() != SQLResultRow) {
+            cursor->m_query = 0;
+            cursor->m_currentId = InvalidId;
+            cursor->m_currentKey = 0;
+            cursor->m_currentSerializedScriptValue = 0;
+            cursor->m_currentIDBKeyValue = 0;
             callbacks->onSuccess();
             return;
         }
 
-        RefPtr<IDBKey> oldKey = m_currentKey;
-        loadCurrentRow();
+        RefPtr<IDBKey> oldKey = cursor->m_currentKey;
+        cursor->loadCurrentRow();
 
         // If a key was supplied, we must loop until we find that key (or hit the end).
-        if (key && !key->isEqual(m_currentKey.get()))
+        if (key && !key->isEqual(cursor->m_currentKey.get()))
             continue;
 
         // If we don't have a uniqueness constraint, we can stop now.
-        if (m_direction == IDBCursor::NEXT || m_direction == IDBCursor::PREV)
+        if (cursor->m_direction == IDBCursor::NEXT || cursor->m_direction == IDBCursor::PREV)
             break;
-        if (!m_currentKey->isEqual(oldKey.get()))
+        if (!cursor->m_currentKey->isEqual(oldKey.get()))
             break;
     }
 
-    callbacks->onSuccess(this);
+    callbacks->onSuccess(cursor.get());
+}
+
+void IDBCursorBackendImpl::remove(PassRefPtr<IDBCallbacks> prpCallbacks)
+{
+    RefPtr<IDBCursorBackendImpl> cursor = this;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!m_transaction->scheduleTask(createCallbackTask(&IDBCursorBackendImpl::removeInternal, cursor, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "remove must be called in the context of a transaction."));
 }
 
-void IDBCursorBackendImpl::remove(PassRefPtr<IDBCallbacks> callbacks)
+void IDBCursorBackendImpl::removeInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl> cursor, PassRefPtr<IDBCallbacks> callbacks)
 {
     // FIXME: This method doesn't update indexes. It's dangerous to call in its current state.
     callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Not implemented."));
     return;
 
-    if (!m_query || m_currentId == InvalidId) {
+    if (!cursor->m_query || cursor->m_currentId == InvalidId) {
         // FIXME: Use the proper error code when it's specced.
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Operation not possible."));
         return;
     }
 
     String sql = "DELETE FROM ObjectStoreData WHERE id = ?";
-    SQLiteStatement deleteQuery(database()->sqliteDatabase(), sql);
+    SQLiteStatement deleteQuery(cursor->database()->sqliteDatabase(), sql);
     
     bool ok = deleteQuery.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
-    deleteQuery.bindInt64(1, m_currentId);
+    deleteQuery.bindInt64(1, cursor->m_currentId);
     ok = deleteQuery.step() == SQLResultDone;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
 
-    m_currentId = InvalidId;
-    m_currentSerializedScriptValue = 0;
-    m_currentIDBKeyValue = 0;
+    cursor->m_currentId = InvalidId;
+    cursor->m_currentSerializedScriptValue = 0;
+    cursor->m_currentIDBKeyValue = 0;
     callbacks->onSuccess();
 }
 
diff --git a/WebCore/storage/IDBCursorBackendImpl.h b/WebCore/storage/IDBCursorBackendImpl.h
index b67ec70..211d38d 100644
--- a/WebCore/storage/IDBCursorBackendImpl.h
+++ b/WebCore/storage/IDBCursorBackendImpl.h
@@ -41,18 +41,19 @@ class IDBDatabaseBackendImpl;
 class IDBIndexBackendImpl;
 class IDBKeyRange;
 class IDBObjectStoreBackendImpl;
+class IDBTransactionBackendInterface;
 class SQLiteStatement;
 class SerializedScriptValue;
 
 class IDBCursorBackendImpl : public IDBCursorBackendInterface {
 public:
-    static PassRefPtr<IDBCursorBackendImpl> create(PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> keyRange, IDBCursor::Direction direction, PassOwnPtr<SQLiteStatement> query)
+    static PassRefPtr<IDBCursorBackendImpl> create(PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> keyRange, IDBCursor::Direction direction, PassOwnPtr<SQLiteStatement> query, IDBTransactionBackendInterface* transaction)
     {
-        return adoptRef(new IDBCursorBackendImpl(objectStore, keyRange, direction, query));
+        return adoptRef(new IDBCursorBackendImpl(objectStore, keyRange, direction, query, transaction));
     }
-    static PassRefPtr<IDBCursorBackendImpl> create(PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> keyRange, IDBCursor::Direction direction, PassOwnPtr<SQLiteStatement> query, bool isSerializedScriptValueCursor)
+    static PassRefPtr<IDBCursorBackendImpl> create(PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> keyRange, IDBCursor::Direction direction, PassOwnPtr<SQLiteStatement> query, bool isSerializedScriptValueCursor, IDBTransactionBackendInterface* transaction)
     {
-        return adoptRef(new IDBCursorBackendImpl(index, keyRange, direction, query, isSerializedScriptValueCursor));
+        return adoptRef(new IDBCursorBackendImpl(index, keyRange, direction, query, isSerializedScriptValueCursor, transaction));
     }
     virtual ~IDBCursorBackendImpl();
 
@@ -64,12 +65,16 @@ public:
     virtual void remove(PassRefPtr<IDBCallbacks>);
 
 private:
-    IDBCursorBackendImpl(PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKeyRange>, IDBCursor::Direction, PassOwnPtr<SQLiteStatement> query);
-    IDBCursorBackendImpl(PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBKeyRange>, IDBCursor::Direction, PassOwnPtr<SQLiteStatement> query, bool isSerializedScriptValueCursor);
+    IDBCursorBackendImpl(PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKeyRange>, IDBCursor::Direction, PassOwnPtr<SQLiteStatement> query, IDBTransactionBackendInterface*);
+    IDBCursorBackendImpl(PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBKeyRange>, IDBCursor::Direction, PassOwnPtr<SQLiteStatement> query, bool isSerializedScriptValueCursor, IDBTransactionBackendInterface*);
 
     void loadCurrentRow();
     IDBDatabaseBackendImpl* database() const;
 
+    static void updateInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl>, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBCallbacks>);
+    static void continueFunctionInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl>, PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>);
+    static void removeInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl>, PassRefPtr<IDBCallbacks>);
+
     static const int64_t InvalidId = -1;
 
     // Only one or the other should be used.
@@ -86,6 +91,8 @@ private:
     // Only one of these will ever be used for each instance. Which depends on m_isSerializedScriptValueCursor.
     RefPtr<SerializedScriptValue> m_currentSerializedScriptValue;
     RefPtr<IDBKey> m_currentIDBKeyValue;
+
+    RefPtr<IDBTransactionBackendInterface> m_transaction;
 };
 
 } // namespace WebCore
diff --git a/WebCore/storage/IDBDatabase.cpp b/WebCore/storage/IDBDatabase.cpp
index 0ea7ac2..4d32213 100644
--- a/WebCore/storage/IDBDatabase.cpp
+++ b/WebCore/storage/IDBDatabase.cpp
@@ -27,6 +27,8 @@
 #include "IDBDatabase.h"
 
 #include "IDBAny.h"
+#include "IDBDatabaseError.h"
+#include "IDBDatabaseException.h"
 #include "IDBFactoryBackendInterface.h"
 #include "IDBObjectStore.h"
 #include "IDBRequest.h"
@@ -48,31 +50,36 @@ IDBDatabase::~IDBDatabase()
 {
 }
 
-PassRefPtr<IDBRequest> IDBDatabase::createObjectStore(ScriptExecutionContext* context, const String& name, const String& keyPath, bool autoIncrement)
+void IDBDatabase::setSetVersionTransaction(IDBTransactionBackendInterface* transaction)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_backend->createObjectStore(name, keyPath, autoIncrement, request);
-    return request;
+    m_setVersionTransaction = transaction;
 }
 
-// FIXME: remove this method.
-PassRefPtr<IDBObjectStore> IDBDatabase::objectStore(const String& name, unsigned short mode)
+// FIXME: Should be synchronous.
+PassRefPtr<IDBRequest> IDBDatabase::createObjectStore(ScriptExecutionContext* context, const String& name, const String& keyPath, bool autoIncrement)
 {
-    RefPtr<IDBObjectStoreBackendInterface> objectStore = m_backend->objectStore(name, mode);
-    ASSERT(objectStore); // FIXME: If this is null, we should raise a NOT_FOUND_ERR.
-    return IDBObjectStore::create(objectStore.release(), 0);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_setVersionTransaction.get());
+    if (!m_setVersionTransaction)
+        request->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "createObjectStore must be called from within a setVersion transaction."));
+    else
+        m_backend->createObjectStore(name, keyPath, autoIncrement, request, m_setVersionTransaction.get());
+    return request;
 }
 
+// FIXME: Should be synchronous.
 PassRefPtr<IDBRequest> IDBDatabase::removeObjectStore(ScriptExecutionContext* context, const String& name)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_backend->removeObjectStore(name, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_setVersionTransaction.get());
+    if (!m_setVersionTransaction)
+        request->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "removeObjectStore must be called from within a setVersion transaction."));
+    else
+        m_backend->removeObjectStore(name, request, m_setVersionTransaction.get());
     return request;
 }
 
 PassRefPtr<IDBRequest> IDBDatabase::setVersion(ScriptExecutionContext* context, const String& version)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), 0);
     m_backend->setVersion(version, request);
     return request;
 }
@@ -89,6 +96,11 @@ PassRefPtr<IDBTransaction> IDBDatabase::transaction(ScriptExecutionContext* cont
     return transaction.release();
 }
 
+void IDBDatabase::close()
+{
+    m_backend->close();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
diff --git a/WebCore/storage/IDBDatabase.h b/WebCore/storage/IDBDatabase.h
index dc70114..cf95317 100644
--- a/WebCore/storage/IDBDatabase.h
+++ b/WebCore/storage/IDBDatabase.h
@@ -50,22 +50,25 @@ public:
     }
     ~IDBDatabase();
 
+    void setSetVersionTransaction(IDBTransactionBackendInterface*);
+
     // Implement the IDL
     String name() const { return m_backend->name(); }
     String version() const { return m_backend->version(); }
     PassRefPtr<DOMStringList> objectStores() const { return m_backend->objectStores(); }
 
     PassRefPtr<IDBRequest> createObjectStore(ScriptExecutionContext*, const String& name, const String& keyPath = String(), bool autoIncrement = false);
-    PassRefPtr<IDBObjectStore> objectStore(const String& name, unsigned short mode = IDBTransaction::READ_ONLY);
     PassRefPtr<IDBRequest> removeObjectStore(ScriptExecutionContext*, const String& name);
     PassRefPtr<IDBRequest> setVersion(ScriptExecutionContext*, const String& version);
     PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext*, DOMStringList* storeNames = 0, unsigned short mode = IDBTransaction::READ_ONLY,
                                            unsigned long timeout = 0); // FIXME: what should the default timeout be?
+    void close();
 
 private:
     IDBDatabase(PassRefPtr<IDBDatabaseBackendInterface>);
 
     RefPtr<IDBDatabaseBackendInterface> m_backend;
+    RefPtr<IDBTransactionBackendInterface> m_setVersionTransaction;
 };
 
 } // namespace WebCore
diff --git a/WebCore/storage/IDBDatabase.idl b/WebCore/storage/IDBDatabase.idl
index 347b3a7..30cdf30 100644
--- a/WebCore/storage/IDBDatabase.idl
+++ b/WebCore/storage/IDBDatabase.idl
@@ -32,14 +32,11 @@ module storage {
         readonly attribute DOMString version;
         readonly attribute DOMStringList objectStores;
 
-
         [CallWith=ScriptExecutionContext] IDBRequest createObjectStore(in DOMString name, in [Optional, ConvertNullToNullString] DOMString keyPath, in [Optional] boolean autoIncrement);
-        // FIXME: objectStore needs to be able to raise an IDBDatabaseException.
-        IDBObjectStore objectStore(in DOMString name, in [Optional] unsigned short mode);
         [CallWith=ScriptExecutionContext] IDBRequest removeObjectStore(in DOMString name);
         [CallWith=ScriptExecutionContext] IDBRequest setVersion(in DOMString version);
         [CallWith=ScriptExecutionContext] IDBTransaction transaction (in [Optional] DOMStringList storeNames, in [Optional] unsigned short mode, in [Optional] unsigned long timeout);
-        // FIXME: Add close.
+        void close();
     };
 
 }
diff --git a/WebCore/storage/IDBDatabaseBackendImpl.cpp b/WebCore/storage/IDBDatabaseBackendImpl.cpp
index b8fe9b5..453f85d 100644
--- a/WebCore/storage/IDBDatabaseBackendImpl.cpp
+++ b/WebCore/storage/IDBDatabaseBackendImpl.cpp
@@ -26,16 +26,18 @@
 #include "config.h"
 #include "IDBDatabaseBackendImpl.h"
 
+#if ENABLE(INDEXED_DATABASE)
+
+#include "CrossThreadTask.h"
 #include "DOMStringList.h"
 #include "IDBDatabaseException.h"
 #include "IDBObjectStoreBackendImpl.h"
+#include "IDBTransactionBackendInterface.h"
 #include "IDBTransactionCoordinator.h"
 #include "SQLiteDatabase.h"
 #include "SQLiteStatement.h"
 #include "SQLiteTransaction.h"
 
-#if ENABLE(INDEXED_DATABASE)
-
 namespace WebCore {
 
 static bool extractMetaData(SQLiteDatabase* sqliteDatabase, const String& expectedName, String& foundDescription, String& foundVersion)
@@ -125,14 +127,22 @@ PassRefPtr<DOMStringList> IDBDatabaseBackendImpl::objectStores() const
     return objectStoreNames.release();
 }
 
-void IDBDatabaseBackendImpl::createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks> callbacks)
+void IDBDatabaseBackendImpl::createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction)
 {
-    if (m_objectStores.contains(name)) {
+    RefPtr<IDBDatabaseBackendImpl> database = this;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::createObjectStoreInternal, database, name, keyPath, autoIncrement, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "createObjectStore must be called from within a setVersion transaction."));
+}
+
+void IDBDatabaseBackendImpl::createObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks> callbacks)
+{
+    if (database->m_objectStores.contains(name)) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "An objectStore with that name already exists."));
         return;
     }
 
-    SQLiteStatement insert(sqliteDatabase(), "INSERT INTO ObjectStores (name, keyPath, doAutoIncrement) VALUES (?, ?, ?)");
+    SQLiteStatement insert(database->sqliteDatabase(), "INSERT INTO ObjectStores (name, keyPath, doAutoIncrement) VALUES (?, ?, ?)");
     bool ok = insert.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
     insert.bindText(1, name);
@@ -140,11 +150,11 @@ void IDBDatabaseBackendImpl::createObjectStore(const String& name, const String&
     insert.bindInt(3, static_cast<int>(autoIncrement));
     ok = insert.step() == SQLResultDone;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
-    int64_t id = sqliteDatabase().lastInsertRowID();
+    int64_t id = database->sqliteDatabase().lastInsertRowID();
 
-    RefPtr<IDBObjectStoreBackendImpl> objectStore = IDBObjectStoreBackendImpl::create(this, id, name, keyPath, autoIncrement);
+    RefPtr<IDBObjectStoreBackendImpl> objectStore = IDBObjectStoreBackendImpl::create(database.get(), id, name, keyPath, autoIncrement);
     ASSERT(objectStore->name() == name);
-    m_objectStores.set(name, objectStore);
+    database->m_objectStores.set(name, objectStore);
     callbacks->onSuccess(objectStore.get());
 }
 
@@ -166,31 +176,46 @@ static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id)
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
 }
 
-void IDBDatabaseBackendImpl::removeObjectStore(const String& name, PassRefPtr<IDBCallbacks> callbacks)
+void IDBDatabaseBackendImpl::removeObjectStore(const String& name, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction)
+{
+    RefPtr<IDBDatabaseBackendImpl> database = this;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::removeObjectStoreInternal, database, name, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "removeObjectStore must be called from within a setVersion transaction."));
+}
+
+void IDBDatabaseBackendImpl::removeObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, const String& name, PassRefPtr<IDBCallbacks> callbacks)
 {
-    RefPtr<IDBObjectStoreBackendImpl> objectStore = m_objectStores.get(name);
+    RefPtr<IDBObjectStoreBackendImpl> objectStore = database->m_objectStores.get(name);
     if (!objectStore) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "No objectStore with that name exists."));
         return;
     }
 
-    SQLiteTransaction transaction(sqliteDatabase());
-    transaction.begin();
-    doDelete(sqliteDatabase(), "DELETE FROM ObjectStores WHERE id = ?", objectStore->id());
-    doDelete(sqliteDatabase(), "DELETE FROM ObjectStoreData WHERE objectStoreId = ?", objectStore->id());
-    doDelete(sqliteDatabase(), "DELETE FROM IndexData WHERE indexId IN (SELECT id FROM Indexes WHERE objectStoreId = ?)", objectStore->id());
-    doDelete(sqliteDatabase(), "DELETE FROM Indexes WHERE objectStoreId = ?", objectStore->id());
-    transaction.commit();
+    doDelete(database->sqliteDatabase(), "DELETE FROM ObjectStores WHERE id = ?", objectStore->id());
+    doDelete(database->sqliteDatabase(), "DELETE FROM ObjectStoreData WHERE objectStoreId = ?", objectStore->id());
+    doDelete(database->sqliteDatabase(), "DELETE FROM IndexData WHERE indexId IN (SELECT id FROM Indexes WHERE objectStoreId = ?)", objectStore->id());
+    doDelete(database->sqliteDatabase(), "DELETE FROM Indexes WHERE objectStoreId = ?", objectStore->id());
 
-    m_objectStores.remove(name);
+    database->m_objectStores.remove(name);
     callbacks->onSuccess();
 }
 
-void IDBDatabaseBackendImpl::setVersion(const String& version, PassRefPtr<IDBCallbacks> callbacks)
+void IDBDatabaseBackendImpl::setVersion(const String& version, PassRefPtr<IDBCallbacks> prpCallbacks)
 {
-    m_version = version;
-    setMetaData(m_sqliteDatabase.get(), m_name, m_description, m_version);
-    callbacks->onSuccess();
+    RefPtr<IDBDatabaseBackendImpl> database = this;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    RefPtr<DOMStringList> objectStores = DOMStringList::create();
+    RefPtr<IDBTransactionBackendInterface> transaction = m_transactionCoordinator->createTransaction(objectStores.get(), IDBTransaction::VERSION_CHANGE, 0, this);
+    if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::setVersionInternal, database, version, callbacks, transaction)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "setVersion must be called from within a setVersion transaction."));
+}
+
+void IDBDatabaseBackendImpl::setVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, const String& version, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
+{
+    database->m_version = version;
+    setMetaData(database->m_sqliteDatabase.get(), database->m_name, database->m_description, database->m_version);
+    callbacks->onSuccess(transaction);
 }
 
 PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(DOMStringList* objectStores, unsigned short mode, unsigned long timeout)
@@ -198,6 +223,11 @@ PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(D
     return m_transactionCoordinator->createTransaction(objectStores, mode, timeout, this);
 }
 
+void IDBDatabaseBackendImpl::close()
+{
+    // FIXME: Implement.
+}
+
 void IDBDatabaseBackendImpl::loadObjectStores()
 {
     SQLiteStatement objectStoresQuery(sqliteDatabase(), "SELECT id, name, keyPath, doAutoIncrement FROM ObjectStores");
diff --git a/WebCore/storage/IDBDatabaseBackendImpl.h b/WebCore/storage/IDBDatabaseBackendImpl.h
index 7e08ad6..b576fa5 100644
--- a/WebCore/storage/IDBDatabaseBackendImpl.h
+++ b/WebCore/storage/IDBDatabaseBackendImpl.h
@@ -50,17 +50,17 @@ public:
     void setDescription(const String& description);
     SQLiteDatabase& sqliteDatabase() const { return *m_sqliteDatabase.get(); }
 
-    // Implements IDBDatabase
     virtual String name() const { return m_name; }
     virtual String description() const { return m_description; }
     virtual String version() const { return m_version; }
     virtual PassRefPtr<DOMStringList> objectStores() const;
 
-    virtual void createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks>);
+    virtual void createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
     virtual PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name, unsigned short mode);
-    virtual void removeObjectStore(const String& name, PassRefPtr<IDBCallbacks>);
+    virtual void removeObjectStore(const String& name, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
     virtual void setVersion(const String& version, PassRefPtr<IDBCallbacks>);
     virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* storeNames, unsigned short mode, unsigned long timeout);
+    virtual void close();
 
     IDBTransactionCoordinator* transactionCoordinator() const { return m_transactionCoordinator.get(); }
 
@@ -69,6 +69,10 @@ private:
 
     void loadObjectStores();
 
+    static void createObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks>);
+    static void removeObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, const String& name, PassRefPtr<IDBCallbacks>);
+    static void setVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, const String& version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>);
+
     OwnPtr<SQLiteDatabase> m_sqliteDatabase;
     String m_name;
     String m_description;
diff --git a/WebCore/storage/IDBDatabaseBackendInterface.h b/WebCore/storage/IDBDatabaseBackendInterface.h
index a2e042a..c01dadf 100644
--- a/WebCore/storage/IDBDatabaseBackendInterface.h
+++ b/WebCore/storage/IDBDatabaseBackendInterface.h
@@ -54,12 +54,12 @@ public:
     virtual String version() const = 0;
     virtual PassRefPtr<DOMStringList> objectStores() const = 0;
 
-    virtual void createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks>) = 0;
+    virtual void createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
     virtual PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name, unsigned short mode) = 0;
-    virtual void removeObjectStore(const String& name, PassRefPtr<IDBCallbacks>) = 0;
+    virtual void removeObjectStore(const String& name, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
     virtual void setVersion(const String& version, PassRefPtr<IDBCallbacks>) = 0;
     virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* storeNames, unsigned short mode, unsigned long timeout) = 0;
-    // FIXME: Add close.
+    virtual void close() = 0;
 };
 
 } // namespace WebCore
diff --git a/WebCore/storage/IDBFactory.cpp b/WebCore/storage/IDBFactory.cpp
index 06c06ea..e1c8c07 100644
--- a/WebCore/storage/IDBFactory.cpp
+++ b/WebCore/storage/IDBFactory.cpp
@@ -67,7 +67,7 @@ PassRefPtr<IDBRequest> IDBFactory::open(ScriptExecutionContext* context, const S
     if (!document->frame() || !document->page())
         return 0;
 
-    RefPtr<IDBRequest> request = IDBRequest::create(document, IDBAny::create(this));
+    RefPtr<IDBRequest> request = IDBRequest::create(document, IDBAny::create(this), 0);
     m_factoryBackend->open(name, description, request, document->securityOrigin(), document->frame(), document->page()->group().groupSettings()->indexedDBDatabasePath());
     return request;
 }
diff --git a/WebCore/storage/IDBIndex.cpp b/WebCore/storage/IDBIndex.cpp
index 5cd12dd..8d78466 100644
--- a/WebCore/storage/IDBIndex.cpp
+++ b/WebCore/storage/IDBIndex.cpp
@@ -33,12 +33,16 @@
 #include "IDBKey.h"
 #include "IDBKeyRange.h"
 #include "IDBRequest.h"
+#include "IDBTransactionBackendInterface.h"
 
 namespace WebCore {
 
-IDBIndex::IDBIndex(PassRefPtr<IDBIndexBackendInterface> backend)
+IDBIndex::IDBIndex(PassRefPtr<IDBIndexBackendInterface> backend, IDBTransactionBackendInterface* transaction)
     : m_backend(backend)
+    , m_transaction(transaction)
 {
+    ASSERT(m_backend);
+    ASSERT(m_transaction);
 }
 
 IDBIndex::~IDBIndex()
@@ -47,29 +51,29 @@ IDBIndex::~IDBIndex()
 
 PassRefPtr<IDBRequest> IDBIndex::openObjectCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, unsigned short direction)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_backend->openObjectCursor(keyRange, direction, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_backend->openObjectCursor(keyRange, direction, request, m_transaction.get());
     return request;
 }
 
 PassRefPtr<IDBRequest> IDBIndex::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, unsigned short direction)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_backend->openCursor(keyRange, direction, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_backend->openCursor(keyRange, direction, request, m_transaction.get());
     return request;
 }
 
 PassRefPtr<IDBRequest> IDBIndex::getObject(ScriptExecutionContext* context, PassRefPtr<IDBKey> key)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_backend->getObject(key, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_backend->getObject(key, request, m_transaction.get());
     return request;
 }
 
 PassRefPtr<IDBRequest> IDBIndex::get(ScriptExecutionContext* context, PassRefPtr<IDBKey> key)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_backend->get(key, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_backend->get(key, request, m_transaction.get());
     return request;
 }
 
diff --git a/WebCore/storage/IDBIndex.h b/WebCore/storage/IDBIndex.h
index 45fcfa1..b258077 100644
--- a/WebCore/storage/IDBIndex.h
+++ b/WebCore/storage/IDBIndex.h
@@ -37,9 +37,9 @@ namespace WebCore {
 
 class IDBIndex : public RefCounted<IDBIndex> {
 public:
-    static PassRefPtr<IDBIndex> create(PassRefPtr<IDBIndexBackendInterface> backend)
+    static PassRefPtr<IDBIndex> create(PassRefPtr<IDBIndexBackendInterface> backend, IDBTransactionBackendInterface* transaction)
     {
-        return adoptRef(new IDBIndex(backend));
+        return adoptRef(new IDBIndex(backend, transaction));
     }
     ~IDBIndex();
 
@@ -55,9 +55,10 @@ public:
     PassRefPtr<IDBRequest> get(ScriptExecutionContext*, PassRefPtr<IDBKey>);
 
 private:
-    IDBIndex(PassRefPtr<IDBIndexBackendInterface>);
+    IDBIndex(PassRefPtr<IDBIndexBackendInterface>, IDBTransactionBackendInterface* transaction);
 
     RefPtr<IDBIndexBackendInterface> m_backend;
+    RefPtr<IDBTransactionBackendInterface> m_transaction;
 };
 
 } // namespace WebCore
diff --git a/WebCore/storage/IDBIndexBackendImpl.cpp b/WebCore/storage/IDBIndexBackendImpl.cpp
index 6f698c6..18e24b2 100644
--- a/WebCore/storage/IDBIndexBackendImpl.cpp
+++ b/WebCore/storage/IDBIndexBackendImpl.cpp
@@ -28,6 +28,7 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "CrossThreadTask.h"
 #include "IDBCallbacks.h"
 #include "IDBCursorBackendImpl.h"
 #include "IDBDatabaseBackendImpl.h"
@@ -58,7 +59,7 @@ String IDBIndexBackendImpl::storeName()
     return m_objectStore->name();
 }
 
-static void openCursorInternal(SQLiteDatabase& database, IDBIndexBackendImpl* index, IDBKeyRange* range, unsigned short untypedDirection, bool objectCursor, IDBCallbacks* callbacks)
+void IDBIndexBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKeyRange> range, unsigned short untypedDirection, bool objectCursor, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
 {
     // Several files depend on this order of selects.
     String sql = String("SELECT IndexData.id, IndexData.keyString, IndexData.keyDate, IndexData.keyNumber, ")
@@ -80,7 +81,7 @@ static void openCursorInternal(SQLiteDatabase& database, IDBIndexBackendImpl* in
     else
         sql += "IndexData.keyString DESC, IndexData.keyDate DESC, IndexData.keyNumber DESC, IndexData.id DESC";
 
-    OwnPtr<SQLiteStatement> query = adoptPtr(new SQLiteStatement(database, sql));
+    OwnPtr<SQLiteStatement> query = adoptPtr(new SQLiteStatement(index->sqliteDatabase(), sql));
     bool ok = query->prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
@@ -96,32 +97,42 @@ static void openCursorInternal(SQLiteDatabase& database, IDBIndexBackendImpl* in
         return;
     }
 
-    RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(index, range, direction, query.release(), objectCursor);
+    RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(index, range, direction, query.release(), objectCursor, transaction.get());
     callbacks->onSuccess(cursor.release());
 }
 
-void IDBIndexBackendImpl::openObjectCursor(PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks)
+void IDBIndexBackendImpl::openObjectCursor(PassRefPtr<IDBKeyRange> prpKeyRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr)
 {
-    openCursorInternal(sqliteDatabase(), this, keyRange.get(), direction, true, callbacks.get());
+    RefPtr<IDBIndexBackendImpl> index = this;
+    RefPtr<IDBKeyRange> keyRange = prpKeyRange;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
+    if (!transaction->scheduleTask(createCallbackTask(&openCursorInternal, index, keyRange, direction, true, callbacks, transaction)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "Get must be called in the context of a transaction."));
 }
 
-void IDBIndexBackendImpl::openCursor(PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks)
+void IDBIndexBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpKeyRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr)
 {
-    openCursorInternal(sqliteDatabase(), this, keyRange.get(), direction, false, callbacks.get());
+    RefPtr<IDBIndexBackendImpl> index = this;
+    RefPtr<IDBKeyRange> keyRange = prpKeyRange;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
+    if (!transaction->scheduleTask(createCallbackTask(&openCursorInternal, index, keyRange, direction, false, callbacks, transaction)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "Get must be called in the context of a transaction."));
 }
 
-static void getInternal(SQLiteDatabase& database, int64 id, IDBKey* key, bool getObject, IDBCallbacks* callbacks)
+void IDBIndexBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl> index, PassRefPtr<IDBKey> key, bool getObject, PassRefPtr<IDBCallbacks> callbacks)
 {
     String sql = String("SELECT ")
                  + (getObject ? "ObjectStoreData.value " : "ObjectStoreData.keyString, ObjectStoreData.keyDate, ObjectStoreData.keyNumber ")
                  + "FROM IndexData INNER JOIN ObjectStoreData ON IndexData.objectStoreDataId = ObjectStoreData.id "
                  + "WHERE IndexData.indexId = ?  AND  " + key->whereSyntax("IndexData.")
                  + "ORDER BY IndexData.id LIMIT 1"; // Order by insertion order when all else fails.
-    SQLiteStatement query(database, sql);
+    SQLiteStatement query(index->sqliteDatabase(), sql);
     bool ok = query.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
-    query.bindInt64(1, id);
+    query.bindInt64(1, index->id());
     key->bind(query, 2);
     if (query.step() != SQLResultRow) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the index."));
@@ -135,14 +146,22 @@ static void getInternal(SQLiteDatabase& database, int64 id, IDBKey* key, bool ge
     ASSERT(query.step() != SQLResultRow);
 }
 
-void IDBIndexBackendImpl::getObject(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
+void IDBIndexBackendImpl::getObject(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction)
 {
-    getInternal(sqliteDatabase(), m_id, key.get(), true, callbacks.get());
+    RefPtr<IDBIndexBackendImpl> index = this;
+    RefPtr<IDBKey> key = prpKey;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!transaction->scheduleTask(createCallbackTask(&getInternal, index, key, true, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "Get must be called in the context of a transaction."));
 }
 
-void IDBIndexBackendImpl::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
+void IDBIndexBackendImpl::get(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction)
 {
-    getInternal(sqliteDatabase(), m_id, key.get(), false, callbacks.get());
+    RefPtr<IDBIndexBackendImpl> index = this;
+    RefPtr<IDBKey> key = prpKey;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!transaction->scheduleTask(createCallbackTask(&getInternal, index, key, false, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "Get must be called in the context of a transaction."));
 }
 
 static String whereClause(IDBKey* key)
diff --git a/WebCore/storage/IDBIndexBackendImpl.h b/WebCore/storage/IDBIndexBackendImpl.h
index a98ed2a..2d06c69 100644
--- a/WebCore/storage/IDBIndexBackendImpl.h
+++ b/WebCore/storage/IDBIndexBackendImpl.h
@@ -35,6 +35,7 @@ namespace WebCore {
 class IDBKey;
 class IDBObjectStoreBackendImpl;
 class SQLiteDatabase;
+class ScriptExecutionContext;
 
 class IDBIndexBackendImpl : public IDBIndexBackendInterface {
 public:
@@ -53,10 +54,10 @@ public:
     virtual String keyPath() { return m_keyPath; }
     virtual bool unique() { return m_unique; }
 
-    virtual void openObjectCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>);
-    virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>);
-    virtual void getObject(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>);
-    virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>);
+    virtual void openObjectCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    virtual void getObject(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
 
     IDBObjectStoreBackendImpl* objectStore() const { return m_objectStore.get(); }
 
@@ -65,6 +66,9 @@ private:
 
     SQLiteDatabase& sqliteDatabase() const;
 
+    static void openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBKeyRange>, unsigned short direction, bool objectCursor, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>);
+    static void getInternal(ScriptExecutionContext*, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBKey>, bool getObject, PassRefPtr<IDBCallbacks>);
+
     RefPtr<IDBObjectStoreBackendImpl> m_objectStore;
 
     int64_t m_id;
diff --git a/WebCore/storage/IDBIndexBackendInterface.h b/WebCore/storage/IDBIndexBackendInterface.h
index ff2316f..fa395a0 100644
--- a/WebCore/storage/IDBIndexBackendInterface.h
+++ b/WebCore/storage/IDBIndexBackendInterface.h
@@ -36,6 +36,7 @@ namespace WebCore {
 class IDBCallbacks;
 class IDBKey;
 class IDBKeyRange;
+class IDBTransactionBackendInterface;
 
 class IDBIndexBackendInterface : public ThreadSafeShared<IDBIndexBackendInterface> {
 public:
@@ -46,10 +47,10 @@ public:
     virtual String keyPath() = 0;
     virtual bool unique() = 0;
 
-    virtual void openObjectCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>) = 0;
-    virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>) = 0;
-    virtual void getObject(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>) = 0;
-    virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>) = 0;
+    virtual void openObjectCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
+    virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
+    virtual void getObject(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
+    virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
 };
 
 } // namespace WebCore
diff --git a/WebCore/storage/IDBKey.cpp b/WebCore/storage/IDBKey.cpp
index 3eec36c..d0f3c2b 100644
--- a/WebCore/storage/IDBKey.cpp
+++ b/WebCore/storage/IDBKey.cpp
@@ -46,7 +46,7 @@ IDBKey::IDBKey(int32_t number)
 
 IDBKey::IDBKey(const String& string)
     : m_type(StringType)
-    , m_string(string)
+    , m_string(string.crossThreadString())
 {
 }
 
diff --git a/WebCore/storage/IDBKey.h b/WebCore/storage/IDBKey.h
index 3175e7e..0303a38 100644
--- a/WebCore/storage/IDBKey.h
+++ b/WebCore/storage/IDBKey.h
@@ -26,17 +26,18 @@
 #ifndef IDBKey_h
 #define IDBKey_h
 
+#if ENABLE(INDEXED_DATABASE)
+
 #include "PlatformString.h"
 #include <wtf/Forward.h>
-
-#if ENABLE(INDEXED_DATABASE)
+#include <wtf/Threading.h>
 
 namespace WebCore {
 
 class SQLiteStatement;
 
 // FIXME: Add dates.
-class IDBKey : public RefCounted<IDBKey> {
+class IDBKey : public ThreadSafeShared<IDBKey> {
 public:
     static PassRefPtr<IDBKey> create()
     {
@@ -82,6 +83,9 @@ public:
     int bind(SQLiteStatement& query, int column) const;
     void bindWithNulls(SQLiteStatement& query, int baseColumn) const;
 
+    using ThreadSafeShared<IDBKey>::ref;
+    using ThreadSafeShared<IDBKey>::deref;
+
 private:
     IDBKey();
     explicit IDBKey(int32_t);
diff --git a/WebCore/storage/IDBKeyRange.h b/WebCore/storage/IDBKeyRange.h
index 4621a50..d246ebc 100644
--- a/WebCore/storage/IDBKeyRange.h
+++ b/WebCore/storage/IDBKeyRange.h
@@ -30,11 +30,11 @@
 
 #include "IDBKey.h"
 #include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
+#include <wtf/Threading.h>
 
 namespace WebCore {
 
-class IDBKeyRange : public RefCounted<IDBKeyRange> {
+class IDBKeyRange : public ThreadSafeShared<IDBKeyRange> {
 public:
     // Keep in sync with what's in the .idl file.
     enum Flags {
diff --git a/WebCore/storage/IDBObjectStore.cpp b/WebCore/storage/IDBObjectStore.cpp
index 4c5cf34..a81e17f 100644
--- a/WebCore/storage/IDBObjectStore.cpp
+++ b/WebCore/storage/IDBObjectStore.cpp
@@ -43,6 +43,8 @@ IDBObjectStore::IDBObjectStore(PassRefPtr<IDBObjectStoreBackendInterface> idbObj
     : m_objectStore(idbObjectStore)
     , m_transaction(transaction)
 {
+    ASSERT(m_objectStore);
+    ASSERT(m_transaction);
     // We pass a reference to this object before it can be adopted.
     relaxAdoptionRequirement();
 }
@@ -71,29 +73,29 @@ PassRefPtr<IDBRequest> IDBObjectStore::get(ScriptExecutionContext* context, Pass
 
 PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_objectStore->put(value, key, true, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_objectStore->put(value, key, true, request, m_transaction.get());
     return request;
 }
 
 PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_objectStore->put(value, key, false, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_objectStore->put(value, key, false, request, m_transaction.get());
     return request;
 }
 
 PassRefPtr<IDBRequest> IDBObjectStore::remove(ScriptExecutionContext* context, PassRefPtr<IDBKey> key)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_objectStore->remove(key, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_objectStore->remove(key, request, m_transaction.get());
     return request;
 }
 
 PassRefPtr<IDBRequest> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const String& keyPath, bool unique)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_objectStore->createIndex(name, keyPath, unique, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_objectStore->createIndex(name, keyPath, unique, request, m_transaction.get());
     return request;
 }
 
@@ -103,20 +105,20 @@ PassRefPtr<IDBIndex> IDBObjectStore::index(const String& name)
     RefPtr<IDBIndexBackendInterface> index = m_objectStore->index(name);
     if (!index)
         return 0;
-    return IDBIndex::create(index.release());
+    return IDBIndex::create(index.release(), m_transaction.get());
 }
 
 PassRefPtr<IDBRequest> IDBObjectStore::removeIndex(ScriptExecutionContext* context, const String& name)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_objectStore->removeIndex(name, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_objectStore->removeIndex(name, request, m_transaction.get());
     return request;
 }
 
 PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, unsigned short direction)
 {
-    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this));
-    m_objectStore->openCursor(range, direction, request);
+    RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
+    m_objectStore->openCursor(range, direction, request, m_transaction.get());
     return request.release();
 }
 
diff --git a/WebCore/storage/IDBObjectStore.idl b/WebCore/storage/IDBObjectStore.idl
index ccd0311..c8aa35d 100644
--- a/WebCore/storage/IDBObjectStore.idl
+++ b/WebCore/storage/IDBObjectStore.idl
@@ -28,21 +28,18 @@ module storage {
     interface [
         Conditional=INDEXED_DATABASE
     ] IDBObjectStore {
+        readonly attribute DOMString name;
+        readonly attribute [ConvertNullStringTo=Null] DOMString keyPath;
+        readonly attribute DOMStringList indexNames;
+
         // FIXME: Many of these should raise on certain errors.
         [CallWith=ScriptExecutionContext] IDBRequest get(in IDBKey key);        
         [CallWith=ScriptExecutionContext] IDBRequest add(in SerializedScriptValue value, in [Optional] IDBKey key);
         [CallWith=ScriptExecutionContext] IDBRequest put(in SerializedScriptValue value, in [Optional] IDBKey key);
         [CallWith=ScriptExecutionContext] IDBRequest remove(in IDBKey key);
-        // FIXME: write openCursor
         [CallWith=ScriptExecutionContext] IDBRequest createIndex(in DOMString name, in [ConvertNullToNullString] DOMString keyPath, in [Optional] boolean unique);
-        // FIXME: This needs to raise an IDBDatabaseException on errors.
         IDBIndex index(in DOMString name);
         [CallWith=ScriptExecutionContext] IDBRequest removeIndex(in DOMString name);
-
         [CallWith=ScriptExecutionContext] IDBRequest openCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction);
-
-        readonly attribute DOMString name;
-        readonly attribute [ConvertNullStringTo=Null] DOMString keyPath;
-        readonly attribute DOMStringList indexNames;
     };
 }
diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.cpp b/WebCore/storage/IDBObjectStoreBackendImpl.cpp
index 18d6b0c..50a2dec 100644
--- a/WebCore/storage/IDBObjectStoreBackendImpl.cpp
+++ b/WebCore/storage/IDBObjectStoreBackendImpl.cpp
@@ -26,6 +26,9 @@
 #include "config.h"
 #include "IDBObjectStoreBackendImpl.h"
 
+#if ENABLE(INDEXED_DATABASE)
+
+#include "CrossThreadTask.h"
 #include "DOMStringList.h"
 #include "IDBBindingUtilities.h"
 #include "IDBCallbacks.h"
@@ -33,6 +36,7 @@
 #include "IDBDatabaseBackendImpl.h"
 #include "IDBDatabaseException.h"
 #include "IDBIndexBackendImpl.h"
+#include "IDBKey.h"
 #include "IDBKeyPath.h"
 #include "IDBKeyPathBackendImpl.h"
 #include "IDBKeyRange.h"
@@ -42,37 +46,8 @@
 #include "SQLiteStatement.h"
 #include "SQLiteTransaction.h"
 
-#if ENABLE(INDEXED_DATABASE)
-
 namespace WebCore {
 
-template <class T, class Method, class Param1, class Param2>
-class IDBTask : public ScriptExecutionContext::Task {
-public:
-    IDBTask(T* obj, Method method, const Param1& param1, const Param2& param2)
-        : m_obj(obj), m_method(method), m_param1(param1), m_param2(param2) 
-    {
-    }
-
-    virtual void performTask(ScriptExecutionContext*) 
-    {
-        if (m_obj)
-            (m_obj->*m_method)(m_param1, m_param2);
-    }
-
-private:
-    T* m_obj;
-    Method m_method;
-    Param1 m_param1;
-    Param2 m_param2;
-};
-
-template <class T, class Method, class Param1, class Param2>
-PassOwnPtr<ScriptExecutionContext::Task> createTask(T* object, Method method, const Param1& param1, const Param2& param2)
-{
-    return adoptPtr(new IDBTask<T, Method, Param1, Param2>(object, method, param1, param2));
-}
-
 IDBObjectStoreBackendImpl::~IDBObjectStoreBackendImpl()
 {
 }
@@ -106,19 +81,22 @@ static void bindWhereClause(SQLiteStatement& query, int64_t id, IDBKey* key)
     key->bind(query, 2);
 }
 
-void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
+void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction)
 {
-    if (!transaction->scheduleTask(createTask(this, &IDBObjectStoreBackendImpl::getInternal, key, callbacks)))
-        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "Get must be called in the context of a transaction."));
+    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
+    RefPtr<IDBKey> key = prpKey;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::getInternal, objectStore, key, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "get must be called in the context of a transaction."));
 }
 
-void IDBObjectStoreBackendImpl::getInternal(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreBackendImpl::getInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
 {
-    SQLiteStatement query(sqliteDatabase(), "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData " + whereClause(key.get()));
+    SQLiteStatement query(objectStore->sqliteDatabase(), "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData " + whereClause(key.get()));
     bool ok = query.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
-    bindWhereClause(query, m_id, key.get());
+    bindWhereClause(query, objectStore->id(), key.get());
     if (query.step() != SQLResultRow) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
         return;
@@ -185,17 +163,27 @@ static void putIndexData(SQLiteDatabase& db, IDBKey* key, int64_t indexId, int64
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 }
 
-void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction)
 {
+    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
     RefPtr<SerializedScriptValue> value = prpValue;
     RefPtr<IDBKey> key = prpKey;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::putInternal, objectStore, value, key, addOnly, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "put must be called in the context of a transaction."));
+}
 
-    if (!m_keyPath.isNull()) {
+void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> callbacks)
+{
+    RefPtr<SerializedScriptValue> value = prpValue;
+    RefPtr<IDBKey> key = prpKey;
+
+    if (!objectStore->m_keyPath.isNull()) {
         if (key) {
             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "A key was supplied for an objectStore that has a keyPath."));
             return;
         }
-        key = fetchKeyFromKeyPath(value.get(), m_keyPath);
+        key = fetchKeyFromKeyPath(value.get(), objectStore->m_keyPath);
         if (!key) {
             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from the keyPath."));
             return;
@@ -206,7 +194,7 @@ void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue,
     }
 
     Vector<RefPtr<IDBKey> > indexKeys;
-    for (IndexMap::iterator it = m_indexes.begin(); it != m_indexes.end(); ++it) {
+    for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
         RefPtr<IDBKey> key = fetchKeyFromKeyPath(value.get(), it->second->keyPath());
         if (!key) {
             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from an index's keyPath."));
@@ -219,11 +207,11 @@ void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue,
         indexKeys.append(key.release());
     }
 
-    SQLiteStatement getQuery(sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key.get()));
+    SQLiteStatement getQuery(objectStore->sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key.get()));
     bool ok = getQuery.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
-    bindWhereClause(getQuery, m_id, key.get());
+    bindWhereClause(getQuery, objectStore->id(), key.get());
     bool isExistingValue = getQuery.step() == SQLResultRow;
     if (addOnly && isExistingValue) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
@@ -233,22 +221,31 @@ void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue,
     // Before this point, don't do any mutation.  After this point, don't error out.
 
     int64_t dataRowId = isExistingValue ? getQuery.getColumnInt(0) : -1;
-    putObjectStoreData(sqliteDatabase(), key.get(), value.get(), m_id, &dataRowId);
+    putObjectStoreData(objectStore->sqliteDatabase(), key.get(), value.get(), objectStore->id(), &dataRowId);
 
     int i = 0;
-    for (IndexMap::iterator it = m_indexes.begin(); it != m_indexes.end(); ++it, ++i)
-        putIndexData(sqliteDatabase(), indexKeys[i].get(), it->second->id(), dataRowId);
+    for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it, ++i)
+        putIndexData(objectStore->sqliteDatabase(), indexKeys[i].get(), it->second->id(), dataRowId);
 
     callbacks->onSuccess(key.get());
 }
 
-void IDBObjectStoreBackendImpl::remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreBackendImpl::remove(PassRefPtr<IDBKey> prpKey, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction)
+{
+    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
+    RefPtr<IDBKey> key = prpKey;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::removeInternal, objectStore, key, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "remove must be called in the context of a transaction."));
+}
+
+void IDBObjectStoreBackendImpl::removeInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
 {
-    SQLiteStatement query(sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key.get()));
+    SQLiteStatement query(objectStore->sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key.get()));
     bool ok = query.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
-    bindWhereClause(query, m_id, key.get());
+    bindWhereClause(query, objectStore->id(), key.get());
     if (query.step() != SQLResultDone) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
         return;
@@ -257,27 +254,35 @@ void IDBObjectStoreBackendImpl::remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCal
     callbacks->onSuccess();
 }
 
-void IDBObjectStoreBackendImpl::createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreBackendImpl::createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction)
 {
-    if (m_indexes.contains(name)) {
+    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::createIndexInternal, objectStore, name, keyPath, unique, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "createIndex must be called in the context of a transaction."));
+}
+
+void IDBObjectStoreBackendImpl::createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks> callbacks)
+{
+    if (objectStore->m_indexes.contains(name)) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Index name already exists."));
         return;
     }
 
-    SQLiteStatement insert(sqliteDatabase(), "INSERT INTO Indexes (objectStoreId, name, keyPath, isUnique) VALUES (?, ?, ?, ?)");
+    SQLiteStatement insert(objectStore->sqliteDatabase(), "INSERT INTO Indexes (objectStoreId, name, keyPath, isUnique) VALUES (?, ?, ?, ?)");
     bool ok = insert.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
-    insert.bindInt64(1, m_id);
+    insert.bindInt64(1, objectStore->m_id);
     insert.bindText(2, name);
     insert.bindText(3, keyPath);
     insert.bindInt(4, static_cast<int>(unique));
     ok = insert.step() == SQLResultDone;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
-    int64_t id = sqliteDatabase().lastInsertRowID();
+    int64_t id = objectStore->sqliteDatabase().lastInsertRowID();
 
-    RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(this, id, name, keyPath, unique);
+    RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(objectStore.get(), id, name, keyPath, unique);
     ASSERT(index->name() == name);
-    m_indexes.set(name, index);
+    objectStore->m_indexes.set(name, index);
     callbacks->onSuccess(index.get());
 }
 
@@ -296,25 +301,40 @@ static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id)
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
 }
 
-void IDBObjectStoreBackendImpl::removeIndex(const String& name, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreBackendImpl::removeIndex(const String& name, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transaction)
+{
+    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::removeIndexInternal, objectStore, name, callbacks)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "createIndex must be called in the context of a transaction."));
+}
+
+void IDBObjectStoreBackendImpl::removeIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, const String& name, PassRefPtr<IDBCallbacks> callbacks)
 {
-    RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
+    RefPtr<IDBIndexBackendImpl> index = objectStore->m_indexes.get(name);
     if (!index) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Index name does not exist."));
         return;
     }
 
-    SQLiteTransaction transaction(sqliteDatabase());
-    transaction.begin();
-    doDelete(sqliteDatabase(), "DELETE FROM Indexes WHERE id = ?", index->id());
-    doDelete(sqliteDatabase(), "DELETE FROM IndexData WHERE indexId = ?", index->id());
-    transaction.commit();
+    doDelete(objectStore->sqliteDatabase(), "DELETE FROM Indexes WHERE id = ?", index->id());
+    doDelete(objectStore->sqliteDatabase(), "DELETE FROM IndexData WHERE indexId = ?", index->id());
 
-    m_indexes.remove(name);
+    objectStore->m_indexes.remove(name);
     callbacks->onSuccess();
 }
 
-void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> range, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr)
+{
+    RefPtr<IDBObjectStoreBackendImpl> objectStore = this;
+    RefPtr<IDBKeyRange> range = prpRange;
+    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+    RefPtr<IDBTransactionBackendInterface> transaction = transactionPtr;
+    if (!transaction->scheduleTask(createCallbackTask(&IDBObjectStoreBackendImpl::openCursorInternal, objectStore, range, direction, callbacks, transaction)))
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_ALLOWED_ERR, "openCursor must be called in the context of a transaction."));
+}
+
+void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> range, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
 {
     // Several files depend on this order of selects.
     String sql = "SELECT id, keyString, keyDate, keyNumber, value FROM ObjectStoreData WHERE ";
@@ -330,7 +350,7 @@ void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> range, unsign
     else
         sql += "keyString DESC, keyDate DESC, keyNumber DESC";
 
-    OwnPtr<SQLiteStatement> query = adoptPtr(new SQLiteStatement(sqliteDatabase(), sql));
+    OwnPtr<SQLiteStatement> query = adoptPtr(new SQLiteStatement(objectStore->sqliteDatabase(), sql));
     bool ok = query->prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
@@ -339,14 +359,14 @@ void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> range, unsign
         currentColumn += range->left()->bind(*query, currentColumn);
     if (range->flags() & IDBKeyRange::RIGHT_BOUND || range->flags() == IDBKeyRange::SINGLE)
         currentColumn += range->right()->bind(*query, currentColumn);
-    query->bindInt64(currentColumn, m_id);
+    query->bindInt64(currentColumn, objectStore->id());
 
     if (query->step() != SQLResultRow) {
         callbacks->onSuccess();
         return;
     }
 
-    RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(this, range, direction, query.release());
+    RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(objectStore, range, direction, query.release(), transaction.get());
     callbacks->onSuccess(cursor.release());
 }
 
diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.h b/WebCore/storage/IDBObjectStoreBackendImpl.h
index 36c0014..ed994fb 100644
--- a/WebCore/storage/IDBObjectStoreBackendImpl.h
+++ b/WebCore/storage/IDBObjectStoreBackendImpl.h
@@ -38,6 +38,7 @@ class IDBDatabaseBackendImpl;
 class IDBIndexBackendImpl;
 class IDBTransactionBackendInterface;
 class SQLiteDatabase;
+class ScriptExecutionContext;
 
 class IDBObjectStoreBackendImpl : public IDBObjectStoreBackendInterface {
 public:
@@ -52,15 +53,15 @@ public:
     String keyPath() const { return m_keyPath; }
     PassRefPtr<DOMStringList> indexNames() const;
 
-    void get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface* transaction);
-    void put(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks>);
-    void remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>);
+    void get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    void put(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    void remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
 
-    void createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>);
+    void createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
     PassRefPtr<IDBIndexBackendInterface> index(const String& name);
-    void removeIndex(const String& name, PassRefPtr<IDBCallbacks>);
+    void removeIndex(const String& name, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
 
-    void openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>);
+    void openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
 
     IDBDatabaseBackendImpl* database() const { return m_database.get(); }
 
@@ -70,7 +71,12 @@ private:
     void loadIndexes();
     SQLiteDatabase& sqliteDatabase() const;
 
-    void getInternal(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>);
+    static void getInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>);
+    static void putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks>);
+    static void removeInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>);
+    static void createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>);
+    static void removeIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, const String& name, PassRefPtr<IDBCallbacks>);
+    static void openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendInterface>);
 
     RefPtr<IDBDatabaseBackendImpl> m_database;
 
diff --git a/WebCore/storage/IDBObjectStoreBackendInterface.h b/WebCore/storage/IDBObjectStoreBackendInterface.h
index c19855c..53ade62 100644
--- a/WebCore/storage/IDBObjectStoreBackendInterface.h
+++ b/WebCore/storage/IDBObjectStoreBackendInterface.h
@@ -49,15 +49,15 @@ public:
     virtual String keyPath() const = 0;
     virtual PassRefPtr<DOMStringList> indexNames() const = 0;
 
-    virtual void get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface* transaction) = 0;
-    virtual void put(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks>) = 0;
-    virtual void remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>) = 0;
+    virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
+    virtual void put(PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, bool addOnly, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
+    virtual void remove(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
 
-    virtual void createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>) = 0;
+    virtual void createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
     virtual PassRefPtr<IDBIndexBackendInterface> index(const String& name) = 0;
-    virtual void removeIndex(const String& name, PassRefPtr<IDBCallbacks>) = 0;
+    virtual void removeIndex(const String& name, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
 
-    virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>) = 0;
+    virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*) = 0;
 };
 
 } // namespace WebCore
diff --git a/WebCore/storage/IDBRequest.cpp b/WebCore/storage/IDBRequest.cpp
index c672642..c67e379 100644
--- a/WebCore/storage/IDBRequest.cpp
+++ b/WebCore/storage/IDBRequest.cpp
@@ -53,8 +53,8 @@ IDBRequest::IDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> sourc
     , m_timer(this, &IDBRequest::timerFired)
     , m_readyState(LOADING)
 {
-    if (transaction)
-        IDBPendingTransactionMonitor::removePendingTransaction(transaction);
+    if (m_transaction)
+        IDBPendingTransactionMonitor::removePendingTransaction(m_transaction.get());
 }
 
 IDBRequest::~IDBRequest()
@@ -70,10 +70,13 @@ IDBRequest::~IDBRequest()
     ASSERT(!m_transaction);
 }
 
-bool IDBRequest::resetReadyState()
+bool IDBRequest::resetReadyState(IDBTransactionBackendInterface* transaction)
 {
     ASSERT(m_readyState == DONE);
     m_readyState = LOADING;
+    ASSERT(!m_transaction);
+    m_transaction = transaction;
+    IDBPendingTransactionMonitor::removePendingTransaction(m_transaction.get());
     return true;
 }
 
@@ -89,7 +92,7 @@ void IDBRequest::onSuccess()
 
 void IDBRequest::onSuccess(PassRefPtr<IDBCursorBackendInterface> backend)
 {
-    scheduleEvent(IDBAny::create(IDBCursor::create(backend, this)), 0);
+    scheduleEvent(IDBAny::create(IDBCursor::create(backend, this, m_transaction.get())), 0);
 }
 
 void IDBRequest::onSuccess(PassRefPtr<IDBDatabaseBackendInterface> backend)
@@ -99,7 +102,7 @@ void IDBRequest::onSuccess(PassRefPtr<IDBDatabaseBackendInterface> backend)
 
 void IDBRequest::onSuccess(PassRefPtr<IDBIndexBackendInterface> backend)
 {
-    scheduleEvent(IDBAny::create(IDBIndex::create(backend)), 0);
+    scheduleEvent(IDBAny::create(IDBIndex::create(backend, m_transaction.get())), 0);
 }
 
 void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey)
@@ -109,9 +112,20 @@ void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey)
 
 void IDBRequest::onSuccess(PassRefPtr<IDBObjectStoreBackendInterface> backend)
 {
-    // FIXME: the transaction pointer should be the one of the setVersion transaction. This is because
-    // this callback is only executed for operations that neen to run in a setVersion transaction.
-    scheduleEvent(IDBAny::create(IDBObjectStore::create(backend, 0)), 0);
+    // FIXME: This function should go away once createObjectStore is sync.
+    scheduleEvent(IDBAny::create(IDBObjectStore::create(backend, m_transaction.get())), 0);
+}
+
+void IDBRequest::onSuccess(PassRefPtr<IDBTransactionBackendInterface> prpBackend)
+{
+    RefPtr<IDBTransactionBackendInterface> backend = prpBackend;
+    // This is only used by setVersion which will always have a source that's an IDBDatabase.
+    m_source->idbDatabase()->setSetVersionTransaction(backend.get());
+    RefPtr<IDBTransaction> frontend = IDBTransaction::create(scriptExecutionContext(), backend, m_source->idbDatabase().get());
+    backend->setCallbacks(frontend.get());
+    m_transaction = backend;
+    IDBPendingTransactionMonitor::removePendingTransaction(m_transaction.get());
+    scheduleEvent(IDBAny::create(frontend.release()), 0);
 }
 
 void IDBRequest::onSuccess(PassRefPtr<SerializedScriptValue> serializedScriptValue)
@@ -151,6 +165,10 @@ void IDBRequest::timerFired(Timer<IDBRequest>*)
     // need to make sure that resume() doesn't re-start the timer based on m_selfRef being set.
     RefPtr<IDBRequest> selfRef = m_selfRef.release();
 
+    // readyStateReset can be called synchronously while we're dispatching the event.
+    RefPtr<IDBTransactionBackendInterface> transaction = m_transaction;
+    m_transaction.clear();
+
     Vector<PendingEvent> pendingEvents;
     pendingEvents.swap(m_pendingEvents);
     for (size_t i = 0; i < pendingEvents.size(); ++i) {
@@ -162,12 +180,11 @@ void IDBRequest::timerFired(Timer<IDBRequest>*)
             dispatchEvent(IDBSuccessEvent::create(m_source, pendingEvents[i].m_result));
         }
     }
-    if (m_transaction) {
+    if (transaction) {
         // Now that we processed all pending events, let the transaction monitor check if
         // it can commit the current transaction or if there's anything new pending.
         // FIXME: Handle the workers case.
-        m_transaction->didCompleteTaskEvents();
-        m_transaction.clear();
+        transaction->didCompleteTaskEvents();
     }
 }
 
diff --git a/WebCore/storage/IDBRequest.h b/WebCore/storage/IDBRequest.h
index 75cd9a8..fa68208 100644
--- a/WebCore/storage/IDBRequest.h
+++ b/WebCore/storage/IDBRequest.h
@@ -46,7 +46,7 @@ class IDBTransactionBackendInterface;
 
 class IDBRequest : public IDBCallbacks, public EventTarget, public ActiveDOMObject {
 public:
-    static PassRefPtr<IDBRequest> create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface* transaction = 0) { return adoptRef(new IDBRequest(context, source, transaction)); }
+    static PassRefPtr<IDBRequest> create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface* transaction) { return adoptRef(new IDBRequest(context, source, transaction)); }
     virtual ~IDBRequest();
 
     // Defined in the IDL
@@ -58,7 +58,7 @@ public:
     DEFINE_ATTRIBUTE_EVENT_LISTENER(success);
     DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
 
-    bool resetReadyState();
+    bool resetReadyState(IDBTransactionBackendInterface*);
 
     // IDBCallbacks
     virtual void onError(PassRefPtr<IDBDatabaseError>);
@@ -68,6 +68,7 @@ public:
     virtual void onSuccess(PassRefPtr<IDBIndexBackendInterface>);
     virtual void onSuccess(PassRefPtr<IDBKey>);
     virtual void onSuccess(PassRefPtr<IDBObjectStoreBackendInterface>);
+    virtual void onSuccess(PassRefPtr<IDBTransactionBackendInterface>);
     virtual void onSuccess(PassRefPtr<SerializedScriptValue>);
 
     // EventTarget
@@ -77,8 +78,8 @@ public:
     virtual ScriptExecutionContext* scriptExecutionContext() const;
     virtual bool canSuspend() const;
 
-    using RefCounted<IDBCallbacks>::ref;
-    using RefCounted<IDBCallbacks>::deref;
+    using ThreadSafeShared<IDBCallbacks>::ref;
+    using ThreadSafeShared<IDBCallbacks>::deref;
 
 private:
     IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface* transaction);
diff --git a/WebCore/storage/IDBTransactionBackendImpl.cpp b/WebCore/storage/IDBTransactionBackendImpl.cpp
index 4f18437..1757295 100644
--- a/WebCore/storage/IDBTransactionBackendImpl.cpp
+++ b/WebCore/storage/IDBTransactionBackendImpl.cpp
@@ -44,7 +44,7 @@ IDBTransactionBackendImpl::IDBTransactionBackendImpl(DOMStringList* objectStores
     , m_mode(mode)
     , m_timeout(timeout)
     , m_id(id)
-    , m_state(NotStarted)
+    , m_state(Unused)
     , m_database(database)
     , m_transaction(new SQLiteTransaction(database->sqliteDatabase()))
     , m_timer(this, &IDBTransactionBackendImpl::timerFired)
@@ -65,7 +65,7 @@ bool IDBTransactionBackendImpl::scheduleTask(PassOwnPtr<ScriptExecutionContext::
         return false;
 
     m_taskQueue.append(task);
-    if (m_state == NotStarted)
+    if (m_state == Unused)
         start();
 
     return true;
@@ -77,6 +77,7 @@ void IDBTransactionBackendImpl::abort()
         return;
 
     m_state = Finished;
+    m_timer.stop();
     m_transaction->rollback();
     m_callbacks->onAbort();
     m_database->transactionCoordinator()->didFinishTransaction(this);
@@ -84,7 +85,10 @@ void IDBTransactionBackendImpl::abort()
 
 void IDBTransactionBackendImpl::didCompleteTaskEvents()
 {
-    ASSERT(m_state == Started);
+    if (m_state == Finished)
+        return;
+
+    ASSERT(m_state == Running);
     ASSERT(m_pendingEvents);
 
     m_pendingEvents--;
@@ -105,7 +109,7 @@ void IDBTransactionBackendImpl::didCompleteTaskEvents()
 
 void IDBTransactionBackendImpl::run()
 {
-    ASSERT(m_state == Started);
+    ASSERT(m_state == StartPending || m_state == Running);
     ASSERT(!m_timer.isActive());
 
     m_timer.startOneShot(0);
@@ -113,16 +117,15 @@ void IDBTransactionBackendImpl::run()
 
 void IDBTransactionBackendImpl::start()
 {
-    ASSERT(m_state == NotStarted);
+    ASSERT(m_state == Unused);
 
-    m_state = Started;
-    m_transaction->begin();
+    m_state = StartPending;
     m_database->transactionCoordinator()->didStartTransaction(this);
 }
 
 void IDBTransactionBackendImpl::commit()
 {
-    ASSERT(m_state == Started);
+    ASSERT(m_state == Running);
 
     m_state = Finished;
     m_transaction->commit();
@@ -132,7 +135,12 @@ void IDBTransactionBackendImpl::commit()
 void IDBTransactionBackendImpl::timerFired(Timer<IDBTransactionBackendImpl>*)
 {
     ASSERT(!m_taskQueue.isEmpty());
-    ASSERT(m_state == Started);
+
+    if (m_state == StartPending) {
+        m_transaction->begin();
+        m_state = Running;
+    } else
+        ASSERT(m_state == Running);
 
     TaskQueue queue;
     queue.swap(m_taskQueue);
diff --git a/WebCore/storage/IDBTransactionBackendImpl.h b/WebCore/storage/IDBTransactionBackendImpl.h
index c037a11..09a6a1c 100644
--- a/WebCore/storage/IDBTransactionBackendImpl.h
+++ b/WebCore/storage/IDBTransactionBackendImpl.h
@@ -60,9 +60,10 @@ private:
     IDBTransactionBackendImpl(DOMStringList* objectStores, unsigned short mode, unsigned long timeout, int id, IDBDatabaseBackendImpl*);
 
     enum State {
-        NotStarted,
-        Started,
-        Finished,
+        Unused, // Created, but no tasks yet.
+        StartPending, // Enqueued tasks, but SQLite transaction not yet started.
+        Running, // SQLite transaction started but not yet finished.
+        Finished, // Either aborted or committed.
     };
 
     void start();
diff --git a/WebKit/chromium/ChangeLog b/WebKit/chromium/ChangeLog
index ec46cd4..645a500 100644
--- a/WebKit/chromium/ChangeLog
+++ b/WebKit/chromium/ChangeLog
@@ -1,3 +1,78 @@
+2010-09-29  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
+        Finished IDBTransaction for IndexedDB
+        https://bugs.webkit.org/show_bug.cgi?id=46823
+
+        Plumbing.
+
+        * public/WebIDBCallbacks.h:
+        (WebKit::WebIDBCallbacks::onSuccess):
+        * public/WebIDBDatabase.h:
+        (WebKit::WebIDBDatabase::createObjectStore):
+        (WebKit::WebIDBDatabase::removeObjectStore):
+        (WebKit::WebIDBDatabase::close):
+        * public/WebIDBIndex.h:
+        (WebKit::WebIDBIndex::openObjectCursor):
+        (WebKit::WebIDBIndex::openCursor):
+        (WebKit::WebIDBIndex::getObject):
+        (WebKit::WebIDBIndex::get):
+        * public/WebIDBObjectStore.h:
+        (WebKit::WebIDBObjectStore::get):
+        (WebKit::WebIDBObjectStore::put):
+        (WebKit::WebIDBObjectStore::remove):
+        (WebKit::WebIDBObjectStore::createIndex):
+        (WebKit::WebIDBObjectStore::removeIndex):
+        (WebKit::WebIDBObjectStore::openCursor):
+        * public/WebIDBTransaction.h:
+        (WebKit::WebIDBTransaction::id):
+        (WebKit::WebIDBTransaction::getIDBTransactionBackendInterface):
+        * src/IDBCallbacksProxy.cpp:
+        (WebCore::IDBCallbacksProxy::onSuccess):
+        * src/IDBCallbacksProxy.h:
+        * src/IDBDatabaseProxy.cpp:
+        (WebCore::IDBDatabaseProxy::createObjectStore):
+        (WebCore::IDBDatabaseProxy::removeObjectStore):
+        (WebCore::IDBDatabaseProxy::close):
+        * src/IDBDatabaseProxy.h:
+        * src/IDBIndexBackendProxy.cpp:
+        (WebCore::IDBIndexBackendProxy::openObjectCursor):
+        (WebCore::IDBIndexBackendProxy::openCursor):
+        (WebCore::IDBIndexBackendProxy::getObject):
+        (WebCore::IDBIndexBackendProxy::get):
+        * src/IDBIndexBackendProxy.h:
+        * src/IDBObjectStoreProxy.cpp:
+        (WebCore::IDBObjectStoreProxy::put):
+        (WebCore::IDBObjectStoreProxy::remove):
+        (WebCore::IDBObjectStoreProxy::createIndex):
+        (WebCore::IDBObjectStoreProxy::removeIndex):
+        (WebCore::IDBObjectStoreProxy::openCursor):
+        * src/IDBObjectStoreProxy.h:
+        * src/IDBTransactionBackendProxy.cpp:
+        (WebCore::IDBTransactionBackendProxy::IDBTransactionBackendProxy):
+        * src/WebIDBCallbacksImpl.cpp:
+        (WebCore::WebIDBCallbacksImpl::onSuccess):
+        * src/WebIDBCallbacksImpl.h:
+        * src/WebIDBDatabaseImpl.cpp:
+        (WebKit::WebIDBDatabaseImpl::createObjectStore):
+        (WebKit::WebIDBDatabaseImpl::removeObjectStore):
+        (WebKit::WebIDBDatabaseImpl::close):
+        * src/WebIDBDatabaseImpl.h:
+        * src/WebIDBIndexImpl.cpp:
+        (WebKit::WebIDBIndexImpl::openCursor):
+        (WebKit::WebIDBIndexImpl::openObjectCursor):
+        (WebKit::WebIDBIndexImpl::getObject):
+        (WebKit::WebIDBIndexImpl::get):
+        * src/WebIDBIndexImpl.h:
+        * src/WebIDBObjectStoreImpl.cpp:
+        (WebKit::WebIDBObjectStoreImpl::put):
+        (WebKit::WebIDBObjectStoreImpl::remove):
+        (WebKit::WebIDBObjectStoreImpl::createIndex):
+        (WebKit::WebIDBObjectStoreImpl::removeIndex):
+        (WebKit::WebIDBObjectStoreImpl::openCursor):
+        * src/WebIDBObjectStoreImpl.h:
+
 2010-09-29  Andrey Kosyakov  <caseq at chromium.org>
 
         Reviewed by Pavel Feldman.
diff --git a/WebKit/chromium/public/WebIDBCallbacks.h b/WebKit/chromium/public/WebIDBCallbacks.h
index 2e2c4d2..64ffc08 100644
--- a/WebKit/chromium/public/WebIDBCallbacks.h
+++ b/WebKit/chromium/public/WebIDBCallbacks.h
@@ -36,6 +36,7 @@ class WebIDBDatabaseError;
 class WebIDBKey;
 class WebIDBIndex;
 class WebIDBObjectStore;
+class WebIDBTransaction;
 class WebSerializedScriptValue;
 
 class WebIDBCallbacks {
@@ -51,6 +52,7 @@ public:
     virtual void onSuccess(const WebIDBKey&) { WEBKIT_ASSERT_NOT_REACHED(); }
     virtual void onSuccess(WebIDBIndex*) { WEBKIT_ASSERT_NOT_REACHED(); }
     virtual void onSuccess(WebIDBObjectStore*) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void onSuccess(WebIDBTransaction*) { WEBKIT_ASSERT_NOT_REACHED(); }
     virtual void onSuccess(const WebSerializedScriptValue&) { WEBKIT_ASSERT_NOT_REACHED(); }
 };
 
diff --git a/WebKit/chromium/public/WebIDBDatabase.h b/WebKit/chromium/public/WebIDBDatabase.h
index 4e5cdcb..2021f6f 100644
--- a/WebKit/chromium/public/WebIDBDatabase.h
+++ b/WebKit/chromium/public/WebIDBDatabase.h
@@ -61,14 +61,14 @@ public:
         WEBKIT_ASSERT_NOT_REACHED();
         return WebDOMStringList();
     }
-    virtual void createObjectStore(const WebString& name, const WebString& keyPath, bool autoIncrement, WebIDBCallbacks*) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void createObjectStore(const WebString& name, const WebString& keyPath, bool autoIncrement, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
     // Transfers ownership of the WebIDBObjectStore to the caller.
     virtual WebIDBObjectStore* objectStore(const WebString& name, unsigned short mode)
     {
         WEBKIT_ASSERT_NOT_REACHED();
         return 0;
     }
-    virtual void removeObjectStore(const WebString& name, WebIDBCallbacks* callbacks) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void removeObjectStore(const WebString& name, WebIDBCallbacks* callbacks, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
     virtual void setVersion(const WebString& version, WebIDBCallbacks* callbacks) { WEBKIT_ASSERT_NOT_REACHED(); }
     // Transfers ownership of the WebIDBTransaction to the caller.
     virtual WebIDBTransaction* transaction(const WebDOMStringList& names, unsigned short mode, unsigned long timeout)
@@ -76,7 +76,7 @@ public:
         WEBKIT_ASSERT_NOT_REACHED();
         return 0;
     }
-
+    virtual void close() { WEBKIT_ASSERT_NOT_REACHED(); }
 };
 
 } // namespace WebKit
diff --git a/WebKit/chromium/public/WebIDBIndex.h b/WebKit/chromium/public/WebIDBIndex.h
index b4ba1f4..e52b487 100644
--- a/WebKit/chromium/public/WebIDBIndex.h
+++ b/WebKit/chromium/public/WebIDBIndex.h
@@ -61,43 +61,10 @@ public:
         return false;
     }
 
-    // FIXME: Remove the versions without transaction parameters.
-    virtual void openObjectCursor(const WebIDBKeyRange& range, unsigned short direction, WebIDBCallbacks* callbacks, const WebIDBTransaction&)
-    {
-        openObjectCursor(range, direction, callbacks);
-    }
-    virtual void openObjectCursor(const WebIDBKeyRange& range, unsigned short direction, WebIDBCallbacks* callbacks)
-    {
-        WebIDBTransaction transaction;
-        openObjectCursor(range, direction, callbacks, transaction);
-    }
-    virtual void openCursor(const WebIDBKeyRange& range, unsigned short direction, WebIDBCallbacks* callbacks, const WebIDBTransaction&)
-    {
-        openCursor(range, direction, callbacks);
-    }
-    virtual void openCursor(const WebIDBKeyRange& range, unsigned short direction, WebIDBCallbacks* callbacks)
-    {
-        WebIDBTransaction transaction;
-        openCursor(range, direction, callbacks, transaction);
-    }
-    virtual void getObject(const WebIDBKey& key, WebIDBCallbacks* callbacks, const WebIDBTransaction&)
-    {
-        getObject(key, callbacks);
-    }
-    virtual void getObject(const WebIDBKey& key, WebIDBCallbacks* callbacks)
-    {
-        WebIDBTransaction transaction;
-        getObject(key, callbacks, transaction);
-    }
-    virtual void get(const WebIDBKey& key, WebIDBCallbacks* callbacks, const WebIDBTransaction&)
-    {
-        get(key, callbacks);
-    }
-    virtual void get(const WebIDBKey& key, WebIDBCallbacks* callbacks)
-    {
-        WebIDBTransaction transaction;
-        get(key, callbacks, transaction);
-    }
+    virtual void openObjectCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void openCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void getObject(const WebIDBKey&, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void get(const WebIDBKey&, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
 };
 
 } // namespace WebKit
diff --git a/WebKit/chromium/public/WebIDBObjectStore.h b/WebKit/chromium/public/WebIDBObjectStore.h
index 19efd48..51a8d8c 100755
--- a/WebKit/chromium/public/WebIDBObjectStore.h
+++ b/WebKit/chromium/public/WebIDBObjectStore.h
@@ -58,51 +58,18 @@ public:
         return WebDOMStringList();
     }
 
-    // FIXME: Remove the default parameters for transactionIds.
-    virtual void get(const WebIDBKey& key, WebIDBCallbacks* callbacks, const WebIDBTransaction&)
-    {
-        get(key, callbacks);
-    }
-    virtual void get(const WebIDBKey& key, WebIDBCallbacks* callbacks)
-    {
-        WebIDBTransaction transaction;
-        get(key, callbacks, transaction);
-    }
-    virtual void put(const WebSerializedScriptValue& value, const WebIDBKey& key, bool addOnly, WebIDBCallbacks* callbacks, const WebIDBTransaction&)
-    {
-        put(value, key, addOnly, callbacks);
-    }
-    virtual void put(const WebSerializedScriptValue& value, const WebIDBKey& key, bool addOnly, WebIDBCallbacks* callbacks)
-    {
-        WebIDBTransaction transaction;
-        put(value, key, addOnly, callbacks, transaction);
-    }
-    virtual void remove(const WebIDBKey& key, WebIDBCallbacks* callbacks, const WebIDBTransaction&)
-    {
-        remove(key, callbacks);
-    }
-    virtual void remove(const WebIDBKey& key, WebIDBCallbacks* callbacks)
-    {
-        WebIDBTransaction transaction;
-        remove(key, callbacks, transaction);
-    }
-    virtual void createIndex(const WebString& name, const WebString& keyPath, bool unique, WebIDBCallbacks*) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void get(const WebIDBKey&, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void put(const WebSerializedScriptValue&, const WebIDBKey&, bool addOnly, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void remove(const WebIDBKey&, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void createIndex(const WebString& name, const WebString& keyPath, bool unique, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
     // Transfers ownership of the WebIDBIndex to the caller.
     virtual WebIDBIndex* index(const WebString& name)
     {
         WEBKIT_ASSERT_NOT_REACHED();
         return 0;
     }
-    virtual void removeIndex(const WebString& name, WebIDBCallbacks*) { WEBKIT_ASSERT_NOT_REACHED(); }
-    virtual void openCursor(const WebIDBKeyRange& range, unsigned short direction, WebIDBCallbacks* callbacks, const WebIDBTransaction&)
-    {
-        openCursor(range, direction, callbacks);
-    }
-    virtual void openCursor(const WebIDBKeyRange& range, unsigned short direction, WebIDBCallbacks* callbacks)
-    {
-        WebIDBTransaction transaction;
-        openCursor(range, direction, callbacks, transaction);
-    }
+    virtual void removeIndex(const WebString& name, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
+    virtual void openCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*, const WebIDBTransaction&) { WEBKIT_ASSERT_NOT_REACHED(); }
     // FIXME: finish.
 };
 
diff --git a/WebKit/chromium/public/WebIDBTransaction.h b/WebKit/chromium/public/WebIDBTransaction.h
index 7b51b97..6a739c3 100644
--- a/WebKit/chromium/public/WebIDBTransaction.h
+++ b/WebKit/chromium/public/WebIDBTransaction.h
@@ -54,8 +54,7 @@ public:
     virtual void didCompleteTaskEvents() { WEBKIT_ASSERT_NOT_REACHED(); }
     virtual int id() const
     {
-        // FIXME: Uncomment this after the next Chromium WebKit roll.
-        //WEBKIT_ASSERT_NOT_REACHED();
+        WEBKIT_ASSERT_NOT_REACHED();
         return 0;
     }
     virtual void setCallbacks(WebIDBTransactionCallbacks*) { WEBKIT_ASSERT_NOT_REACHED(); }
@@ -63,7 +62,6 @@ public:
     // FIXME: this is never called from WebCore. Find a cleaner solution.
     virtual WebCore::IDBTransactionBackendInterface* getIDBTransactionBackendInterface() const
     {
-        WEBKIT_ASSERT_NOT_REACHED();
         return 0;
     }
 
diff --git a/WebKit/chromium/src/IDBCallbacksProxy.cpp b/WebKit/chromium/src/IDBCallbacksProxy.cpp
index 3eab622..69051d0 100644
--- a/WebKit/chromium/src/IDBCallbacksProxy.cpp
+++ b/WebKit/chromium/src/IDBCallbacksProxy.cpp
@@ -38,6 +38,7 @@
 #include "WebIDBIndexImpl.h"
 #include "WebIDBKey.h"
 #include "WebIDBObjectStoreImpl.h"
+#include "WebIDBTransactionImpl.h"
 #include "WebSerializedScriptValue.h"
 
 #if ENABLE(INDEXED_DATABASE)
@@ -100,6 +101,12 @@ void IDBCallbacksProxy::onSuccess(PassRefPtr<IDBObjectStoreBackendInterface> bac
     m_callbacks.clear();
 }
 
+void IDBCallbacksProxy::onSuccess(PassRefPtr<IDBTransactionBackendInterface> backend)
+{
+    m_callbacks->onSuccess(new WebKit::WebIDBTransactionImpl(backend));
+    m_callbacks.clear();
+}
+
 void IDBCallbacksProxy::onSuccess(PassRefPtr<SerializedScriptValue> serializedScriptValue)
 {
     m_callbacks->onSuccess(WebKit::WebSerializedScriptValue(serializedScriptValue));
diff --git a/WebKit/chromium/src/IDBCallbacksProxy.h b/WebKit/chromium/src/IDBCallbacksProxy.h
index 506dbb0..8c26161 100644
--- a/WebKit/chromium/src/IDBCallbacksProxy.h
+++ b/WebKit/chromium/src/IDBCallbacksProxy.h
@@ -54,6 +54,7 @@ public:
     virtual void onSuccess(PassRefPtr<IDBIndexBackendInterface>);
     virtual void onSuccess(PassRefPtr<IDBKey>);
     virtual void onSuccess(PassRefPtr<IDBObjectStoreBackendInterface>);
+    virtual void onSuccess(PassRefPtr<IDBTransactionBackendInterface>);
     virtual void onSuccess(PassRefPtr<SerializedScriptValue>);
 
 private:
diff --git a/WebKit/chromium/src/IDBDatabaseProxy.cpp b/WebKit/chromium/src/IDBDatabaseProxy.cpp
index ce5e0a6..564fddb 100644
--- a/WebKit/chromium/src/IDBDatabaseProxy.cpp
+++ b/WebKit/chromium/src/IDBDatabaseProxy.cpp
@@ -76,9 +76,12 @@ PassRefPtr<DOMStringList> IDBDatabaseProxy::objectStores() const
     return m_webIDBDatabase->objectStores();
 }
 
-void IDBDatabaseProxy::createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks> callbacks)
+void IDBDatabaseProxy::createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBDatabase->createObjectStore(name, keyPath, autoIncrement, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBDatabase->createObjectStore(name, keyPath, autoIncrement, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
 PassRefPtr<IDBObjectStoreBackendInterface> IDBDatabaseProxy::objectStore(const String& name, unsigned short mode)
@@ -89,9 +92,12 @@ PassRefPtr<IDBObjectStoreBackendInterface> IDBDatabaseProxy::objectStore(const S
     return IDBObjectStoreProxy::create(objectStore);
 }
 
-void IDBDatabaseProxy::removeObjectStore(const String& name, PassRefPtr<IDBCallbacks> callbacks)
+void IDBDatabaseProxy::removeObjectStore(const String& name, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBDatabase->removeObjectStore(name, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBDatabase->removeObjectStore(name, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
 void IDBDatabaseProxy::setVersion(const String& version, PassRefPtr<IDBCallbacks> callbacks)
@@ -106,6 +112,11 @@ PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseProxy::transaction(DOMStri
     return IDBTransactionBackendProxy::create(transaction);
 }
 
+void IDBDatabaseProxy::close()
+{
+    m_webIDBDatabase->close();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
diff --git a/WebKit/chromium/src/IDBDatabaseProxy.h b/WebKit/chromium/src/IDBDatabaseProxy.h
index fffd23e..eaeeb27 100644
--- a/WebKit/chromium/src/IDBDatabaseProxy.h
+++ b/WebKit/chromium/src/IDBDatabaseProxy.h
@@ -47,13 +47,12 @@ public:
     virtual String version() const;
     virtual PassRefPtr<DOMStringList> objectStores() const;
 
-    // FIXME: Add setVersion.
-
-    virtual void createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks>);
+    virtual void createObjectStore(const String& name, const String& keyPath, bool autoIncrement, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
     virtual PassRefPtr<IDBObjectStoreBackendInterface> objectStore(const String& name, unsigned short mode);
-    virtual void removeObjectStore(const String& name, PassRefPtr<IDBCallbacks>);
+    virtual void removeObjectStore(const String& name, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
     virtual void setVersion(const String& version, PassRefPtr<IDBCallbacks>);
     virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* storeNames, unsigned short mode, unsigned long timeout);
+    virtual void close();
 
 private:
     IDBDatabaseProxy(PassOwnPtr<WebKit::WebIDBDatabase>);
diff --git a/WebKit/chromium/src/IDBIndexBackendProxy.cpp b/WebKit/chromium/src/IDBIndexBackendProxy.cpp
index f92f4f2..8f26bf1 100644
--- a/WebKit/chromium/src/IDBIndexBackendProxy.cpp
+++ b/WebKit/chromium/src/IDBIndexBackendProxy.cpp
@@ -30,6 +30,7 @@
 
 #include "IDBCallbacks.h"
 #include "IDBKeyRange.h"
+#include "IDBTransactionBackendProxy.h"
 #include "WebIDBCallbacksImpl.h"
 #include "WebIDBDatabaseError.h"
 #include "WebIDBIndex.h"
@@ -72,24 +73,36 @@ bool IDBIndexBackendProxy::unique()
     return m_webIDBIndex->unique();
 }
 
-void IDBIndexBackendProxy::openObjectCursor(PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks)
+void IDBIndexBackendProxy::openObjectCursor(PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBIndex->openObjectCursor(keyRange, direction, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBIndex->openObjectCursor(keyRange, direction, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
-void IDBIndexBackendProxy::openCursor(PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks)
+void IDBIndexBackendProxy::openCursor(PassRefPtr<IDBKeyRange> keyRange, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBIndex->openCursor(keyRange, direction, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBIndex->openCursor(keyRange, direction, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
-void IDBIndexBackendProxy::getObject(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
+void IDBIndexBackendProxy::getObject(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBIndex->getObject(key, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBIndex->getObject(key, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
-void IDBIndexBackendProxy::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
+void IDBIndexBackendProxy::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBIndex->get(key, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBIndex->get(key, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
 } // namespace WebCore
diff --git a/WebKit/chromium/src/IDBIndexBackendProxy.h b/WebKit/chromium/src/IDBIndexBackendProxy.h
index 6aafdfa..031ed40 100644
--- a/WebKit/chromium/src/IDBIndexBackendProxy.h
+++ b/WebKit/chromium/src/IDBIndexBackendProxy.h
@@ -46,10 +46,10 @@ public:
     virtual String keyPath();
     virtual bool unique();
 
-    virtual void openObjectCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>);
-    virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>);
-    virtual void getObject(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>);
-    virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>);
+    virtual void openObjectCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    virtual void getObject(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
 
 private:
     IDBIndexBackendProxy(PassOwnPtr<WebKit::WebIDBIndex>);
diff --git a/WebKit/chromium/src/IDBObjectStoreProxy.cpp b/WebKit/chromium/src/IDBObjectStoreProxy.cpp
index 82ca5f6..69aa8ca 100755
--- a/WebKit/chromium/src/IDBObjectStoreProxy.cpp
+++ b/WebKit/chromium/src/IDBObjectStoreProxy.cpp
@@ -80,19 +80,28 @@ void IDBObjectStoreProxy::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> c
     m_webIDBObjectStore->get(key, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
-void IDBObjectStoreProxy::put(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreProxy::put(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBObjectStore->put(value, key, addOnly, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBObjectStore->put(value, key, addOnly, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
-void IDBObjectStoreProxy::remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreProxy::remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBObjectStore->remove(key, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBObjectStore->remove(key, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
-void IDBObjectStoreProxy::createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreProxy::createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBObjectStore->createIndex(name, keyPath, unique, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBObjectStore->createIndex(name, keyPath, unique, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreProxy::index(const String& name)
@@ -103,14 +112,20 @@ PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreProxy::index(const String& na
     return IDBIndexBackendProxy::create(index);
 }
 
-void IDBObjectStoreProxy::removeIndex(const String& name, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreProxy::removeIndex(const String& name, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBObjectStore->removeIndex(name, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBObjectStore->removeIndex(name, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
-void IDBObjectStoreProxy::openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks)
+void IDBObjectStoreProxy::openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction)
 {
-    m_webIDBObjectStore->openCursor(range, direction, new WebIDBCallbacksImpl(callbacks));
+    // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer,
+    // all implementations of IDB interfaces are proxy objects.
+    IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction);
+    m_webIDBObjectStore->openCursor(range, direction, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction());
 }
 
 } // namespace WebCore
diff --git a/WebKit/chromium/src/IDBObjectStoreProxy.h b/WebKit/chromium/src/IDBObjectStoreProxy.h
index 13dfe23..80e4668 100755
--- a/WebKit/chromium/src/IDBObjectStoreProxy.h
+++ b/WebKit/chromium/src/IDBObjectStoreProxy.h
@@ -40,21 +40,21 @@ namespace WebCore {
 class IDBObjectStoreProxy : public IDBObjectStoreBackendInterface {
 public:
     static PassRefPtr<IDBObjectStoreBackendInterface> create(PassOwnPtr<WebKit::WebIDBObjectStore>);
-    ~IDBObjectStoreProxy();
+    virtual ~IDBObjectStoreProxy();
 
-    String name() const;
-    String keyPath() const;
-    PassRefPtr<DOMStringList> indexNames() const;
+    virtual String name() const;
+    virtual String keyPath() const;
+    virtual PassRefPtr<DOMStringList> indexNames() const;
 
-    void get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
-    void put(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, bool addOnly, PassRefPtr<IDBCallbacks>);
-    void remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks>);
+    virtual void get(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    virtual void put(PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, bool addOnly, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    virtual void remove(PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
 
-    void createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>);
-    PassRefPtr<IDBIndexBackendInterface> index(const String& name);
-    void removeIndex(const String& name, PassRefPtr<IDBCallbacks>);
+    virtual void createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
+    virtual PassRefPtr<IDBIndexBackendInterface> index(const String& name);
+    virtual void removeIndex(const String& name, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
 
-    virtual void openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>);
+    virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*);
 
 private:
     IDBObjectStoreProxy(PassOwnPtr<WebKit::WebIDBObjectStore>);
diff --git a/WebKit/chromium/src/IDBTransactionBackendProxy.cpp b/WebKit/chromium/src/IDBTransactionBackendProxy.cpp
index 59e88d8..81b7cee 100644
--- a/WebKit/chromium/src/IDBTransactionBackendProxy.cpp
+++ b/WebKit/chromium/src/IDBTransactionBackendProxy.cpp
@@ -45,6 +45,8 @@ PassRefPtr<IDBTransactionBackendInterface> IDBTransactionBackendProxy::create(Pa
 IDBTransactionBackendProxy::IDBTransactionBackendProxy(PassOwnPtr<WebKit::WebIDBTransaction> transaction)
     : m_webIDBTransaction(transaction)
 {
+    if (!m_webIDBTransaction)
+        m_webIDBTransaction = adoptPtr(new WebKit::WebIDBTransaction());
 }
 
 IDBTransactionBackendProxy::~IDBTransactionBackendProxy()
diff --git a/WebKit/chromium/src/WebIDBCallbacksImpl.cpp b/WebKit/chromium/src/WebIDBCallbacksImpl.cpp
index fe67789..14ed02e 100644
--- a/WebKit/chromium/src/WebIDBCallbacksImpl.cpp
+++ b/WebKit/chromium/src/WebIDBCallbacksImpl.cpp
@@ -33,12 +33,14 @@
 #include "IDBIndexBackendProxy.h"
 #include "IDBKey.h"
 #include "IDBObjectStoreProxy.h"
+#include "IDBTransactionBackendProxy.h"
 #include "WebIDBCallbacks.h"
 #include "WebIDBDatabase.h"
 #include "WebIDBDatabaseError.h"
 #include "WebIDBIndex.h"
 #include "WebIDBKey.h"
 #include "WebIDBObjectStore.h"
+#include "WebIDBTransaction.h"
 #include "WebSerializedScriptValue.h"
 
 #if ENABLE(INDEXED_DATABASE)
@@ -89,6 +91,11 @@ void WebIDBCallbacksImpl::onSuccess(WebKit::WebIDBObjectStore* webKitInstance)
     m_callbacks->onSuccess(IDBObjectStoreProxy::create(webKitInstance));
 }
 
+void WebIDBCallbacksImpl::onSuccess(WebKit::WebIDBTransaction* webKitInstance)
+{
+    m_callbacks->onSuccess(IDBTransactionBackendProxy::create(webKitInstance));
+}
+
 void WebIDBCallbacksImpl::onSuccess(const WebKit::WebSerializedScriptValue& serializedScriptValue)
 {
     m_callbacks->onSuccess(serializedScriptValue);
diff --git a/WebKit/chromium/src/WebIDBCallbacksImpl.h b/WebKit/chromium/src/WebIDBCallbacksImpl.h
index 1835c60..33a72f4 100644
--- a/WebKit/chromium/src/WebIDBCallbacksImpl.h
+++ b/WebKit/chromium/src/WebIDBCallbacksImpl.h
@@ -48,6 +48,7 @@ public:
     virtual void onSuccess(const WebKit::WebIDBKey&);
     virtual void onSuccess(WebKit::WebIDBIndex*);
     virtual void onSuccess(WebKit::WebIDBObjectStore*);
+    virtual void onSuccess(WebKit::WebIDBTransaction*);
     virtual void onSuccess(const WebKit::WebSerializedScriptValue&);
 
 private:
diff --git a/WebKit/chromium/src/WebIDBDatabaseImpl.cpp b/WebKit/chromium/src/WebIDBDatabaseImpl.cpp
index 8870ff9..abe6fbd 100644
--- a/WebKit/chromium/src/WebIDBDatabaseImpl.cpp
+++ b/WebKit/chromium/src/WebIDBDatabaseImpl.cpp
@@ -69,9 +69,9 @@ WebDOMStringList WebIDBDatabaseImpl::objectStores() const
     return m_databaseBackend->objectStores();
 }
 
-void WebIDBDatabaseImpl::createObjectStore(const WebString& name, const WebString& keyPath, bool autoIncrement, WebIDBCallbacks* callbacks)
+void WebIDBDatabaseImpl::createObjectStore(const WebString& name, const WebString& keyPath, bool autoIncrement, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_databaseBackend->createObjectStore(name, keyPath, autoIncrement, IDBCallbacksProxy::create(callbacks));
+    m_databaseBackend->createObjectStore(name, keyPath, autoIncrement, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
 WebIDBObjectStore* WebIDBDatabaseImpl::objectStore(const WebString& name, unsigned short mode)
@@ -82,9 +82,9 @@ WebIDBObjectStore* WebIDBDatabaseImpl::objectStore(const WebString& name, unsign
     return new WebIDBObjectStoreImpl(objectStore);
 }
 
-void WebIDBDatabaseImpl::removeObjectStore(const WebString& name, WebIDBCallbacks* callbacks)
+void WebIDBDatabaseImpl::removeObjectStore(const WebString& name, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_databaseBackend->removeObjectStore(name, IDBCallbacksProxy::create(callbacks));
+    m_databaseBackend->removeObjectStore(name, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
 void WebIDBDatabaseImpl::setVersion(const WebString& version, WebIDBCallbacks* callbacks)
@@ -101,6 +101,11 @@ WebIDBTransaction* WebIDBDatabaseImpl::transaction(const WebDOMStringList& names
     return new WebIDBTransactionImpl(transaction);
 }
 
+void WebIDBDatabaseImpl::close()
+{
+    m_databaseBackend->close();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
diff --git a/WebKit/chromium/src/WebIDBDatabaseImpl.h b/WebKit/chromium/src/WebIDBDatabaseImpl.h
index e0eaaa5..2274e48 100644
--- a/WebKit/chromium/src/WebIDBDatabaseImpl.h
+++ b/WebKit/chromium/src/WebIDBDatabaseImpl.h
@@ -49,11 +49,12 @@ public:
     virtual WebString version() const;
     virtual WebDOMStringList objectStores() const;
 
-    virtual void createObjectStore(const WebString& name, const WebString& keyPath, bool autoIncrement, WebIDBCallbacks* callbacks);
+    virtual void createObjectStore(const WebString& name, const WebString& keyPath, bool autoIncrement, WebIDBCallbacks* callbacks, const WebIDBTransaction&);
     virtual WebIDBObjectStore* objectStore(const WebString& name, unsigned short mode);
-    virtual void removeObjectStore(const WebString& name, WebIDBCallbacks* callbacks);
+    virtual void removeObjectStore(const WebString& name, WebIDBCallbacks* callbacks, const WebIDBTransaction&);
     virtual void setVersion(const WebString& version, WebIDBCallbacks* callbacks);
     virtual WebIDBTransaction* transaction(const WebDOMStringList& names, unsigned short mode, unsigned long timeout);
+    virtual void close();
 
 private:
     WTF::RefPtr<WebCore::IDBDatabaseBackendInterface> m_databaseBackend;
diff --git a/WebKit/chromium/src/WebIDBIndexImpl.cpp b/WebKit/chromium/src/WebIDBIndexImpl.cpp
index c049aac..8795778 100644
--- a/WebKit/chromium/src/WebIDBIndexImpl.cpp
+++ b/WebKit/chromium/src/WebIDBIndexImpl.cpp
@@ -68,24 +68,24 @@ bool WebIDBIndexImpl::unique() const
     return m_backend->unique();
 }
 
-void WebIDBIndexImpl::openCursor(const WebIDBKeyRange& keyRange, unsigned short direction, WebIDBCallbacks* callbacks)
+void WebIDBIndexImpl::openCursor(const WebIDBKeyRange& keyRange, unsigned short direction, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_backend->openCursor(keyRange, direction, IDBCallbacksProxy::create(callbacks));
+    m_backend->openCursor(keyRange, direction, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
-void WebIDBIndexImpl::openObjectCursor(const WebIDBKeyRange& keyRange, unsigned short direction, WebIDBCallbacks* callbacks)
+void WebIDBIndexImpl::openObjectCursor(const WebIDBKeyRange& keyRange, unsigned short direction, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_backend->openObjectCursor(keyRange, direction, IDBCallbacksProxy::create(callbacks));
+    m_backend->openObjectCursor(keyRange, direction, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
-void WebIDBIndexImpl::getObject(const WebIDBKey& keyRange, WebIDBCallbacks* callbacks)
+void WebIDBIndexImpl::getObject(const WebIDBKey& keyRange, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_backend->getObject(keyRange, IDBCallbacksProxy::create(callbacks));
+    m_backend->getObject(keyRange, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
-void WebIDBIndexImpl::get(const WebIDBKey& keyRange, WebIDBCallbacks* callbacks)
+void WebIDBIndexImpl::get(const WebIDBKey& keyRange, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_backend->get(keyRange, IDBCallbacksProxy::create(callbacks));
+    m_backend->get(keyRange, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
 } // namespace WebCore
diff --git a/WebKit/chromium/src/WebIDBIndexImpl.h b/WebKit/chromium/src/WebIDBIndexImpl.h
index 2108001..cb2efc7 100644
--- a/WebKit/chromium/src/WebIDBIndexImpl.h
+++ b/WebKit/chromium/src/WebIDBIndexImpl.h
@@ -46,10 +46,10 @@ public:
     virtual WebString keyPath() const;
     virtual bool unique() const;
 
-    virtual void openObjectCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*); 
-    virtual void openCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*);
-    virtual void getObject(const WebIDBKey&, WebIDBCallbacks*);
-    virtual void get(const WebIDBKey&, WebIDBCallbacks*);
+    virtual void openObjectCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*, const WebIDBTransaction&); 
+    virtual void openCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*, const WebIDBTransaction&);
+    virtual void getObject(const WebIDBKey&, WebIDBCallbacks*, const WebIDBTransaction&);
+    virtual void get(const WebIDBKey&, WebIDBCallbacks*, const WebIDBTransaction&);
 
 private:
     WTF::RefPtr<WebCore::IDBIndexBackendInterface> m_backend;
diff --git a/WebKit/chromium/src/WebIDBObjectStoreImpl.cpp b/WebKit/chromium/src/WebIDBObjectStoreImpl.cpp
index 36d8ace..3cf7f25 100755
--- a/WebKit/chromium/src/WebIDBObjectStoreImpl.cpp
+++ b/WebKit/chromium/src/WebIDBObjectStoreImpl.cpp
@@ -71,19 +71,19 @@ void WebIDBObjectStoreImpl::get(const WebIDBKey& key, WebIDBCallbacks* callbacks
     m_objectStore->get(key, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
-void WebIDBObjectStoreImpl::put(const WebSerializedScriptValue& value, const WebIDBKey& key, bool addOnly, WebIDBCallbacks* callbacks)
+void WebIDBObjectStoreImpl::put(const WebSerializedScriptValue& value, const WebIDBKey& key, bool addOnly, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_objectStore->put(value, key, addOnly, IDBCallbacksProxy::create(callbacks));
+    m_objectStore->put(value, key, addOnly, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
-void WebIDBObjectStoreImpl::remove(const WebIDBKey& key, WebIDBCallbacks* callbacks)
+void WebIDBObjectStoreImpl::remove(const WebIDBKey& key, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_objectStore->remove(key, IDBCallbacksProxy::create(callbacks));
+    m_objectStore->remove(key, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
-void WebIDBObjectStoreImpl::createIndex(const WebString& name, const WebString& keyPath, bool unique, WebIDBCallbacks* callbacks)
+void WebIDBObjectStoreImpl::createIndex(const WebString& name, const WebString& keyPath, bool unique, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_objectStore->createIndex(name, keyPath, unique, IDBCallbacksProxy::create(callbacks));
+    m_objectStore->createIndex(name, keyPath, unique, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
 WebIDBIndex* WebIDBObjectStoreImpl::index(const WebString& name)
@@ -94,14 +94,14 @@ WebIDBIndex* WebIDBObjectStoreImpl::index(const WebString& name)
     return new WebIDBIndexImpl(index);
 }
 
-void WebIDBObjectStoreImpl::removeIndex(const WebString& name, WebIDBCallbacks* callbacks)
+void WebIDBObjectStoreImpl::removeIndex(const WebString& name, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_objectStore->removeIndex(name, IDBCallbacksProxy::create(callbacks));
+    m_objectStore->removeIndex(name, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
-void WebIDBObjectStoreImpl::openCursor(const WebIDBKeyRange& keyRange, unsigned short direction, WebIDBCallbacks* callbacks)
+void WebIDBObjectStoreImpl::openCursor(const WebIDBKeyRange& keyRange, unsigned short direction, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction)
 {
-    m_objectStore->openCursor(IDBKeyRange::create(keyRange.left(), keyRange.right(), keyRange.flags()), direction, IDBCallbacksProxy::create(callbacks));
+    m_objectStore->openCursor(IDBKeyRange::create(keyRange.left(), keyRange.right(), keyRange.flags()), direction, IDBCallbacksProxy::create(callbacks), transaction.getIDBTransactionBackendInterface());
 }
 
 } // namespace WebCore
diff --git a/WebKit/chromium/src/WebIDBObjectStoreImpl.h b/WebKit/chromium/src/WebIDBObjectStoreImpl.h
index a9f1200..76e414b 100755
--- a/WebKit/chromium/src/WebIDBObjectStoreImpl.h
+++ b/WebKit/chromium/src/WebIDBObjectStoreImpl.h
@@ -48,14 +48,14 @@ public:
     WebDOMStringList indexNames() const;
 
     void get(const WebIDBKey& key, WebIDBCallbacks*, const WebIDBTransaction&);
-    void put(const WebSerializedScriptValue& value, const WebIDBKey& key, bool addOnly, WebIDBCallbacks*);
-    void remove(const WebIDBKey& key, WebIDBCallbacks*);
+    void put(const WebSerializedScriptValue&, const WebIDBKey& key, bool addOnly, WebIDBCallbacks*, const WebIDBTransaction&);
+    void remove(const WebIDBKey& key, WebIDBCallbacks*, const WebIDBTransaction&);
 
-    void createIndex(const WebString& name, const WebString& keyPath, bool unique, WebIDBCallbacks* callbacks);
+    void createIndex(const WebString& name, const WebString& keyPath, bool unique, WebIDBCallbacks*, const WebIDBTransaction&);
     WebIDBIndex* index(const WebString& name);
-    void removeIndex(const WebString& name, WebIDBCallbacks* callbacks);
+    void removeIndex(const WebString& name, WebIDBCallbacks*, const WebIDBTransaction&);
 
-    void openCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*);
+    void openCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*, const WebIDBTransaction&);
 
  private:
     WTF::RefPtr<WebCore::IDBObjectStoreBackendInterface> m_objectStore;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list