[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 14:57:42 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 81e04f1f6cd4371d6b2e3318946c4074b897b62c
Author: jorlow at chromium.org <jorlow at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Oct 26 15:21:32 2010 +0000

    2010-10-26  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Quota for IndexedDB should be per origin not per database
            https://bugs.webkit.org/show_bug.cgi?id=48064
    
            Verify our backing database can handle multiple indexes, objectStores,
            items in the index/object stores, etc within databases of different
            names.
    
            Also adjust the quota test so it doesn't fail with subtle differences
            in the backing db (which can change the size a bit).
    
            * storage/indexeddb/database-quota-expected.txt:
            * storage/indexeddb/database-quota.html:
            * storage/indexeddb/duplicates-expected.txt: Added.
            * storage/indexeddb/duplicates.html: Added.
    2010-10-26  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Quota for IndexedDB should be per origin not per database
            https://bugs.webkit.org/show_bug.cgi?id=48064
    
            Merge all databases for each origin into a single SQLiteDatabase.
    
            Replace the awkward metaData table with a Database table.
    
            Create a new IDBSQLiteDatabase class that wraps SQLiteDatabase
            and implements weak pointer semantics for IDBFactory. It's ref
            counted so multiple IDBDatabaseBackendImpls can share one.
    
            Fix uniqueness constraints that were overly conservitive.
    
            Get rid of the code that blows away existing data every time
            the database is opened.
    
            Get rid of the fairly useless indexedDB manual test and replace
            it with one that verifies data persists.
    
            Use name+origin (not just name) in our cache of IDBDatabaseBackend
            objects (so one origin can't access anothers' data).
    
            Test: storage/indexeddb/duplicates.html
    
            * WebCore.gypi:
            * manual-tests/indexed-database.html: Removed.
            * manual-tests/indexeddb-persists.html: Added.
            * storage/IDBDatabaseBackendImpl.cpp:
            (WebCore::extractMetaData):
            (WebCore::setMetaData):
            (WebCore::IDBDatabaseBackendImpl::IDBDatabaseBackendImpl):
            (WebCore::IDBDatabaseBackendImpl::setDescription):
            (WebCore::IDBDatabaseBackendImpl::sqliteDatabase):
            (WebCore::IDBDatabaseBackendImpl::createObjectStoreInternal):
            (WebCore::IDBDatabaseBackendImpl::setVersionInternal):
            (WebCore::IDBDatabaseBackendImpl::loadObjectStores):
            * storage/IDBDatabaseBackendImpl.h:
            (WebCore::IDBDatabaseBackendImpl::create):
            (WebCore::IDBDatabaseBackendImpl::id):
            * storage/IDBFactoryBackendImpl.cpp:
            (WebCore::IDBFactoryBackendImpl::removeSQLiteDatabase):
            (WebCore::openSQLiteDatabase):
            (WebCore::createTables):
            (WebCore::IDBFactoryBackendImpl::open):
            (WebCore::IDBFactoryBackendImpl::databaseFileName):
            * storage/IDBFactoryBackendImpl.h:
            * storage/IDBObjectStoreBackendImpl.cpp:
            (WebCore::putObjectStoreData):
            (WebCore::IDBObjectStoreBackendImpl::putInternal):
            * storage/IDBSQLiteDatabase.cpp: Added.
            (WebCore::IDBSQLiteDatabase::IDBSQLiteDatabase):
            (WebCore::IDBSQLiteDatabase::~IDBSQLiteDatabase):
            * storage/IDBSQLiteDatabase.h: Added.
            (WebCore::IDBSQLiteDatabase::create):
            (WebCore::IDBSQLiteDatabase::db):
    2010-10-26  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Quota for IndexedDB should be per origin not per database
            https://bugs.webkit.org/show_bug.cgi?id=48064
    
            * public/WebIDBFactory.h:
            * public/WebSecurityOrigin.h:
            * src/WebIDBFactory.cpp:
            (WebKit::WebIDBFactory::databaseFileName):
            * src/WebSecurityOrigin.cpp:
            (WebKit::WebSecurityOrigin::get):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@70522 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 6ca1752..6ec49fc 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -2,6 +2,25 @@
 
         Reviewed by Steve Block.
 
+        Quota for IndexedDB should be per origin not per database
+        https://bugs.webkit.org/show_bug.cgi?id=48064
+
+        Verify our backing database can handle multiple indexes, objectStores,
+        items in the index/object stores, etc within databases of different
+        names.
+
+        Also adjust the quota test so it doesn't fail with subtle differences
+        in the backing db (which can change the size a bit).
+
+        * storage/indexeddb/database-quota-expected.txt:
+        * storage/indexeddb/database-quota.html:
+        * storage/indexeddb/duplicates-expected.txt: Added.
+        * storage/indexeddb/duplicates.html: Added.
+
+2010-10-26  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
         Add IndexedDB test/tutorial
         https://bugs.webkit.org/show_bug.cgi?id=48067
 
diff --git a/LayoutTests/storage/indexeddb/database-quota-expected.txt b/LayoutTests/storage/indexeddb/database-quota-expected.txt
index b6ea505..6c245d4 100644
--- a/LayoutTests/storage/indexeddb/database-quota-expected.txt
+++ b/LayoutTests/storage/indexeddb/database-quota-expected.txt
@@ -68,1034 +68,6 @@ trans = db.transaction()
 Creating 'data' which contains 64K of data
 PASS data.length is 65536
 store = trans.objectStore('test123')
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
-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
-
-store = event.source
-store.add({x: data}, dataAdded)
 Error function called: (0) Error writing data to stable storage.
 Error event fired:
 PASS 'result' in event is false
@@ -1108,7 +80,7 @@ PASS 'onerror' in event.target is true
 PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
-PASS Adding data failed due to quota error. Data added was: 5120 KB
+PASS Adding data failed due to quota error. Data added was about 5 MB
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/storage/indexeddb/database-quota.html b/LayoutTests/storage/indexeddb/database-quota.html
index 45ce709..aefe6b1 100644
--- a/LayoutTests/storage/indexeddb/database-quota.html
+++ b/LayoutTests/storage/indexeddb/database-quota.html
@@ -90,17 +90,15 @@ function checkQuotaEnforcing()
 function addData()
 {
     if (dataAdded < 5 * 1024 * 1024) {
-        if (dataAdded > 0) {
-            verifySuccessEvent(event);
-            store = evalAndLog("store = event.source");
-        }
+        if (dataAdded > 0)
+            store = event.source;
     } else {
         testFailed("added more than quota");
         done();
         return;
     }
     dataAdded += 65536;
-    result = evalAndLog("store.add({x: data}, dataAdded)");
+    result = store.add({x: data}, dataAdded);
     result.onsuccess = addData;
     result.onerror = logError;
 }
@@ -113,7 +111,7 @@ function logError()
 
 function testComplete()
 {
-    testPassed("Adding data failed due to quota error. Data added was: " + dataAdded / 1024 + " KB");
+    testPassed("Adding data failed due to quota error. Data added was about " + Math.round(dataAdded / 1024 / 1024) + " MB");
     done();
 }
 
diff --git a/LayoutTests/storage/indexeddb/duplicates-expected.txt b/LayoutTests/storage/indexeddb/duplicates-expected.txt
new file mode 100644
index 0000000..2ea8c36
--- /dev/null
+++ b/LayoutTests/storage/indexeddb/duplicates-expected.txt
@@ -0,0 +1,541 @@
+Verify that you can put the same data in 2 different databases without uniqueness constraints firing.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+webkitIndexedDB.open('name', 'description')
+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
+
+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
+Deleted all object stores.
+db.createObjectStore('storeName', null)
+store.createIndex('indexName', 'x')
+store.add({x: 'value', y: 'zzz'}, 'key')
+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
+
+event.source.add({x: 'value2', y: 'zzz2'}, 'key2')
+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
+
+indexObject.getKey('value')
+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
+
+PASS event.result is "key"
+indexObject.get('value')
+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
+
+PASS event.result.x is "value"
+PASS event.result.y is "zzz"
+indexObject.getKey('does not exist')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+Error event fired:
+PASS 'result' in event is false
+PASS 'code' in event is true
+PASS 'message' in event is true
+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
+
+PASS event.code is webkitIDBDatabaseException.NOT_FOUND_ERR
+indexObject.get('does not exist')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+Error event fired:
+PASS 'result' in event is false
+PASS 'code' in event is true
+PASS 'message' in event is true
+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
+
+PASS event.code is webkitIDBDatabaseException.NOT_FOUND_ERR
+indexObject.openKeyCursor()
+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
+
+PASS event.result === null is false
+PASS event.result.key is "value"
+PASS event.result.value is "key"
+event.result.continue()
+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
+
+PASS event.result === null is false
+PASS event.result.key is "value2"
+PASS event.result.value is "key2"
+event.result.continue()
+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
+
+PASS event.result === null is true
+indexObject.openCursor()
+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
+
+PASS event.result === null is false
+PASS event.result.key is "value"
+PASS event.result.value.x is "value"
+PASS event.result.value.y is "zzz"
+event.result.continue()
+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
+
+PASS event.result === null is false
+PASS event.result.key is "value2"
+PASS event.result.value.x is "value2"
+PASS event.result.value.y is "zzz2"
+event.result.continue()
+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
+
+PASS event.result === null is true
+webkitIndexedDB.open('name2', 'description2')
+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
+
+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
+Deleted all object stores.
+db.createObjectStore('storeName', null)
+store.createIndex('indexName', 'x')
+store.add({x: 'value', y: 'zzz'}, 'key')
+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
+
+event.source.add({x: 'value2', y: 'zzz2'}, 'key2')
+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
+
+indexObject.getKey('value')
+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
+
+PASS event.result is "key"
+indexObject.get('value')
+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
+
+PASS event.result.x is "value"
+PASS event.result.y is "zzz"
+indexObject.getKey('does not exist')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+Error event fired:
+PASS 'result' in event is false
+PASS 'code' in event is true
+PASS 'message' in event is true
+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
+
+PASS event.code is webkitIDBDatabaseException.NOT_FOUND_ERR
+indexObject.get('does not exist')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+Error event fired:
+PASS 'result' in event is false
+PASS 'code' in event is true
+PASS 'message' in event is true
+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
+
+PASS event.code is webkitIDBDatabaseException.NOT_FOUND_ERR
+indexObject.openKeyCursor()
+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
+
+PASS event.result === null is false
+PASS event.result.key is "value"
+PASS event.result.value is "key"
+event.result.continue()
+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
+
+PASS event.result === null is false
+PASS event.result.key is "value2"
+PASS event.result.value is "key2"
+event.result.continue()
+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
+
+PASS event.result === null is true
+indexObject.openCursor()
+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
+
+PASS event.result === null is false
+PASS event.result.key is "value"
+PASS event.result.value.x is "value"
+PASS event.result.value.y is "zzz"
+event.result.continue()
+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
+
+PASS event.result === null is false
+PASS event.result.key is "value2"
+PASS event.result.value.x is "value2"
+PASS event.result.value.y is "zzz2"
+event.result.continue()
+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
+
+PASS event.result === null is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/duplicates.html b/LayoutTests/storage/indexeddb/duplicates.html
new file mode 100644
index 0000000..70cf8c4
--- /dev/null
+++ b/LayoutTests/storage/indexeddb/duplicates.html
@@ -0,0 +1,213 @@
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="../../fast/js/resources/js-test-post-function.js"></script>
+<script src="resources/shared.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+
+description("Verify that you can put the same data in 2 different databases without uniqueness constraints firing.");
+if (window.layoutTestController) 
+    layoutTestController.waitUntilDone();
+
+testCount = 0;
+function test()
+{
+    if (testCount++ == 0)
+        result = evalAndLog("webkitIndexedDB.open('name', 'description')");
+    else
+        result = evalAndLog("webkitIndexedDB.open('name2', 'description2')");
+    verifyResult(result);
+    result.onsuccess = setVersion;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function setVersion()
+{
+    verifySuccessEvent(event);
+    db = evalAndLog("db = event.result");
+
+    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, createIndex);
+}
+
+function createIndex()
+{
+    window.store = evalAndLog("db.createObjectStore('storeName', null)");
+    window.indexObject = evalAndLog("store.createIndex('indexName', 'x')");
+    addData();
+}
+
+function addData()
+{
+    result = evalAndLog("store.add({x: 'value', y: 'zzz'}, 'key')");
+    verifyResult(result);
+    result.onsuccess = addMore;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function addMore()
+{
+    verifySuccessEvent(event);
+
+    result = evalAndLog("event.source.add({x: 'value2', y: 'zzz2'}, 'key2')");
+    verifyResult(result);
+    result.onsuccess = getData;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function getData()
+{
+    verifySuccessEvent(event);
+
+    result = evalAndLog("indexObject.getKey('value')");
+    verifyResult(result);
+    result.onsuccess = getObjectData;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function getObjectData()
+{
+    verifySuccessEvent(event);
+    shouldBeEqualToString("event.result", "key");
+
+    result = evalAndLog("indexObject.get('value')");
+    verifyResult(result);
+    result.onsuccess = getDataFail;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function getDataFail()
+{
+    verifySuccessEvent(event);
+    shouldBeEqualToString("event.result.x", "value");
+    shouldBeEqualToString("event.result.y", "zzz");
+
+    result = evalAndLog("indexObject.getKey('does not exist')");
+    verifyResult(result);
+    result.onsuccess = unexpectedSuccessCallback;
+    result.onerror = getObjectDataFail;
+}
+
+function getObjectDataFail()
+{
+    verifyErrorEvent(event);
+    shouldBe("event.code", "webkitIDBDatabaseException.NOT_FOUND_ERR");
+
+    result = evalAndLog("indexObject.get('does not exist')");
+    verifyResult(result);
+    result.onsuccess = unexpectedSuccessCallback;
+    result.onerror = openKeyCursor;
+}
+
+function openKeyCursor()
+{
+    verifyErrorEvent(event);
+    shouldBe("event.code", "webkitIDBDatabaseException.NOT_FOUND_ERR");
+
+    window.result = evalAndLog("indexObject.openKeyCursor()");
+    verifyResult(result);
+    result.onsuccess = cursor1Continue;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function cursor1Continue()
+{
+    verifySuccessEvent(event);
+    shouldBeFalse("event.result === null");
+    shouldBeEqualToString("event.result.key", "value");
+    shouldBeEqualToString("event.result.value", "key");
+
+    // We re-use the last result object.
+    evalAndLog("event.result.continue()");
+    verifyResult(window.result);
+    window.result.onsuccess = cursor1Continue2;
+}
+
+function cursor1Continue2()
+{
+    verifySuccessEvent(event);
+    shouldBeFalse("event.result === null");
+    shouldBeEqualToString("event.result.key", "value2");
+    shouldBeEqualToString("event.result.value", "key2");
+
+    // We re-use the last result object.
+    evalAndLog("event.result.continue()");
+    verifyResult(window.result);
+    window.result.onsuccess = openObjectCursor;
+}
+
+function openObjectCursor()
+{
+    verifySuccessEvent(event);
+    shouldBeTrue("event.result === null");
+
+    window.result = evalAndLog("indexObject.openCursor()");
+    verifyResult(result);
+    result.onsuccess = cursor2Continue;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function cursor2Continue()
+{
+    verifySuccessEvent(event);
+    shouldBeFalse("event.result === null");
+    shouldBeEqualToString("event.result.key", "value");
+    shouldBeEqualToString("event.result.value.x", "value");
+    shouldBeEqualToString("event.result.value.y", "zzz");
+
+    // We re-use the last result object.
+    evalAndLog("event.result.continue()");
+    verifyResult(window.result);
+    window.result.onsuccess = cursor2Continue2;
+}
+
+function cursor2Continue2()
+{
+    verifySuccessEvent(event);
+    shouldBeFalse("event.result === null");
+    shouldBeEqualToString("event.result.key", "value2");
+    shouldBeEqualToString("event.result.value.x", "value2");    
+    shouldBeEqualToString("event.result.value.y", "zzz2");
+
+    // We re-use the last result object.
+    evalAndLog("event.result.continue()");
+    verifyResult(window.result);
+    window.result.onsuccess = last;
+}
+
+function last()
+{
+    verifySuccessEvent(event);
+    shouldBeTrue("event.result === null");
+
+    if (testCount == 1)
+        test();
+    else
+        done();
+}
+
+test();
+
+var successfullyParsed = true;
+
+</script>
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 2527c4b..94dbde8 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,63 @@
+2010-10-26  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
+        Quota for IndexedDB should be per origin not per database
+        https://bugs.webkit.org/show_bug.cgi?id=48064
+
+        Merge all databases for each origin into a single SQLiteDatabase.
+
+        Replace the awkward metaData table with a Database table.
+
+        Create a new IDBSQLiteDatabase class that wraps SQLiteDatabase
+        and implements weak pointer semantics for IDBFactory. It's ref
+        counted so multiple IDBDatabaseBackendImpls can share one.
+
+        Fix uniqueness constraints that were overly conservitive.
+
+        Get rid of the code that blows away existing data every time
+        the database is opened.
+
+        Get rid of the fairly useless indexedDB manual test and replace
+        it with one that verifies data persists.
+
+        Use name+origin (not just name) in our cache of IDBDatabaseBackend
+        objects (so one origin can't access anothers' data).
+
+        Test: storage/indexeddb/duplicates.html
+
+        * WebCore.gypi:
+        * manual-tests/indexed-database.html: Removed.
+        * manual-tests/indexeddb-persists.html: Added.
+        * storage/IDBDatabaseBackendImpl.cpp:
+        (WebCore::extractMetaData):
+        (WebCore::setMetaData):
+        (WebCore::IDBDatabaseBackendImpl::IDBDatabaseBackendImpl):
+        (WebCore::IDBDatabaseBackendImpl::setDescription):
+        (WebCore::IDBDatabaseBackendImpl::sqliteDatabase):
+        (WebCore::IDBDatabaseBackendImpl::createObjectStoreInternal):
+        (WebCore::IDBDatabaseBackendImpl::setVersionInternal):
+        (WebCore::IDBDatabaseBackendImpl::loadObjectStores):
+        * storage/IDBDatabaseBackendImpl.h:
+        (WebCore::IDBDatabaseBackendImpl::create):
+        (WebCore::IDBDatabaseBackendImpl::id):
+        * storage/IDBFactoryBackendImpl.cpp:
+        (WebCore::IDBFactoryBackendImpl::removeSQLiteDatabase):
+        (WebCore::openSQLiteDatabase):
+        (WebCore::createTables):
+        (WebCore::IDBFactoryBackendImpl::open):
+        (WebCore::IDBFactoryBackendImpl::databaseFileName):
+        * storage/IDBFactoryBackendImpl.h:
+        * storage/IDBObjectStoreBackendImpl.cpp:
+        (WebCore::putObjectStoreData):
+        (WebCore::IDBObjectStoreBackendImpl::putInternal):
+        * storage/IDBSQLiteDatabase.cpp: Added.
+        (WebCore::IDBSQLiteDatabase::IDBSQLiteDatabase):
+        (WebCore::IDBSQLiteDatabase::~IDBSQLiteDatabase):
+        * storage/IDBSQLiteDatabase.h: Added.
+        (WebCore::IDBSQLiteDatabase::create):
+        (WebCore::IDBSQLiteDatabase::db):
+
 2010-10-20  Andrey Kosyakov  <caseq at chromium.org>
 
         Reviewed by Yury Semikhatsky.
diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi
index 1b8cabe..f526d07 100644
--- a/WebCore/WebCore.gypi
+++ b/WebCore/WebCore.gypi
@@ -3852,6 +3852,8 @@
             'storage/IDBPendingTransactionMonitor.h',
             'storage/IDBRequest.cpp',
             'storage/IDBRequest.h',
+            'storage/IDBSQLiteDatabase.cpp',
+            'storage/IDBSQLiteDatabase.h',
             'storage/IDBSuccessEvent.cpp',
             'storage/IDBSuccessEvent.h',
             'storage/IDBTimeoutEvent.cpp',
diff --git a/WebCore/manual-tests/indexed-database.html b/WebCore/manual-tests/indexed-database.html
deleted file mode 100644
index da2a1e1..0000000
--- a/WebCore/manual-tests/indexed-database.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<html>
-<body>
-<p>This is a test that only applies to IndexedDB.  <span id=enabled>Our test for whether you have it enabled seems to have failed.</span></p>
-
-<p>Please follow these steps in order:</p>
-
-<p>First, click <a href="javascript: doOpen(true)">here</a> to open an indexedDB database.  Look in the proper place in your file system (the place being specific to each port) and verify a file was created.  You should be able to open the file up with sqlite and examine it that way as well.</p>
-
-<p>Next, close the browser, delete the file, replace it with some garbage, and make it read only to the user the browser is running as.  Now click <a href="javascript: doOpen(false)">here</a>.  You should get some sort of error.</p>
-
-<p>Close the browser, delete the file you made, and click <a href="javascript: doOpen(true)">here</a>.  All should be well again.</p>
-
-<p>Status: <span id=status>...</span></p>
-
-<script>
-
-if (!('indexedDB' in window))
-    document.getElementById("enabled").innerHTML = "<font color=red>Your build does NOT seem to have it enabled.  So all code on this page is disabled.</font>";
-else
-    document.getElementById("enabled").innerHTML = "<font color=green>Your build seems to have it enabled.</font>";
-
-function status(str, color)
-{
-    if (color)
-        str = "<font color='" + color + "'>" + str + "</font>";
-    document.getElementById("status").innerHTML = str;
-}
-
-function doOpen(expectSuccess)
-{
-    status("Calling open");
-    request = indexedDB.open("xyz");
-    request.onsuccess = function() {
-        if (expectSuccess)
-            status("Open successful", "green");        
-        else
-            status("Open was successful...but shouldn't have been", "red");        
-    };
-    request.onerror = function() {
-        if (expectSuccess)
-            status("Unexpected error: " + event.message, "red");
-        else
-            status("Expected error: " + event.message, "green");
-    };
-}
-
-</script>
-</body>
-</html>
diff --git a/WebCore/manual-tests/indexeddb-persists.html b/WebCore/manual-tests/indexeddb-persists.html
new file mode 100644
index 0000000..6f5e036
--- /dev/null
+++ b/WebCore/manual-tests/indexeddb-persists.html
@@ -0,0 +1,69 @@
+<html>
+<body>
+<p>This is a test that only applies to IndexedDB.  <span id=enabled>Our test for whether you have it enabled seems to have failed.</span></p>
+
+<p>Please follow these steps in order:</p>
+
+<p>First, click <a href="javascript: setData()">here</a> to open a database and set some data within it.</p>
+
+<p>Next, close the browser and then re-open this page.</p>
+
+<p>Lastly, click <a href="javascript: verifyData()">here</a> to verify the data was there</p>
+
+<p>Status: <span id=status>...</span></p>
+
+<script>
+
+if (!('webkitIndexedDB' in window))
+    document.getElementById("enabled").innerHTML = "<font color=red>Your build does NOT seem to have it enabled.  So all code on this page is disabled.</font>";
+else
+    document.getElementById("enabled").innerHTML = "<font color=green>Your build seems to have it enabled.</font>";
+
+function status(str, color)
+{
+    if (color)
+        str = "<font color='" + color + "'>" + str + "</font>";
+    document.getElementById("status").innerHTML = str;
+}
+
+function setData()
+{
+    status("Something must have gone wrong (or we're still working)...", "red");
+
+    webkitIndexedDB.open("someDB", "some description").onsuccess = function() {
+        event.result.setVersion("some version").onsuccess = function() {
+            var db = event.source;
+            while (db.objectStores.length)
+                db.removeObjectStore(db.objectStores[0]);
+            db.createObjectStore("test").put("value", "key").onsuccess = function() {
+                status("Value set", "green");
+            }
+        }
+    }
+}
+
+function verifyData()
+{
+    status("Something must have gone wrong (or we're still working)...", "red");
+
+    webkitIndexedDB.open("someDB", "some description").onsuccess = function() {
+        try {
+            var result = event.result.transaction([]).objectStore("test").get("key");
+            result.onsuccess = function() {
+                if (event.result == "value")
+                    status("Value verified", "green");
+                else
+                    status("Value incorrect!", "red");
+            }
+            result.onerror = function() {
+                status("An error occurred: " + event.code + " " + event.message, "red");
+            }
+        } catch (e) {
+            status("An exception occurred: " + e, "red");
+        }
+    }
+}
+
+</script>
+</body>
+</html>
diff --git a/WebCore/storage/IDBDatabaseBackendImpl.cpp b/WebCore/storage/IDBDatabaseBackendImpl.cpp
index dc61e22..020ddb9 100644
--- a/WebCore/storage/IDBDatabaseBackendImpl.cpp
+++ b/WebCore/storage/IDBDatabaseBackendImpl.cpp
@@ -32,60 +32,65 @@
 #include "DOMStringList.h"
 #include "IDBDatabaseException.h"
 #include "IDBObjectStoreBackendImpl.h"
+#include "IDBSQLiteDatabase.h"
 #include "IDBTransactionBackendInterface.h"
 #include "IDBTransactionCoordinator.h"
-#include "SQLiteDatabase.h"
 #include "SQLiteStatement.h"
 #include "SQLiteTransaction.h"
 
 namespace WebCore {
 
-static bool extractMetaData(SQLiteDatabase* sqliteDatabase, const String& expectedName, String& foundVersion)
+static bool extractMetaData(SQLiteDatabase& sqliteDatabase, const String& name, String& foundVersion, int64& foundId)
 {
-    SQLiteStatement metaDataQuery(*sqliteDatabase, "SELECT name, version FROM MetaData");
-    if (metaDataQuery.prepare() != SQLResultOk || metaDataQuery.step() != SQLResultRow)
-        return false;
-
-    if (metaDataQuery.getColumnText(0) != expectedName) {
-        LOG_ERROR("Name in MetaData (%s) doesn't match expected (%s) for IndexedDB", metaDataQuery.getColumnText(0).utf8().data(), expectedName.utf8().data());
+    SQLiteStatement databaseQuery(sqliteDatabase, "SELECT id, version FROM Databases WHERE name = ?");
+    if (databaseQuery.prepare() != SQLResultOk) {
         ASSERT_NOT_REACHED();
+        return false;
     }
-    foundVersion = metaDataQuery.getColumnText(1);
+    databaseQuery.bindText(1, name);
+    if (databaseQuery.step() != SQLResultRow)
+        return false;
 
-    if (metaDataQuery.step() == SQLResultRow) {
-        LOG_ERROR("More than one row found in MetaData table");
-        ASSERT_NOT_REACHED();
-    }
+    foundId = databaseQuery.getColumnInt64(0);
+    foundVersion = databaseQuery.getColumnText(1);
 
+    if (databaseQuery.step() == SQLResultRow)
+        ASSERT_NOT_REACHED();
     return true;
 }
 
-static bool setMetaData(SQLiteDatabase* sqliteDatabase, const String& name, const String& description, const String& version)
+static bool setMetaData(SQLiteDatabase& sqliteDatabase, const String& name, const String& description, const String& version, int64_t& rowId)
 {
-    ASSERT(!name.isNull() && !description.isNull() && !version.isNull());
-
-    sqliteDatabase->executeCommand("DELETE FROM MetaData");
-
-    SQLiteStatement insert(*sqliteDatabase, "INSERT INTO MetaData (name, description, version) VALUES (?, ?, ?)");
-    if (insert.prepare() != SQLResultOk) {
-        LOG_ERROR("Failed to prepare MetaData insert statement for IndexedDB");
+    ASSERT(!name.isNull());
+    ASSERT(!description.isNull());
+    ASSERT(!version.isNull());
+
+    String sql = rowId != IDBDatabaseBackendImpl::InvalidId ? "UPDATE Databases SET name = ?, description = ?, version = ? WHERE id = ?"
+                                                            : "INSERT INTO Databases (name, description, version) VALUES (?, ?, ?)";
+    SQLiteStatement query(sqliteDatabase, sql);
+    if (query.prepare() != SQLResultOk) {
+        ASSERT_NOT_REACHED();
         return false;
     }
 
-    insert.bindText(1, name);
-    insert.bindText(2, description);
-    insert.bindText(3, version);
+    query.bindText(1, name);
+    query.bindText(2, description);
+    query.bindText(3, version);
+    if (rowId != IDBDatabaseBackendImpl::InvalidId)
+        query.bindInt64(4, rowId);
 
-    if (insert.step() != SQLResultDone) {
-        LOG_ERROR("Failed to insert row into MetaData for IndexedDB");
+    if (query.step() != SQLResultDone)
         return false;
-    }
+
+    if (rowId == IDBDatabaseBackendImpl::InvalidId)
+        rowId = sqliteDatabase.lastInsertRowID();
 
     return true;
 }
 
-IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, const String& description, PassOwnPtr<SQLiteDatabase> sqliteDatabase, IDBTransactionCoordinator* coordinator)
+IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, const String& description, IDBSQLiteDatabase* sqliteDatabase, IDBTransactionCoordinator* coordinator)
     : m_sqliteDatabase(sqliteDatabase)
+    , m_id(InvalidId)
     , m_name(name)
     , m_description(description)
     , m_version("")
@@ -94,9 +99,10 @@ IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, const String&
     ASSERT(!m_name.isNull());
     ASSERT(!m_description.isNull());
 
-    extractMetaData(m_sqliteDatabase.get(), m_name, m_version);
-    setMetaData(m_sqliteDatabase.get(), m_name, m_description, m_version);
-
+    bool success = extractMetaData(m_sqliteDatabase->db(), m_name, m_version, m_id);
+    ASSERT_UNUSED(success, success == (m_id != InvalidId));
+    if (!setMetaData(m_sqliteDatabase->db(), m_name, m_description, m_version, m_id))
+        ASSERT_NOT_REACHED(); // FIXME: Need better error handling.
     loadObjectStores();
 }
 
@@ -110,7 +116,12 @@ void IDBDatabaseBackendImpl::setDescription(const String& description)
         return;
 
     m_description = description;
-    setMetaData(m_sqliteDatabase.get(), m_name, m_description, m_version);
+    setMetaData(m_sqliteDatabase->db(), m_name, m_description, m_version, m_id);
+}
+
+SQLiteDatabase& IDBDatabaseBackendImpl::sqliteDatabase() const
+{
+    return m_sqliteDatabase->db();
 }
 
 PassRefPtr<DOMStringList> IDBDatabaseBackendImpl::objectStores() const
@@ -144,7 +155,7 @@ PassRefPtr<IDBObjectStoreBackendInterface>  IDBDatabaseBackendImpl::createObject
 
 void IDBDatabaseBackendImpl::createObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore,  PassRefPtr<IDBTransactionBackendInterface> transaction)
 {
-    SQLiteStatement insert(database->sqliteDatabase(), "INSERT INTO ObjectStores (name, keyPath, doAutoIncrement) VALUES (?, ?, ?)");
+    SQLiteStatement insert(database->sqliteDatabase(), "INSERT INTO ObjectStores (name, keyPath, doAutoIncrement, databaseId) VALUES (?, ?, ?, ?)");
     if (insert.prepare() != SQLResultOk) {
         transaction->abort();
         return;
@@ -152,6 +163,7 @@ void IDBDatabaseBackendImpl::createObjectStoreInternal(ScriptExecutionContext*,
     insert.bindText(1, objectStore->name());
     insert.bindText(2, objectStore->keyPath());
     insert.bindInt(3, static_cast<int>(objectStore->autoIncrement()));
+    insert.bindInt64(4, database->id());
     if (insert.step() != SQLResultDone) {
         transaction->abort();
         return;
@@ -217,8 +229,9 @@ void IDBDatabaseBackendImpl::setVersion(const String& version, PassRefPtr<IDBCal
 
 void IDBDatabaseBackendImpl::setVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, const String& version, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendInterface> transaction)
 {
+    int64_t databaseId = database->id();
     database->m_version = version;
-    if (!setMetaData(database->m_sqliteDatabase.get(), database->m_name, database->m_description, database->m_version)) {
+    if (!setMetaData(database->m_sqliteDatabase->db(), database->m_name, database->m_description, database->m_version, databaseId)) {
         // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
         transaction->abort();
@@ -240,10 +253,12 @@ void IDBDatabaseBackendImpl::close()
 
 void IDBDatabaseBackendImpl::loadObjectStores()
 {
-    SQLiteStatement objectStoresQuery(sqliteDatabase(), "SELECT id, name, keyPath, doAutoIncrement FROM ObjectStores");
+    SQLiteStatement objectStoresQuery(sqliteDatabase(), "SELECT id, name, keyPath, doAutoIncrement FROM ObjectStores WHERE databaseId = ?");
     bool ok = objectStoresQuery.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
+    objectStoresQuery.bindInt64(1, m_id);
+
     while (objectStoresQuery.step() == SQLResultRow) {
         int64_t id = objectStoresQuery.getColumnInt64(0);
         String name = objectStoresQuery.getColumnText(1);
diff --git a/WebCore/storage/IDBDatabaseBackendImpl.h b/WebCore/storage/IDBDatabaseBackendImpl.h
index bb6429c..53e1a5f 100644
--- a/WebCore/storage/IDBDatabaseBackendImpl.h
+++ b/WebCore/storage/IDBDatabaseBackendImpl.h
@@ -36,19 +36,23 @@
 namespace WebCore {
 
 class IDBObjectStoreBackendImpl;
+class IDBSQLiteDatabase;
 class IDBTransactionCoordinator;
 class SQLiteDatabase;
 
 class IDBDatabaseBackendImpl : public IDBDatabaseBackendInterface {
 public:
-    static PassRefPtr<IDBDatabaseBackendImpl> create(const String& name, const String& description, PassOwnPtr<SQLiteDatabase> database, IDBTransactionCoordinator* coordinator)
+    static PassRefPtr<IDBDatabaseBackendImpl> create(const String& name, const String& description, IDBSQLiteDatabase* database, IDBTransactionCoordinator* coordinator)
     {
         return adoptRef(new IDBDatabaseBackendImpl(name, description, database, coordinator));
     }
     virtual ~IDBDatabaseBackendImpl();
 
     void setDescription(const String& description);
-    SQLiteDatabase& sqliteDatabase() const { return *m_sqliteDatabase.get(); }
+    SQLiteDatabase& sqliteDatabase() const;
+
+    static const int64_t InvalidId = 0;
+    int64_t id() const { return m_id; }
 
     virtual String name() const { return m_name; }
     virtual String description() const { return m_description; }
@@ -65,7 +69,7 @@ public:
     IDBTransactionCoordinator* transactionCoordinator() const { return m_transactionCoordinator.get(); }
 
 private:
-    IDBDatabaseBackendImpl(const String& name, const String& description, PassOwnPtr<SQLiteDatabase> database, IDBTransactionCoordinator*);
+    IDBDatabaseBackendImpl(const String& name, const String& description, IDBSQLiteDatabase* database, IDBTransactionCoordinator*);
 
     void loadObjectStores();
 
@@ -78,7 +82,8 @@ private:
     static void addObjectStoreToMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, PassRefPtr<IDBObjectStoreBackendImpl>);
     static void resetVersion(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl>, const String& version);
 
-    OwnPtr<SQLiteDatabase> m_sqliteDatabase;
+    RefPtr<IDBSQLiteDatabase> m_sqliteDatabase;
+    int64 m_id;
     String m_name;
     String m_description;
     String m_version;
diff --git a/WebCore/storage/IDBFactoryBackendImpl.cpp b/WebCore/storage/IDBFactoryBackendImpl.cpp
index c18294d..1905c0c 100644
--- a/WebCore/storage/IDBFactoryBackendImpl.cpp
+++ b/WebCore/storage/IDBFactoryBackendImpl.cpp
@@ -33,8 +33,8 @@
 #include "FileSystem.h"
 #include "IDBDatabaseBackendImpl.h"
 #include "IDBDatabaseException.h"
+#include "IDBSQLiteDatabase.h"
 #include "IDBTransactionCoordinator.h"
-#include "SQLiteDatabase.h"
 #include "SecurityOrigin.h"
 #include <wtf/Threading.h>
 #include <wtf/UnusedParam.h>
@@ -52,7 +52,13 @@ IDBFactoryBackendImpl::~IDBFactoryBackendImpl()
 {
 }
 
-static PassOwnPtr<SQLiteDatabase> openSQLiteDatabase(SecurityOrigin* securityOrigin, String name, const String& pathBase, int64_t maximumSize)
+void IDBFactoryBackendImpl::removeSQLiteDatabase(const String& filePath)
+{
+    ASSERT(m_sqliteDatabaseMap.contains(filePath));
+    m_sqliteDatabaseMap.remove(filePath);
+}
+
+static PassRefPtr<IDBSQLiteDatabase> openSQLiteDatabase(SecurityOrigin* securityOrigin, const String& pathBase, int64_t maximumSize, const String& fileIdentifier, IDBFactoryBackendImpl* factory)
 {
     String path = ":memory:";
     if (!pathBase.isEmpty()) {
@@ -62,54 +68,46 @@ static PassOwnPtr<SQLiteDatabase> openSQLiteDatabase(SecurityOrigin* securityOri
             return 0;
         }
 
-        path = pathByAppendingComponent(pathBase, IDBFactoryBackendImpl::databaseFileName(name, securityOrigin));
+        path = pathByAppendingComponent(pathBase, IDBFactoryBackendImpl::databaseFileName(securityOrigin));
     }
 
-    OwnPtr<SQLiteDatabase> sqliteDatabase = adoptPtr(new SQLiteDatabase());
-    if (!sqliteDatabase->open(path)) {
+    RefPtr<IDBSQLiteDatabase> sqliteDatabase = IDBSQLiteDatabase::create(fileIdentifier, factory);
+    if (!sqliteDatabase->db().open(path)) {
         // FIXME: Is there any other thing we could possibly do to recover at this point? If so, do it rather than just erroring out.
         LOG_ERROR("Failed to open database file %s for IndexedDB", path.utf8().data());
         return 0;
     }
 
-    sqliteDatabase->setMaximumSize(maximumSize);
+    // FIXME: Error checking?
+    sqliteDatabase->db().setMaximumSize(maximumSize);
+    sqliteDatabase->db().turnOnIncrementalAutoVacuum();
+
     return sqliteDatabase.release();
 }
 
-static bool createTables(SQLiteDatabase* sqliteDatabase)
+static bool createTables(SQLiteDatabase& sqliteDatabase)
 {
-    // FIXME: Remove all the drop table commands once the on disk structure stabilizes.
     static const char* commands[] = {
-        "DROP TABLE IF EXISTS MetaData",
-        "CREATE TABLE IF NOT EXISTS MetaData (id INTEGER PRIMARY KEY, name TEXT NOT NULL, description TEXT NOT NULL, version TEXT NOT NULL)",
+        "CREATE TABLE IF NOT EXISTS Databases (id INTEGER PRIMARY KEY, name TEXT NOT NULL, description TEXT NOT NULL, version TEXT NOT NULL)",
+        "CREATE UNIQUE INDEX IF NOT EXISTS Databases_name ON Databases(name)",
 
-        "DROP TABLE IF EXISTS ObjectStores",
-        "CREATE TABLE IF NOT EXISTS ObjectStores (id INTEGER PRIMARY KEY, name TEXT NOT NULL UNIQUE, keyPath TEXT, doAutoIncrement INTEGER NOT NULL)",
-        "DROP INDEX IF EXISTS ObjectStores_name",
-        "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStores_name ON ObjectStores(name)",
+        "CREATE TABLE IF NOT EXISTS ObjectStores (id INTEGER PRIMARY KEY, name TEXT NOT NULL, keyPath TEXT, doAutoIncrement INTEGER NOT NULL, databaseId INTEGER NOT NULL REFERENCES Databases(id))",
+        "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStores_composit ON ObjectStores(databaseId, name)",
 
-        "DROP TABLE IF EXISTS Indexes",
-        "CREATE TABLE IF NOT EXISTS Indexes (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), name TEXT NOT NULL UNIQUE, keyPath TEXT, isUnique INTEGER NOT NULL)",
-        "DROP INDEX IF EXISTS Indexes_composit",
+        "CREATE TABLE IF NOT EXISTS Indexes (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), name TEXT NOT NULL, keyPath TEXT, isUnique INTEGER NOT NULL)",
         "CREATE UNIQUE INDEX IF NOT EXISTS Indexes_composit ON Indexes(objectStoreId, name)",
 
-        "DROP TABLE IF EXISTS ObjectStoreData",
-        "CREATE TABLE IF NOT EXISTS ObjectStoreData (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), keyString TEXT UNIQUE, keyDate INTEGER UNIQUE, keyNumber INTEGER UNIQUE, value TEXT NOT NULL)",
-        "DROP INDEX IF EXISTS ObjectStoreData_composit",
+        "CREATE TABLE IF NOT EXISTS ObjectStoreData (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), keyString TEXT, keyDate INTEGER, keyNumber INTEGER, value TEXT NOT NULL)",
         "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStoreData_composit ON ObjectStoreData(keyString, keyDate, keyNumber, objectStoreId)",
 
-        "DROP TABLE IF EXISTS IndexData",
         "CREATE TABLE IF NOT EXISTS IndexData (id INTEGER PRIMARY KEY, indexId INTEGER NOT NULL REFERENCES Indexes(id), keyString TEXT, keyDate INTEGER, keyNumber INTEGER, objectStoreDataId INTEGER NOT NULL REFERENCES ObjectStoreData(id))",
-        "DROP INDEX IF EXISTS IndexData_composit",
         "CREATE INDEX IF NOT EXISTS IndexData_composit ON IndexData(keyString, keyDate, keyNumber, indexId)",
-        "DROP INDEX IF EXISTS IndexData_objectStoreDataId",
         "CREATE INDEX IF NOT EXISTS IndexData_objectStoreDataId ON IndexData(objectStoreDataId)",
-        "DROP INDEX IF EXISTS IndexData_indexId",
         "CREATE INDEX IF NOT EXISTS IndexData_indexId ON IndexData(indexId)"
         };
 
     for (size_t i = 0; i < arraysize(commands); ++i) {
-        if (!sqliteDatabase->executeCommand(commands[i])) {
+        if (!sqliteDatabase.executeCommand(commands[i])) {
             // FIXME: We should try to recover from this situation. Maybe nuke the database and start over?
             LOG_ERROR("Failed to run the following command for IndexedDB: %s", commands[i]);
             return false;
@@ -120,7 +118,9 @@ static bool createTables(SQLiteDatabase* sqliteDatabase)
 
 void IDBFactoryBackendImpl::open(const String& name, const String& description, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> securityOrigin, Frame*, const String& dataDir, int64_t maximumSize)
 {
-    IDBDatabaseBackendMap::iterator it = m_databaseBackendMap.find(name);
+    String fileIdentifier = securityOrigin->databaseIdentifier();
+    String uniqueIdentifier = fileIdentifier + "@" + name;
+    IDBDatabaseBackendMap::iterator it = m_databaseBackendMap.find(uniqueIdentifier);
     if (it != m_databaseBackendMap.end()) {
         if (!description.isNull())
             it->second->setDescription(description); // The description may have changed.
@@ -130,22 +130,29 @@ void IDBFactoryBackendImpl::open(const String& name, const String& description,
 
     // FIXME: Everything from now on should be done on another thread.
 
-    OwnPtr<SQLiteDatabase> sqliteDatabase = openSQLiteDatabase(securityOrigin.get(), name, dataDir, maximumSize);
-    if (!sqliteDatabase || !createTables(sqliteDatabase.get())) {
-        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
-        return;
+    RefPtr<IDBSQLiteDatabase> sqliteDatabase;
+    SQLiteDatabaseMap::iterator it2 = m_sqliteDatabaseMap.find(fileIdentifier);
+    if (it2 != m_sqliteDatabaseMap.end())
+        sqliteDatabase = it2->second;
+    else {
+        sqliteDatabase = openSQLiteDatabase(securityOrigin.get(), dataDir, maximumSize, fileIdentifier, this);
+
+        if (!sqliteDatabase || !createTables(sqliteDatabase->db())) {
+            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
+            return;
+        }
+        m_sqliteDatabaseMap.set(fileIdentifier, sqliteDatabase.get());
     }
 
-    RefPtr<IDBDatabaseBackendImpl> databaseBackend = IDBDatabaseBackendImpl::create(name, description, sqliteDatabase.release(), m_transactionCoordinator.get());
+    RefPtr<IDBDatabaseBackendImpl> databaseBackend = IDBDatabaseBackendImpl::create(name, description, sqliteDatabase.get(), m_transactionCoordinator.get());
     callbacks->onSuccess(databaseBackend.get());
-    m_databaseBackendMap.set(name, databaseBackend.release());
+    m_databaseBackendMap.set(uniqueIdentifier, databaseBackend.release());
 }
 
-String IDBFactoryBackendImpl::databaseFileName(const String& name, SecurityOrigin* securityOrigin)
+String IDBFactoryBackendImpl::databaseFileName(SecurityOrigin* securityOrigin)
 {
     String databaseIdentifier = securityOrigin->databaseIdentifier();
-    String santizedName = encodeForFileName(name);
-    return databaseIdentifier + "@" + santizedName + ".indexeddb";
+    return databaseIdentifier + ".indexeddb";
 }
 
 } // namespace WebCore
diff --git a/WebCore/storage/IDBFactoryBackendImpl.h b/WebCore/storage/IDBFactoryBackendImpl.h
index 211b7fa..381c402 100644
--- a/WebCore/storage/IDBFactoryBackendImpl.h
+++ b/WebCore/storage/IDBFactoryBackendImpl.h
@@ -39,6 +39,7 @@ namespace WebCore {
 class DOMStringList;
 
 class IDBDatabaseBackendImpl;
+class IDBSQLiteDatabase;
 class IDBTransactionCoordinator;
 
 class IDBFactoryBackendImpl : public IDBFactoryBackendInterface {
@@ -49,18 +50,26 @@ public:
     }
     virtual ~IDBFactoryBackendImpl();
 
+    // IDBSQLiteDatabase's lifetime may be shorter than ours, so we need notification when it dies.
+    void removeSQLiteDatabase(const String& filePath);
+
     virtual void open(const String& name, const String& description, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, Frame*, const String& dataDir, int64_t maximumSize);
 
-    static String databaseFileName(const String& name, SecurityOrigin*);
+    static String databaseFileName(SecurityOrigin*);
 
 private:
     IDBFactoryBackendImpl();
 
+    // FIXME: Just hold a weak pointer.
     typedef HashMap<String, RefPtr<IDBDatabaseBackendImpl> > IDBDatabaseBackendMap;
     IDBDatabaseBackendMap m_databaseBackendMap;
+
+    typedef HashMap<String, IDBSQLiteDatabase*> SQLiteDatabaseMap;
+    SQLiteDatabaseMap m_sqliteDatabaseMap;
+
     RefPtr<IDBTransactionCoordinator> m_transactionCoordinator;
 
-    // We only create one instance of this class at a time.
+    // Only one instance of the factory should exist at any given time.
     static IDBFactoryBackendImpl* idbFactoryBackendImpl;
 };
 
diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.cpp b/WebCore/storage/IDBObjectStoreBackendImpl.cpp
index f3aee91..fe68ebf 100644
--- a/WebCore/storage/IDBObjectStoreBackendImpl.cpp
+++ b/WebCore/storage/IDBObjectStoreBackendImpl.cpp
@@ -131,25 +131,25 @@ static PassRefPtr<IDBKey> fetchKeyFromKeyPath(SerializedScriptValue* value, cons
     return keys[0].release();
 }
 
-static bool putObjectStoreData(SQLiteDatabase& db, IDBKey* key, SerializedScriptValue* value, int64_t objectStoreId, int64_t* dataRowId)
+static bool putObjectStoreData(SQLiteDatabase& db, IDBKey* key, SerializedScriptValue* value, int64_t objectStoreId, int64_t& dataRowId)
 {
-    String sql = *dataRowId != -1 ? "UPDATE ObjectStoreData SET keyString = ?, keyDate = ?, keyNumber = ?, value = ? WHERE id = ?"
-                                  : "INSERT INTO ObjectStoreData (keyString, keyDate, keyNumber, value, objectStoreId) VALUES (?, ?, ?, ?, ?)";
+    String sql = dataRowId != IDBObjectStoreBackendImpl::InvalidId ? "UPDATE ObjectStoreData SET keyString = ?, keyDate = ?, keyNumber = ?, value = ? WHERE id = ?"
+                                                                   : "INSERT INTO ObjectStoreData (keyString, keyDate, keyNumber, value, objectStoreId) VALUES (?, ?, ?, ?, ?)";
     SQLiteStatement query(db, sql);
     if (query.prepare() != SQLResultOk)
         return false;
     key->bindWithNulls(query, 1);
     query.bindText(4, value->toWireString());
-    if (*dataRowId != -1)
-        query.bindInt(5, *dataRowId);
+    if (dataRowId != IDBDatabaseBackendImpl::InvalidId)
+        query.bindInt64(5, dataRowId);
     else
         query.bindInt64(5, objectStoreId);
 
     if (query.step() != SQLResultDone)
         return false;
 
-    if (*dataRowId == -1)
-        *dataRowId = db.lastInsertRowID();
+    if (dataRowId == IDBDatabaseBackendImpl::InvalidId)
+        dataRowId = db.lastInsertRowID();
 
     return true;
 }
@@ -238,8 +238,8 @@ void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<
 
     // Before this point, don't do any mutation.  After this point, rollback the transaction in case of error.
 
-    int64_t dataRowId = isExistingValue ? getQuery.getColumnInt(0) : -1;
-    if (!putObjectStoreData(objectStore->sqliteDatabase(), key.get(), value.get(), objectStore->id(), &dataRowId)) {
+    int64_t dataRowId = isExistingValue ? getQuery.getColumnInt(0) : InvalidId;
+    if (!putObjectStoreData(objectStore->sqliteDatabase(), key.get(), value.get(), objectStore->id(), dataRowId)) {
         // FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
         transaction->abort();
diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.h b/WebCore/storage/IDBObjectStoreBackendImpl.h
index 09223b1..60e011f 100644
--- a/WebCore/storage/IDBObjectStoreBackendImpl.h
+++ b/WebCore/storage/IDBObjectStoreBackendImpl.h
@@ -52,6 +52,7 @@ public:
     }
     virtual ~IDBObjectStoreBackendImpl();
 
+    static const int64_t InvalidId = 0;
     int64_t id() const
     {
         ASSERT(m_id != InvalidId);
@@ -94,8 +95,6 @@ private:
     static void removeIndexFromMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>);
     static void addIndexToMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>);
 
-    static const int64_t InvalidId = 0;
-
     RefPtr<IDBDatabaseBackendImpl> m_database;
 
     int64_t m_id;
diff --git a/WebCore/storage/IDBSQLiteDatabase.cpp b/WebCore/storage/IDBSQLiteDatabase.cpp
new file mode 100644
index 0000000..e881917
--- /dev/null
+++ b/WebCore/storage/IDBSQLiteDatabase.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IDBSQLiteDatabase.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBFactoryBackendImpl.h"
+
+namespace WebCore {
+
+IDBSQLiteDatabase::IDBSQLiteDatabase(String identifier, IDBFactoryBackendImpl* factory)
+    : m_identifier(identifier)
+    , m_factory(factory)
+{
+}
+
+IDBSQLiteDatabase::~IDBSQLiteDatabase()
+{
+    m_factory->removeSQLiteDatabase(m_identifier);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/WebCore/storage/IDBSQLiteDatabase.h b/WebCore/storage/IDBSQLiteDatabase.h
new file mode 100644
index 0000000..0556506
--- /dev/null
+++ b/WebCore/storage/IDBSQLiteDatabase.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IDBSQLiteDatabase_h
+#define IDBSQLiteDatabase_h
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "SQLiteDatabase.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class IDBFactoryBackendImpl;
+
+class IDBSQLiteDatabase : public RefCounted<IDBSQLiteDatabase> {
+public:
+    static PassRefPtr<IDBSQLiteDatabase> create(String identifier, IDBFactoryBackendImpl* factory)
+    {
+        return adoptRef(new IDBSQLiteDatabase(identifier, factory));
+    }
+    ~IDBSQLiteDatabase();
+
+    SQLiteDatabase& db() { return m_db; }
+
+private:
+    IDBSQLiteDatabase(String identifier, IDBFactoryBackendImpl* factory);
+
+    SQLiteDatabase m_db;
+    String m_identifier;
+    RefPtr<IDBFactoryBackendImpl> m_factory;
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // IDBSQLiteDatabase_h
diff --git a/WebKit/chromium/ChangeLog b/WebKit/chromium/ChangeLog
index 8367446..af59e60 100644
--- a/WebKit/chromium/ChangeLog
+++ b/WebKit/chromium/ChangeLog
@@ -1,3 +1,17 @@
+2010-10-26  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
+        Quota for IndexedDB should be per origin not per database
+        https://bugs.webkit.org/show_bug.cgi?id=48064
+
+        * public/WebIDBFactory.h:
+        * public/WebSecurityOrigin.h:
+        * src/WebIDBFactory.cpp:
+        (WebKit::WebIDBFactory::databaseFileName):
+        * src/WebSecurityOrigin.cpp:
+        (WebKit::WebSecurityOrigin::get):
+
 2010-10-26  Sheriff Bot  <webkit.review.bot at gmail.com>
 
         Unreviewed, rolling out r70512.
diff --git a/WebKit/chromium/public/WebIDBFactory.h b/WebKit/chromium/public/WebIDBFactory.h
index c7fbe02..66ceadb 100755
--- a/WebKit/chromium/public/WebIDBFactory.h
+++ b/WebKit/chromium/public/WebIDBFactory.h
@@ -58,6 +58,8 @@ public:
     }
 
     // The file name that would be used for persisting a given indexed database on the file system.
+    WEBKIT_API static WebString databaseFileName(const WebSecurityOrigin&);
+    // FIXME: Remove after roll.
     WEBKIT_API static WebString databaseFileName(const WebString& name, const WebSecurityOrigin&);
 };
 
diff --git a/WebKit/chromium/public/WebIDBKey.h b/WebKit/chromium/public/WebIDBKey.h
index 60d3325..171fe78 100644
--- a/WebKit/chromium/public/WebIDBKey.h
+++ b/WebKit/chromium/public/WebIDBKey.h
@@ -82,7 +82,6 @@ public:
 #endif
 
 private:
-
     WebPrivatePtr<WebCore::IDBKey> m_private;
 };
 
diff --git a/WebKit/chromium/public/WebSecurityOrigin.h b/WebKit/chromium/public/WebSecurityOrigin.h
index efcb2e9..a241682 100644
--- a/WebKit/chromium/public/WebSecurityOrigin.h
+++ b/WebKit/chromium/public/WebSecurityOrigin.h
@@ -100,6 +100,7 @@ public:
     WebSecurityOrigin(const WTF::PassRefPtr<WebCore::SecurityOrigin>&);
     WebSecurityOrigin& operator=(const WTF::PassRefPtr<WebCore::SecurityOrigin>&);
     operator WTF::PassRefPtr<WebCore::SecurityOrigin>() const;
+    WebCore::SecurityOrigin* get() const;
 #endif
 
 private:
diff --git a/WebKit/chromium/src/WebIDBFactory.cpp b/WebKit/chromium/src/WebIDBFactory.cpp
index b186b68..40eff97 100755
--- a/WebKit/chromium/src/WebIDBFactory.cpp
+++ b/WebKit/chromium/src/WebIDBFactory.cpp
@@ -31,22 +31,23 @@
 #include "config.h"
 #include "WebIDBFactory.h"
 
-#if ENABLE(INDEXED_DATABASE)
-
 #include "IDBFactoryBackendImpl.h"
-#include "SecurityOrigin.h"
+#include "WebSecurityOrigin.h"
+#include <wtf/UnusedParam.h>
 
 using namespace WebCore;
 
 namespace WebKit {
 
-WebString WebIDBFactory::databaseFileName(const WebString& name, const WebSecurityOrigin& origin)
+WebString WebIDBFactory::databaseFileName(const WebSecurityOrigin& origin)
 {
-    RefPtr<SecurityOrigin> securityOrigin;
-    securityOrigin = origin;
-    return IDBFactoryBackendImpl::databaseFileName(name, securityOrigin.get());
+    return IDBFactoryBackendImpl::databaseFileName(origin.get());
 }
 
+WebString WebIDBFactory::databaseFileName(const WebString& name, const WebSecurityOrigin& origin)
+{
+    UNUSED_PARAM(name);
+    return databaseFileName(origin);
 }
 
-#endif // ENABLE(INDEXED_DATABASE)
+}
diff --git a/WebKit/chromium/src/WebSecurityOrigin.cpp b/WebKit/chromium/src/WebSecurityOrigin.cpp
index 8685738..adccb31 100644
--- a/WebKit/chromium/src/WebSecurityOrigin.cpp
+++ b/WebKit/chromium/src/WebSecurityOrigin.cpp
@@ -143,6 +143,11 @@ WebSecurityOrigin::operator WTF::PassRefPtr<WebCore::SecurityOrigin>() const
     return PassRefPtr<SecurityOrigin>(const_cast<WebSecurityOriginPrivate*>(m_private));
 }
 
+SecurityOrigin* WebSecurityOrigin::get() const
+{
+    return m_private;
+}
+
 void WebSecurityOrigin::assign(WebSecurityOriginPrivate* p)
 {
     // p is already ref'd for us by the caller

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list