IndexedDB 2.0: Support IDBObjectStore getAll/getAllKeys.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 31 Oct 2016 23:43:50 +0000 (23:43 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 31 Oct 2016 23:43:50 +0000 (23:43 +0000)
<rdar://problem/28806934> and https://bugs.webkit.org/show_bug.cgi?id=164097

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

* web-platform-tests/IndexedDB/idbobjectstore_getAll-expected.txt:
* web-platform-tests/IndexedDB/idbobjectstore_getAllKeys-expected.txt:

Source/WebCore:

Tests: storage/indexeddb/modern/idbobjectstore-getall-1-private.html
       storage/indexeddb/modern/idbobjectstore-getall-1.html
       storage/indexeddb/modern/idbobjectstore-getallkeys-1-private.html
       storage/indexeddb/modern/idbobjectstore-getallkeys-1.html
       Existing imported W3C tests.

- Add new objects for "IDBGetAllRequestData" and "IDBGetAllResult" to represent these
  new requests and responses.
- Add lots of boilerplate code to move these new objects around in the IDB machinery.
- Update "GetRecord" code to be shared with "GetAll" code where necessary.
- Other tweaks here and there.

* WebCore.xcodeproj/project.pbxproj:
* CMakeLists.txt:

* Modules/indexeddb/IDBGetAllResult.cpp: Added.
(WebCore::isolatedCopyOfVariant):
(WebCore::IDBGetAllResult::isolatedCopy):
(WebCore::IDBGetAllResult::addKey):
(WebCore::IDBGetAllResult::addValue):
(WebCore::IDBGetAllResult::keys):
(WebCore::IDBGetAllResult::values):
(WebCore::IDBGetAllResult::allBlobFilePaths):
* Modules/indexeddb/IDBGetAllResult.h: Added.
(WebCore::IDBGetAllResult::IDBGetAllResult):
(WebCore::IDBGetAllResult::type):
(WebCore::IDBGetAllResult::encode):
(WebCore::IDBGetAllResult::decode):

* Modules/indexeddb/IDBObjectStore.cpp:
(WebCore::IDBObjectStore::getAll):
(WebCore::IDBObjectStore::getAllKeys):
* Modules/indexeddb/IDBObjectStore.h:
* Modules/indexeddb/IDBObjectStore.idl:

* Modules/indexeddb/IDBRequest.cpp:
(WebCore::IDBRequest::setResult):
* Modules/indexeddb/IDBRequest.h:

* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::requestGetAllObjectStoreRecords):
(WebCore::IDBTransaction::getAllRecordsOnServer):
(WebCore::IDBTransaction::didGetAllRecordsOnServer):
* Modules/indexeddb/IDBTransaction.h:

* Modules/indexeddb/IndexedDB.h:

* Modules/indexeddb/client/IDBConnectionProxy.cpp:
(WebCore::IDBClient::IDBConnectionProxy::getAllRecords):
* Modules/indexeddb/client/IDBConnectionProxy.h:

* Modules/indexeddb/client/IDBConnectionToServer.cpp:
(WebCore::IDBClient::IDBConnectionToServer::getAllRecords):
(WebCore::IDBClient::IDBConnectionToServer::didGetAllRecords):
* Modules/indexeddb/client/IDBConnectionToServer.h:
* Modules/indexeddb/client/IDBConnectionToServerDelegate.h:

* Modules/indexeddb/server/IDBBackingStore.h:

* Modules/indexeddb/server/IDBConnectionToClient.cpp:
(WebCore::IDBServer::IDBConnectionToClient::didGetAllRecords):
* Modules/indexeddb/server/IDBConnectionToClient.h:
* Modules/indexeddb/server/IDBConnectionToClientDelegate.h:

* Modules/indexeddb/server/IDBServer.cpp:
(WebCore::IDBServer::IDBServer::getAllRecords):
* Modules/indexeddb/server/IDBServer.h:

* Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
(WebCore::IDBServer::MemoryIDBBackingStore::getAllRecords):
* Modules/indexeddb/server/MemoryIDBBackingStore.h:

* Modules/indexeddb/server/MemoryObjectStore.cpp:
(WebCore::IDBServer::MemoryObjectStore::getAllRecords):
* Modules/indexeddb/server/MemoryObjectStore.h:

* Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
(WebCore::IDBServer::queryForGetAllRecords):
(WebCore::IDBServer::SQLiteIDBBackingStore::getAllRecords):
* Modules/indexeddb/server/SQLiteIDBBackingStore.h:

* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::hasAnyPendingCallbacks):
(WebCore::IDBServer::UniqueIDBDatabase::storeCallbackOrFireError):
(WebCore::IDBServer::UniqueIDBDatabase::getAllRecords):
(WebCore::IDBServer::UniqueIDBDatabase::performGetAllRecords):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformGetAllRecords):
(WebCore::IDBServer::UniqueIDBDatabase::performGetAllResultsCallback):
* Modules/indexeddb/server/UniqueIDBDatabase.h:

* Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::getAllRecords):
* Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h:

* Modules/indexeddb/shared/IDBGetAllRecordsData.cpp: Added.
(WebCore::IDBGetAllRecordsData::isolatedCopy):
* Modules/indexeddb/shared/IDBGetAllRecordsData.h: Added.
(WebCore::IDBGetAllRecordsData::encode):
(WebCore::IDBGetAllRecordsData::decode):

* Modules/indexeddb/shared/IDBResultData.cpp:
(WebCore::IDBResultData::IDBResultData):
(WebCore::IDBResultData::getAllRecordsSuccess):
(WebCore::IDBResultData::getAllResult):
* Modules/indexeddb/shared/IDBResultData.h:
(WebCore::IDBResultData::encode):
(WebCore::IDBResultData::decode):

* Modules/indexeddb/shared/InProcessIDBServer.cpp:
(WebCore::InProcessIDBServer::didGetAllRecords):
(WebCore::InProcessIDBServer::getAllRecords):
* Modules/indexeddb/shared/InProcessIDBServer.h:

* bindings/js/IDBBindingUtilities.cpp:
(WebCore::deserializeIDBValueToJSValue):
(WebCore::toJS):
* bindings/js/IDBBindingUtilities.h:

Source/WebKit2:

- Handle moving "Get All" requests to and from the DatabaseProcess.
- Handle the additional task of creating/passing Sandbox Extensions for
  referenced files when necessary.

* DatabaseProcess/IndexedDB/WebIDBConnectionToClient.cpp:
(WebKit::WebIDBConnectionToClient::handleGetResult):
(WebKit::WebIDBConnectionToClient::didGetAllRecords):
(WebKit::WebIDBConnectionToClient::getAllRecords):
* DatabaseProcess/IndexedDB/WebIDBConnectionToClient.h:
* DatabaseProcess/IndexedDB/WebIDBConnectionToClient.messages.in:

* Shared/WebCoreArgumentCoders.h:

* WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.cpp:
(WebKit::WebIDBConnectionToServer::getAllRecords):
(WebKit::preregisterSandboxExtensionsIfNecessary):
(WebKit::WebIDBConnectionToServer::didGetAllRecords):
* WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.h:
* WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.messages.in:

LayoutTests:

* storage/indexeddb/modern/idbobjectstore-getall-1-expected.txt: Added.
* storage/indexeddb/modern/idbobjectstore-getall-1-private-expected.txt: Added.
* storage/indexeddb/modern/idbobjectstore-getall-1-private.html: Added.
* storage/indexeddb/modern/idbobjectstore-getall-1.html: Added.
* storage/indexeddb/modern/idbobjectstore-getallkeys-1-expected.txt: Added.
* storage/indexeddb/modern/idbobjectstore-getallkeys-1-private-expected.txt: Added.
* storage/indexeddb/modern/idbobjectstore-getallkeys-1-private.html: Added.
* storage/indexeddb/modern/idbobjectstore-getallkeys-1.html: Added.
* storage/indexeddb/modern/resources/idbobjectstore-getall-1.js: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208194 268f45cc-cd09-0410-ab3c-d52691b4dbfc

65 files changed:
LayoutTests/ChangeLog
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/IndexedDB/idbobjectstore_getAll-expected.txt
LayoutTests/imported/w3c/web-platform-tests/IndexedDB/idbobjectstore_getAllKeys-expected.txt
LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1-private-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1-private.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1-private-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1-private.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/resources/idbobjectstore-getall-1.js [new file with mode: 0644]
LayoutTests/storage/indexeddb/modern/resources/idbobjectstore-getallkeys-1.js [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBGetAllResult.cpp [new file with mode: 0644]
Source/WebCore/Modules/indexeddb/IDBGetAllResult.h [new file with mode: 0644]
Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp
Source/WebCore/Modules/indexeddb/IDBObjectStore.h
Source/WebCore/Modules/indexeddb/IDBObjectStore.idl
Source/WebCore/Modules/indexeddb/IDBRequest.cpp
Source/WebCore/Modules/indexeddb/IDBRequest.h
Source/WebCore/Modules/indexeddb/IDBTransaction.cpp
Source/WebCore/Modules/indexeddb/IDBTransaction.h
Source/WebCore/Modules/indexeddb/IndexedDB.h
Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.cpp
Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.h
Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.cpp
Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.h
Source/WebCore/Modules/indexeddb/client/IDBConnectionToServerDelegate.h
Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.cpp
Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.h
Source/WebCore/Modules/indexeddb/server/IDBConnectionToClientDelegate.h
Source/WebCore/Modules/indexeddb/server/IDBServer.cpp
Source/WebCore/Modules/indexeddb/server/IDBServer.h
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp
Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h
Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp
Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp
Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h
Source/WebCore/Modules/indexeddb/shared/IDBGetAllRecordsData.cpp [new file with mode: 0644]
Source/WebCore/Modules/indexeddb/shared/IDBGetAllRecordsData.h [new file with mode: 0644]
Source/WebCore/Modules/indexeddb/shared/IDBResultData.cpp
Source/WebCore/Modules/indexeddb/shared/IDBResultData.h
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp
Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/IDBBindingUtilities.cpp
Source/WebCore/bindings/js/IDBBindingUtilities.h
Source/WebKit2/ChangeLog
Source/WebKit2/DatabaseProcess/IndexedDB/WebIDBConnectionToClient.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/WebIDBConnectionToClient.h
Source/WebKit2/DatabaseProcess/IndexedDB/WebIDBConnectionToClient.messages.in
Source/WebKit2/Platform/IPC/ArgumentCoders.h
Source/WebKit2/Shared/WebCoreArgumentCoders.h
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.cpp
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.h
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.messages.in

index b0afe56..78a1e0e 100644 (file)
@@ -1,3 +1,20 @@
+2016-10-31  Brady Eidson  <beidson@apple.com>
+
+        IndexedDB 2.0: Support IDBObjectStore getAll/getAllKeys.
+        <rdar://problem/28806934> and https://bugs.webkit.org/show_bug.cgi?id=164097
+
+        Reviewed by Darin Adler.
+
+        * storage/indexeddb/modern/idbobjectstore-getall-1-expected.txt: Added.
+        * storage/indexeddb/modern/idbobjectstore-getall-1-private-expected.txt: Added.
+        * storage/indexeddb/modern/idbobjectstore-getall-1-private.html: Added.
+        * storage/indexeddb/modern/idbobjectstore-getall-1.html: Added.
+        * storage/indexeddb/modern/idbobjectstore-getallkeys-1-expected.txt: Added.
+        * storage/indexeddb/modern/idbobjectstore-getallkeys-1-private-expected.txt: Added.
+        * storage/indexeddb/modern/idbobjectstore-getallkeys-1-private.html: Added.
+        * storage/indexeddb/modern/idbobjectstore-getallkeys-1.html: Added.
+        * storage/indexeddb/modern/resources/idbobjectstore-getall-1.js: Added.
+
 2016-10-31  Ryan Haddad  <ryanhaddad@apple.com>
 
         Marking two http/tests/websocket/tests/hybi tests as flaky.
index 2906dde..3dd3859 100644 (file)
@@ -1,3 +1,13 @@
+2016-10-31  Brady Eidson  <beidson@apple.com>
+
+        IndexedDB 2.0: Support IDBObjectStore getAll/getAllKeys.
+        <rdar://problem/28806934> and https://bugs.webkit.org/show_bug.cgi?id=164097
+
+        Reviewed by Darin Adler.
+
+        * web-platform-tests/IndexedDB/idbobjectstore_getAll-expected.txt:
+        * web-platform-tests/IndexedDB/idbobjectstore_getAllKeys-expected.txt:
+
 2016-10-31  Ryosuke Niwa  <rniwa@webkit.org>
 
         CSSStyleDeclaration should be annotated with CEReactions
index d1a2613..2f6186b 100644 (file)
@@ -1,14 +1,14 @@
 
-FAIL Single item get store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL Single item get (generated key) store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL getAll on empty object store store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL Get all values store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL Test maxCount store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL Get bound range store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL Get bound range with maxCount store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL Get upper excluded store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL Get lower excluded store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL Get bound range (generated) with maxCount store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL Non existent key store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
-FAIL zero maxCount store.getAll is not a function. (In 'store.getAll(range, maxCount)', 'store.getAll' is undefined)
+PASS Single item get 
+PASS Single item get (generated key) 
+PASS getAll on empty object store 
+PASS Get all values 
+PASS Test maxCount 
+PASS Get bound range 
+PASS Get bound range with maxCount 
+PASS Get upper excluded 
+PASS Get lower excluded 
+PASS Get bound range (generated) with maxCount 
+PASS Non existent key 
+PASS zero maxCount 
 
index 48f7e1f..a19638c 100644 (file)
@@ -1,14 +1,14 @@
 
-FAIL Single item get store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL Single item get (generated key) store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL getAllKeys on empty object store store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL Get all values store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL Test maxCount store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL Get bound range store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL Get bound range with maxCount store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL Get upper excluded store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL Get lower excluded store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL Get bound range (generated) with maxCount store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL Non existent key store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
-FAIL zero maxCount store.getAllKeys is not a function. (In 'store.getAllKeys(range, maxCount)', 'store.getAllKeys' is undefined)
+PASS Single item get 
+PASS Single item get (generated key) 
+PASS getAllKeys on empty object store 
+PASS Get all values 
+PASS Test maxCount 
+PASS Get bound range 
+PASS Get bound range with maxCount 
+PASS Get upper excluded 
+PASS Get lower excluded 
+PASS Get bound range (generated) with maxCount 
+PASS Non existent key 
+PASS zero maxCount 
 
diff --git a/LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1-expected.txt b/LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1-expected.txt
new file mode 100644 (file)
index 0000000..3de8ba1
--- /dev/null
@@ -0,0 +1,30 @@
+Test IDBObjectStore.getAll()
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+Initial upgrade needed: Old version - 0 New version - 1
+getAll() result is:
+[ 'false' '-10' '10' 'hello' 'hellothere' ]
+getAll(undefined, 4) result is:
+[ 'false' '-10' '10' 'hello' ]
+getAll(6) result is:
+[ ]
+getAll(3) result is:
+[ '10' ]
+getAll(IDBKeyRange.only(5)) result is:
+[ 'hellothere' ]
+getAll(IDBKeyRange.lowerBound(2)) result is:
+[ '-10' '10' 'hello' 'hellothere' ]
+getAll(IDBKeyRange.upperBound(2)) result is:
+[ 'false' '-10' ]
+getAll(IDBKeyRange.bound(2, 4)) result is:
+[ '-10' '10' 'hello' ]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1-private-expected.txt b/LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1-private-expected.txt
new file mode 100644 (file)
index 0000000..3de8ba1
--- /dev/null
@@ -0,0 +1,30 @@
+Test IDBObjectStore.getAll()
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+Initial upgrade needed: Old version - 0 New version - 1
+getAll() result is:
+[ 'false' '-10' '10' 'hello' 'hellothere' ]
+getAll(undefined, 4) result is:
+[ 'false' '-10' '10' 'hello' ]
+getAll(6) result is:
+[ ]
+getAll(3) result is:
+[ '10' ]
+getAll(IDBKeyRange.only(5)) result is:
+[ 'hellothere' ]
+getAll(IDBKeyRange.lowerBound(2)) result is:
+[ '-10' '10' 'hello' 'hellothere' ]
+getAll(IDBKeyRange.upperBound(2)) result is:
+[ 'false' '-10' ]
+getAll(IDBKeyRange.bound(2, 4)) result is:
+[ '-10' '10' 'hello' ]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1-private.html b/LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1-private.html
new file mode 100644 (file)
index 0000000..85f5e25
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+<head>
+<script>
+enablePrivateBrowsing = true;
+</script>
+<script src="../../../resources/js-test.js"></script>
+<script src="../resources/shared.js"></script>
+</head>
+<body>
+
+<script src="resources/idbobjectstore-getall-1.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1.html b/LayoutTests/storage/indexeddb/modern/idbobjectstore-getall-1.html
new file mode 100644 (file)
index 0000000..21ba97a
--- /dev/null
@@ -0,0 +1,10 @@
+<html>
+<head>
+<script src="../../../resources/js-test.js"></script>
+<script src="../resources/shared.js"></script>
+</head>
+<body>
+
+<script src="resources/idbobjectstore-getall-1.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1-expected.txt b/LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1-expected.txt
new file mode 100644 (file)
index 0000000..c294f0d
--- /dev/null
@@ -0,0 +1,30 @@
+Test IDBObjectStore.getAllKeys()
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+Initial upgrade needed: Old version - 0 New version - 1
+getAllKeys() result is:
+[ '1' '2' '3' '4' '5' ]
+getAllKeys(undefined, 4) result is:
+[ '1' '2' '3' '4' ]
+getAllKeys(6) result is:
+[ ]
+getAllKeys(3) result is:
+[ '3' ]
+getAllKeys(IDBKeyRange.only(5)) result is:
+[ '5' ]
+getAllKeys(IDBKeyRange.lowerBound(2)) result is:
+[ '2' '3' '4' '5' ]
+getAllKeys(IDBKeyRange.upperBound(2)) result is:
+[ '1' '2' ]
+getAllKeys(IDBKeyRange.bound(2, 4)) result is:
+[ '2' '3' '4' ]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1-private-expected.txt b/LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1-private-expected.txt
new file mode 100644 (file)
index 0000000..c294f0d
--- /dev/null
@@ -0,0 +1,30 @@
+Test IDBObjectStore.getAllKeys()
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.deleteDatabase(dbname)
+indexedDB.open(dbname)
+Initial upgrade needed: Old version - 0 New version - 1
+getAllKeys() result is:
+[ '1' '2' '3' '4' '5' ]
+getAllKeys(undefined, 4) result is:
+[ '1' '2' '3' '4' ]
+getAllKeys(6) result is:
+[ ]
+getAllKeys(3) result is:
+[ '3' ]
+getAllKeys(IDBKeyRange.only(5)) result is:
+[ '5' ]
+getAllKeys(IDBKeyRange.lowerBound(2)) result is:
+[ '2' '3' '4' '5' ]
+getAllKeys(IDBKeyRange.upperBound(2)) result is:
+[ '1' '2' ]
+getAllKeys(IDBKeyRange.bound(2, 4)) result is:
+[ '2' '3' '4' ]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1-private.html b/LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1-private.html
new file mode 100644 (file)
index 0000000..bff42cb
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+<head>
+<script>
+enablePrivateBrowsing = true;
+</script>
+<script src="../../../resources/js-test.js"></script>
+<script src="../resources/shared.js"></script>
+</head>
+<body>
+
+<script src="resources/idbobjectstore-getallkeys-1.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1.html b/LayoutTests/storage/indexeddb/modern/idbobjectstore-getallkeys-1.html
new file mode 100644 (file)
index 0000000..cdb6719
--- /dev/null
@@ -0,0 +1,10 @@
+<html>
+<head>
+<script src="../../../resources/js-test.js"></script>
+<script src="../resources/shared.js"></script>
+</head>
+<body>
+
+<script src="resources/idbobjectstore-getallkeys-1.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/storage/indexeddb/modern/resources/idbobjectstore-getall-1.js b/LayoutTests/storage/indexeddb/modern/resources/idbobjectstore-getall-1.js
new file mode 100644 (file)
index 0000000..6ff4434
--- /dev/null
@@ -0,0 +1,128 @@
+description("Test IDBObjectStore.getAll()");
+
+indexedDBTest(prepareDatabase);
+
+function done()
+{
+    finishJSTest();
+}
+
+function log(message)
+{
+    debug(message);
+}
+
+var testGenerator;
+
+function continueWithEvent(event)
+{
+    testGenerator.next(event);
+}
+
+function asyncContinue()
+{
+    setTimeout("testGenerator.next();", 0);
+}
+
+function idbRequest(request)
+{
+    request.onerror = continueWithEvent;
+    request.onsuccess = continueWithEvent;
+       return request;
+}
+
+var db;
+
+function prepareDatabase(event)
+{
+    debug("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+    db = event.target.result;
+    os = db.createObjectStore("foo");
+       os.add(false, 1);
+       os.add(-10, 2);
+       os.add(10, 3);
+       os.add("hello", 4);
+       os.add("hellothere", 5);
+
+    event.target.transaction.oncomplete = function() {
+        testGenerator = testSteps();
+        testGenerator.next();
+    };
+}
+
+function dumpArray(array)
+{
+       if (!array) {
+               debug("Undefined array");
+               return;
+       }
+
+       var string = "[ ";
+       for (var i = 0; i < array.length; ++i)
+               string += "'" + array[i] + "' ";
+       string += "]";
+       
+       debug(string);
+}
+
+function is(a, b, message) {
+    result = a == b ? "true" : "false";
+    debug(message + ": " + result);
+}
+
+function* testSteps()
+{
+    objectStore = db.transaction("foo").objectStore("foo");
+       // Get everything
+    req = idbRequest(objectStore.getAll());
+    event = yield;    
+       debug("getAll() result is:");
+       dumpArray(req.result);
+
+       // Get everything, limit to 4
+    req = idbRequest(objectStore.getAll(undefined, 4));
+    event = yield;    
+       debug("getAll(undefined, 4) result is:");
+       dumpArray(req.result);
+       
+       // Non-existent key
+    req = idbRequest(objectStore.getAll(6));
+    event = yield;    
+       debug("getAll(6) result is:");
+       dumpArray(req.result);
+
+       // Existent key
+    req = idbRequest(objectStore.getAll(3));
+    event = yield;    
+       debug("getAll(3) result is:");
+       dumpArray(req.result);
+       
+       // Key range only
+    req = idbRequest(objectStore.getAll(IDBKeyRange.only(5)));
+    event = yield;    
+       debug("getAll(IDBKeyRange.only(5)) result is:");
+       dumpArray(req.result);
+
+       // Key range lower bound
+    req = idbRequest(objectStore.getAll(IDBKeyRange.lowerBound(2)));
+    event = yield;    
+       debug("getAll(IDBKeyRange.lowerBound(2)) result is:");
+       dumpArray(req.result);
+
+       // Key range upper bound
+    req = idbRequest(objectStore.getAll(IDBKeyRange.upperBound(2)));
+    event = yield;    
+       debug("getAll(IDBKeyRange.upperBound(2)) result is:");
+       dumpArray(req.result);
+
+       // Key range bound
+    req = idbRequest(objectStore.getAll(IDBKeyRange.bound(2, 4)));
+    event = yield;    
+       debug("getAll(IDBKeyRange.bound(2, 4)) result is:");
+       dumpArray(req.result);
+    
+    finishJSTest();
+ }
\ No newline at end of file
diff --git a/LayoutTests/storage/indexeddb/modern/resources/idbobjectstore-getallkeys-1.js b/LayoutTests/storage/indexeddb/modern/resources/idbobjectstore-getallkeys-1.js
new file mode 100644 (file)
index 0000000..477c65e
--- /dev/null
@@ -0,0 +1,128 @@
+description("Test IDBObjectStore.getAllKeys()");
+
+indexedDBTest(prepareDatabase);
+
+function done()
+{
+    finishJSTest();
+}
+
+function log(message)
+{
+    debug(message);
+}
+
+var testGenerator;
+
+function continueWithEvent(event)
+{
+    testGenerator.next(event);
+}
+
+function asyncContinue()
+{
+    setTimeout("testGenerator.next();", 0);
+}
+
+function idbRequest(request)
+{
+    request.onerror = continueWithEvent;
+    request.onsuccess = continueWithEvent;
+       return request;
+}
+
+var db;
+
+function prepareDatabase(event)
+{
+    debug("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+    db = event.target.result;
+    os = db.createObjectStore("foo");
+       os.add(false, 1);
+       os.add(-10, 2);
+       os.add(10, 3);
+       os.add("hello", 4);
+       os.add("hellothere", 5);
+
+    event.target.transaction.oncomplete = function() {
+        testGenerator = testSteps();
+        testGenerator.next();
+    };
+}
+
+function dumpArray(array)
+{
+       if (!array) {
+               debug("Undefined array");
+               return;
+       }
+
+       var string = "[ ";
+       for (var i = 0; i < array.length; ++i)
+               string += "'" + array[i] + "' ";
+       string += "]";
+       
+       debug(string);
+}
+
+function is(a, b, message) {
+    result = a == b ? "true" : "false";
+    debug(message + ": " + result);
+}
+
+function* testSteps()
+{
+    objectStore = db.transaction("foo").objectStore("foo");
+       // Get everything
+    req = idbRequest(objectStore.getAllKeys());
+    event = yield;    
+       debug("getAllKeys() result is:");
+       dumpArray(req.result);
+
+       // Get everything, limit to 4
+    req = idbRequest(objectStore.getAllKeys(undefined, 4));
+    event = yield;    
+       debug("getAllKeys(undefined, 4) result is:");
+       dumpArray(req.result);
+       
+       // Non-existent key
+    req = idbRequest(objectStore.getAllKeys(6));
+    event = yield;    
+       debug("getAllKeys(6) result is:");
+       dumpArray(req.result);
+
+       // Existent key
+    req = idbRequest(objectStore.getAllKeys(3));
+    event = yield;    
+       debug("getAllKeys(3) result is:");
+       dumpArray(req.result);
+       
+       // Key range only
+    req = idbRequest(objectStore.getAllKeys(IDBKeyRange.only(5)));
+    event = yield;    
+       debug("getAllKeys(IDBKeyRange.only(5)) result is:");
+       dumpArray(req.result);
+
+       // Key range lower bound
+    req = idbRequest(objectStore.getAllKeys(IDBKeyRange.lowerBound(2)));
+    event = yield;    
+       debug("getAllKeys(IDBKeyRange.lowerBound(2)) result is:");
+       dumpArray(req.result);
+
+       // Key range upper bound
+    req = idbRequest(objectStore.getAllKeys(IDBKeyRange.upperBound(2)));
+    event = yield;    
+       debug("getAllKeys(IDBKeyRange.upperBound(2)) result is:");
+       dumpArray(req.result);
+
+       // Key range bound
+    req = idbRequest(objectStore.getAllKeys(IDBKeyRange.bound(2, 4)));
+    event = yield;    
+       debug("getAllKeys(IDBKeyRange.bound(2, 4)) result is:");
+       dumpArray(req.result);
+    
+    finishJSTest();
+ }
\ No newline at end of file
index 01a144b..8f5417d 100644 (file)
@@ -824,6 +824,7 @@ set(WebCore_SOURCES
     Modules/indexeddb/IDBDatabaseIdentifier.cpp
     Modules/indexeddb/IDBEventDispatcher.cpp
     Modules/indexeddb/IDBFactory.cpp
+    Modules/indexeddb/IDBGetAllResult.cpp
     Modules/indexeddb/IDBGetResult.cpp
     Modules/indexeddb/IDBIndex.cpp
     Modules/indexeddb/IDBKey.cpp
@@ -867,6 +868,7 @@ set(WebCore_SOURCES
     Modules/indexeddb/shared/IDBCursorInfo.cpp
     Modules/indexeddb/shared/IDBDatabaseInfo.cpp
     Modules/indexeddb/shared/IDBError.cpp
+    Modules/indexeddb/shared/IDBGetAllRecordsData.cpp
     Modules/indexeddb/shared/IDBGetRecordData.cpp
     Modules/indexeddb/shared/IDBIndexInfo.cpp
     Modules/indexeddb/shared/IDBObjectStoreInfo.cpp
index 4993a9b..4ad7185 100644 (file)
@@ -1,3 +1,128 @@
+2016-10-31  Brady Eidson  <beidson@apple.com>
+
+        IndexedDB 2.0: Support IDBObjectStore getAll/getAllKeys.
+        <rdar://problem/28806934> and https://bugs.webkit.org/show_bug.cgi?id=164097
+
+        Reviewed by Darin Adler.
+
+        Tests: storage/indexeddb/modern/idbobjectstore-getall-1-private.html
+               storage/indexeddb/modern/idbobjectstore-getall-1.html
+               storage/indexeddb/modern/idbobjectstore-getallkeys-1-private.html
+               storage/indexeddb/modern/idbobjectstore-getallkeys-1.html
+               Existing imported W3C tests.
+
+        - Add new objects for "IDBGetAllRequestData" and "IDBGetAllResult" to represent these
+          new requests and responses.
+        - Add lots of boilerplate code to move these new objects around in the IDB machinery.
+        - Update "GetRecord" code to be shared with "GetAll" code where necessary.
+        - Other tweaks here and there.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * CMakeLists.txt:
+
+        * Modules/indexeddb/IDBGetAllResult.cpp: Added.
+        (WebCore::isolatedCopyOfVariant):
+        (WebCore::IDBGetAllResult::isolatedCopy):
+        (WebCore::IDBGetAllResult::addKey):
+        (WebCore::IDBGetAllResult::addValue):
+        (WebCore::IDBGetAllResult::keys):
+        (WebCore::IDBGetAllResult::values):
+        (WebCore::IDBGetAllResult::allBlobFilePaths):
+        * Modules/indexeddb/IDBGetAllResult.h: Added.
+        (WebCore::IDBGetAllResult::IDBGetAllResult):
+        (WebCore::IDBGetAllResult::type):
+        (WebCore::IDBGetAllResult::encode):
+        (WebCore::IDBGetAllResult::decode):
+
+        * Modules/indexeddb/IDBObjectStore.cpp:
+        (WebCore::IDBObjectStore::getAll):
+        (WebCore::IDBObjectStore::getAllKeys):
+        * Modules/indexeddb/IDBObjectStore.h:
+        * Modules/indexeddb/IDBObjectStore.idl:
+
+        * Modules/indexeddb/IDBRequest.cpp:
+        (WebCore::IDBRequest::setResult):
+        * Modules/indexeddb/IDBRequest.h:
+
+        * Modules/indexeddb/IDBTransaction.cpp:
+        (WebCore::IDBTransaction::requestGetAllObjectStoreRecords):
+        (WebCore::IDBTransaction::getAllRecordsOnServer):
+        (WebCore::IDBTransaction::didGetAllRecordsOnServer):
+        * Modules/indexeddb/IDBTransaction.h:
+
+        * Modules/indexeddb/IndexedDB.h:
+
+        * Modules/indexeddb/client/IDBConnectionProxy.cpp:
+        (WebCore::IDBClient::IDBConnectionProxy::getAllRecords):
+        * Modules/indexeddb/client/IDBConnectionProxy.h:
+
+        * Modules/indexeddb/client/IDBConnectionToServer.cpp:
+        (WebCore::IDBClient::IDBConnectionToServer::getAllRecords):
+        (WebCore::IDBClient::IDBConnectionToServer::didGetAllRecords):
+        * Modules/indexeddb/client/IDBConnectionToServer.h:
+        * Modules/indexeddb/client/IDBConnectionToServerDelegate.h:
+
+        * Modules/indexeddb/server/IDBBackingStore.h:
+
+        * Modules/indexeddb/server/IDBConnectionToClient.cpp:
+        (WebCore::IDBServer::IDBConnectionToClient::didGetAllRecords):
+        * Modules/indexeddb/server/IDBConnectionToClient.h:
+        * Modules/indexeddb/server/IDBConnectionToClientDelegate.h:
+
+        * Modules/indexeddb/server/IDBServer.cpp:
+        (WebCore::IDBServer::IDBServer::getAllRecords):
+        * Modules/indexeddb/server/IDBServer.h:
+
+        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+        (WebCore::IDBServer::MemoryIDBBackingStore::getAllRecords):
+        * Modules/indexeddb/server/MemoryIDBBackingStore.h:
+
+        * Modules/indexeddb/server/MemoryObjectStore.cpp:
+        (WebCore::IDBServer::MemoryObjectStore::getAllRecords):
+        * Modules/indexeddb/server/MemoryObjectStore.h:
+
+        * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
+        (WebCore::IDBServer::queryForGetAllRecords):
+        (WebCore::IDBServer::SQLiteIDBBackingStore::getAllRecords):
+        * Modules/indexeddb/server/SQLiteIDBBackingStore.h:
+
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::hasAnyPendingCallbacks):
+        (WebCore::IDBServer::UniqueIDBDatabase::storeCallbackOrFireError):
+        (WebCore::IDBServer::UniqueIDBDatabase::getAllRecords):
+        (WebCore::IDBServer::UniqueIDBDatabase::performGetAllRecords):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformGetAllRecords):
+        (WebCore::IDBServer::UniqueIDBDatabase::performGetAllResultsCallback):
+        * Modules/indexeddb/server/UniqueIDBDatabase.h:
+
+        * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::getAllRecords):
+        * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h:
+
+        * Modules/indexeddb/shared/IDBGetAllRecordsData.cpp: Added.
+        (WebCore::IDBGetAllRecordsData::isolatedCopy):
+        * Modules/indexeddb/shared/IDBGetAllRecordsData.h: Added.
+        (WebCore::IDBGetAllRecordsData::encode):
+        (WebCore::IDBGetAllRecordsData::decode):
+
+        * Modules/indexeddb/shared/IDBResultData.cpp:
+        (WebCore::IDBResultData::IDBResultData):
+        (WebCore::IDBResultData::getAllRecordsSuccess):
+        (WebCore::IDBResultData::getAllResult):
+        * Modules/indexeddb/shared/IDBResultData.h:
+        (WebCore::IDBResultData::encode):
+        (WebCore::IDBResultData::decode):
+
+        * Modules/indexeddb/shared/InProcessIDBServer.cpp:
+        (WebCore::InProcessIDBServer::didGetAllRecords):
+        (WebCore::InProcessIDBServer::getAllRecords):
+        * Modules/indexeddb/shared/InProcessIDBServer.h:
+
+        * bindings/js/IDBBindingUtilities.cpp:
+        (WebCore::deserializeIDBValueToJSValue):
+        (WebCore::toJS):
+        * bindings/js/IDBBindingUtilities.h:
+
 2016-10-31  Ryosuke Niwa  <rniwa@webkit.org>
 
         GTK+ and EFL build fixes after r208176.
diff --git a/Source/WebCore/Modules/indexeddb/IDBGetAllResult.cpp b/Source/WebCore/Modules/indexeddb/IDBGetAllResult.cpp
new file mode 100644 (file)
index 0000000..4e7e6f4
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IDBGetAllResult.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+template<typename T> void isolatedCopyOfVariant(const WTF::Variant<Vector<IDBKeyData>, Vector<IDBValue>, std::nullptr_t>& source, WTF::Variant<Vector<IDBKeyData>, Vector<IDBValue>, std::nullptr_t>& target)
+{
+    target = Vector<T>();
+    auto& sourceVector = WTF::get<Vector<T>>(source);
+    auto& targetVector = WTF::get<Vector<T>>(target);
+    targetVector.reserveInitialCapacity(sourceVector.size());
+    for (auto& element : sourceVector)
+        targetVector.uncheckedAppend(element.isolatedCopy());
+}
+
+IDBGetAllResult IDBGetAllResult::isolatedCopy() const
+{
+    IDBGetAllResult result;
+    result.m_type = m_type;
+
+    if (WTF::holds_alternative<std::nullptr_t>(m_results))
+        return result;
+
+    switch (m_type) {
+    case IndexedDB::GetAllType::Keys:
+        isolatedCopyOfVariant<IDBKeyData>(m_results, result.m_results);
+        break;
+    case IndexedDB::GetAllType::Values:
+        isolatedCopyOfVariant<IDBValue>(m_results, result.m_results);
+        break;
+    }
+
+    return result;
+}
+
+void IDBGetAllResult::addKey(IDBKeyData&& key)
+{
+    ASSERT(m_type == IndexedDB::GetAllType::Keys);
+    ASSERT(WTF::holds_alternative<Vector<IDBKeyData>>(m_results));
+    WTF::get<Vector<IDBKeyData>>(m_results).append(WTFMove(key));
+}
+
+void IDBGetAllResult::addValue(IDBValue&& value)
+{
+    ASSERT(m_type == IndexedDB::GetAllType::Values);
+    ASSERT(WTF::holds_alternative<Vector<IDBValue>>(m_results));
+    WTF::get<Vector<IDBValue>>(m_results).append(WTFMove(value));
+}
+
+const Vector<IDBKeyData>& IDBGetAllResult::keys() const
+{
+    ASSERT(m_type == IndexedDB::GetAllType::Keys);
+    ASSERT(WTF::holds_alternative<Vector<IDBKeyData>>(m_results));
+    return WTF::get<Vector<IDBKeyData>>(m_results);
+}
+
+const Vector<IDBValue>& IDBGetAllResult::values() const
+{
+    ASSERT(m_type == IndexedDB::GetAllType::Values);
+    ASSERT(WTF::holds_alternative<Vector<IDBValue>>(m_results));
+    return WTF::get<Vector<IDBValue>>(m_results);
+}
+
+Vector<String> IDBGetAllResult::allBlobFilePaths() const
+{
+    ASSERT(m_type == IndexedDB::GetAllType::Values);
+
+    HashSet<String> pathSet;
+    for (auto& value : WTF::get<Vector<IDBValue>>(m_results)) {
+        for (auto& path : value.blobFilePaths())
+            pathSet.add(path);
+    }
+
+    Vector<String> paths;
+    copyToVector(pathSet, paths);
+
+    return paths;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/Modules/indexeddb/IDBGetAllResult.h b/Source/WebCore/Modules/indexeddb/IDBGetAllResult.h
new file mode 100644 (file)
index 0000000..e5fc6a9
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBKeyData.h"
+#include "IDBValue.h"
+#include "IndexedDB.h"
+
+#include <wtf/Variant.h>
+
+namespace WebCore {
+
+class IDBGetAllResult {
+public:
+    IDBGetAllResult()
+    {
+    }
+
+    IDBGetAllResult(IndexedDB::GetAllType type)
+        : m_type(type)
+    {
+        switch (m_type) {
+        case IndexedDB::GetAllType::Keys:
+            m_results = Vector<IDBKeyData>();
+            break;
+        case IndexedDB::GetAllType::Values:
+            m_results = Vector<IDBValue>();
+            break;
+        }
+    }
+
+    IDBGetAllResult isolatedCopy() const;
+
+    IndexedDB::GetAllType type() const { return m_type; }
+    const Vector<IDBKeyData>& keys() const;
+    const Vector<IDBValue>& values() const;
+
+    void addKey(IDBKeyData&&);
+    void addValue(IDBValue&&);
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static bool decode(Decoder&, IDBGetAllResult&);
+
+    WEBCORE_EXPORT Vector<String> allBlobFilePaths() const;
+
+private:
+    IndexedDB::GetAllType m_type { IndexedDB::GetAllType::Keys };
+    WTF::Variant<Vector<IDBKeyData>, Vector<IDBValue>, std::nullptr_t> m_results { nullptr };
+};
+
+template<class Encoder>
+void IDBGetAllResult::encode(Encoder& encoder) const
+{
+    encoder << m_type << static_cast<uint64_t>(m_results.index());
+
+    switch (m_results.index()) {
+    case 0:
+        encoder << WTF::get<Vector<IDBKeyData>>(m_results);
+        break;
+    case 1:
+        encoder << WTF::get<Vector<IDBValue>>(m_results);
+        break;
+    case 2:
+        break;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
+template<class Decoder>
+bool IDBGetAllResult::decode(Decoder& decoder, IDBGetAllResult& result)
+{
+    if (!decoder.decode(result.m_type))
+        return false;
+
+    uint64_t index;
+    if (!decoder.decode(index))
+        return false;
+
+    switch (index) {
+    case 0:
+        result.m_results = Vector<IDBKeyData>();
+        if (!decoder.decode(WTF::get<Vector<IDBKeyData>>(result.m_results)))
+            return false;
+        break;
+    case 1:
+        result.m_results = Vector<IDBValue>();
+        if (!decoder.decode(WTF::get<Vector<IDBValue>>(result.m_results)))
+            return false;
+        break;
+    case 2:
+        result.m_results = nullptr;
+        break;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+
+    return true;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
index effa0e6..67290b4 100644 (file)
@@ -548,6 +548,52 @@ ExceptionOr<Ref<IDBRequest>> IDBObjectStore::doCount(ExecState& execState, const
     return m_transaction->requestCount(execState, *this, range);
 }
 
+ExceptionOr<Ref<IDBRequest>> IDBObjectStore::getAll(ExecState& execState, RefPtr<IDBKeyRange> range, Optional<uint32_t> count)
+{
+    LOG(IndexedDB, "IDBObjectStore::getAll");
+    ASSERT(currentThread() == m_transaction->database().originThreadID());
+
+    if (m_deleted)
+        return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral("Failed to execute 'getAll' on 'IDBObjectStore': The object store has been deleted.") };
+
+    if (!m_transaction->isActive())
+        return Exception { IDBDatabaseException::TransactionInactiveError, ASCIILiteral("Failed to execute 'getAll' on 'IDBObjectStore': The transaction is inactive or finished.") };
+
+    return m_transaction->requestGetAllObjectStoreRecords(execState, *this, range.get(), IndexedDB::GetAllType::Values, count);
+}
+
+ExceptionOr<Ref<IDBRequest>> IDBObjectStore::getAll(ExecState& execState, JSValue key, Optional<uint32_t> count)
+{
+    auto onlyResult = IDBKeyRange::only(execState, key);
+    if (onlyResult.hasException())
+        return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to execute 'getAll' on 'IDBObjectStore': The parameter is not a valid key.") };
+
+    return getAll(execState, onlyResult.releaseReturnValue(), count);
+}
+
+ExceptionOr<Ref<IDBRequest>> IDBObjectStore::getAllKeys(ExecState& execState, RefPtr<IDBKeyRange> range, Optional<uint32_t> count)
+{
+    LOG(IndexedDB, "IDBObjectStore::getAllKeys");
+    ASSERT(currentThread() == m_transaction->database().originThreadID());
+
+    if (m_deleted)
+        return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral("Failed to execute 'getAllKeys' on 'IDBObjectStore': The object store has been deleted.") };
+
+    if (!m_transaction->isActive())
+        return Exception { IDBDatabaseException::TransactionInactiveError, ASCIILiteral("Failed to execute 'getAllKeys' on 'IDBObjectStore': The transaction is inactive or finished.") };
+
+    return m_transaction->requestGetAllObjectStoreRecords(execState, *this, range.get(), IndexedDB::GetAllType::Keys, count);
+}
+
+ExceptionOr<Ref<IDBRequest>> IDBObjectStore::getAllKeys(ExecState& execState, JSValue key, Optional<uint32_t> count)
+{
+    auto onlyResult = IDBKeyRange::only(execState, key);
+    if (onlyResult.hasException())
+        return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to execute 'getAllKeys' on 'IDBObjectStore': The parameter is not a valid key.") };
+
+    return getAllKeys(execState, onlyResult.releaseReturnValue(), count);
+}
+
 void IDBObjectStore::markAsDeleted()
 {
     ASSERT(currentThread() == m_transaction->database().originThreadID());
index f787fab..7b14d0f 100644 (file)
@@ -88,6 +88,10 @@ public:
     ExceptionOr<void> deleteIndex(const String& name);
     ExceptionOr<Ref<IDBRequest>> count(JSC::ExecState&, IDBKeyRange*);
     ExceptionOr<Ref<IDBRequest>> count(JSC::ExecState&, JSC::JSValue key);
+    ExceptionOr<Ref<IDBRequest>> getAll(JSC::ExecState&, RefPtr<IDBKeyRange>, Optional<uint32_t> count);
+    ExceptionOr<Ref<IDBRequest>> getAll(JSC::ExecState&, JSC::JSValue key, Optional<uint32_t> count);
+    ExceptionOr<Ref<IDBRequest>> getAllKeys(JSC::ExecState&, RefPtr<IDBKeyRange>, Optional<uint32_t> count);
+    ExceptionOr<Ref<IDBRequest>> getAllKeys(JSC::ExecState&, JSC::JSValue key, Optional<uint32_t> count);
 
     ExceptionOr<Ref<IDBRequest>> putForCursorUpdate(JSC::ExecState&, JSC::JSValue, JSC::JSValue key);
 
index f0bd5bf..edd78e9 100644 (file)
     [CallWith=ScriptState, MayThrowException] IDBRequest openCursor(any key, optional DOMString direction = "next");
     [CallWith=ScriptState, MayThrowException] IDBRequest openKeyCursor(optional IDBKeyRange? range = null, optional DOMString direction = "next");
     [CallWith=ScriptState, MayThrowException] IDBRequest openKeyCursor(any key, optional DOMString direction = "next");
+    [CallWith=ScriptState, MayThrowException] IDBRequest getAll(optional IDBKeyRange? range = null, [EnforceRange] optional unsigned long count);
+    [CallWith=ScriptState, MayThrowException] IDBRequest getAll(any key,  [EnforceRange] optional unsigned long count);
+    [CallWith=ScriptState, MayThrowException] IDBRequest getAllKeys(optional IDBKeyRange? range = null, [EnforceRange] optional unsigned long count);
+    [CallWith=ScriptState, MayThrowException] IDBRequest getAllKeys(any key,  [EnforceRange] optional unsigned long count);
     [CallWith=ScriptState, MayThrowException] IDBIndex createIndex(DOMString name, (DOMString or sequence<DOMString>) keyPath, optional IDBIndexParameters options);
     [MayThrowException] IDBIndex index(DOMString name);
     [MayThrowException] void deleteIndex(DOMString name);
index 1300f68..2c2ed14 100644 (file)
 #include "IDBKeyData.h"
 #include "IDBObjectStore.h"
 #include "IDBResultData.h"
+#include "JSDOMConvert.h"
 #include "Logging.h"
 #include "ScopeGuard.h"
 #include "ScriptExecutionContext.h"
 #include "ThreadSafeDataBuffer.h"
 #include <wtf/NeverDestroyed.h>
 
+using namespace JSC;
+
 namespace WebCore {
 
 Ref<IDBRequest> IDBRequest::create(ScriptExecutionContext& context, IDBObjectStore& objectStore, IDBTransaction& transaction)
@@ -330,6 +333,42 @@ void IDBRequest::setResult(const IDBKeyData& keyData)
     m_scriptResult = { context->vm(), idbKeyDataToScriptValue(*exec, keyData) };
 }
 
+void IDBRequest::setResult(const Vector<IDBKeyData>& keyDatas)
+{
+    ASSERT(currentThread() == originThreadID());
+
+    auto* context = scriptExecutionContext();
+    if (!context)
+        return;
+
+    auto* state = context->execState();
+    if (!state)
+        return;
+
+    clearResult();
+
+    Locker<JSLock> locker(context->vm().apiLock());
+    m_scriptResult = { context->vm(), toJS(state, jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), keyDatas) };
+}
+
+void IDBRequest::setResult(const Vector<IDBValue>& values)
+{
+    ASSERT(currentThread() == originThreadID());
+
+    auto* context = scriptExecutionContext();
+    if (!context)
+        return;
+
+    auto* exec = context->execState();
+    if (!exec)
+        return;
+
+    clearResult();
+
+    Locker<JSLock> locker(context->vm().apiLock());
+    m_scriptResult = { context->vm(), toJS(exec, jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), values) };
+}
+
 void IDBRequest::setResult(uint64_t number)
 {
     ASSERT(currentThread() == originThreadID());
index 650c8d0..7e69612 100644 (file)
@@ -88,6 +88,8 @@ public:
     void requestCompleted(const IDBResultData&);
 
     void setResult(const IDBKeyData&);
+    void setResult(const Vector<IDBKeyData>&);
+    void setResult(const Vector<IDBValue>&);
     void setResult(uint64_t);
     void setResultToStructuredClone(const IDBValue&);
     void setResultToUndefined();
index 625016f..df67a20 100644 (file)
@@ -737,6 +737,58 @@ void IDBTransaction::didIterateCursorOnServer(IDBRequest& request, const IDBResu
     request.didOpenOrIterateCursor(resultData);
 }
 
+Ref<IDBRequest> IDBTransaction::requestGetAllObjectStoreRecords(JSC::ExecState& state, IDBObjectStore& objectStore, const IDBKeyRangeData& keyRangeData, IndexedDB::GetAllType getAllType, Optional<uint32_t> count)
+{
+    LOG(IndexedDB, "IDBTransaction::requestGetAllObjectStoreRecords");
+    ASSERT(isActive());
+    ASSERT(currentThread() == m_database->originThreadID());
+
+    ASSERT_UNUSED(state, scriptExecutionContext() == scriptExecutionContextFromExecState(&state));
+
+    Ref<IDBRequest> request = IDBRequest::create(*scriptExecutionContext(), objectStore, *this);
+    addRequest(request.get());
+
+    IDBGetAllRecordsData getAllRecordsData { keyRangeData, getAllType, count, objectStore.info().identifier(), 0 };
+
+    auto operation = IDBClient::createTransactionOperation(*this, request.get(), &IDBTransaction::didGetAllRecordsOnServer, &IDBTransaction::getAllRecordsOnServer, getAllRecordsData);
+    scheduleOperation(WTFMove(operation));
+
+    return request;
+}
+
+void IDBTransaction::getAllRecordsOnServer(IDBClient::TransactionOperation& operation, const IDBGetAllRecordsData& getAllRecordsData)
+{
+    LOG(IndexedDB, "IDBTransaction::getAllRecordsOnServer");
+    ASSERT(currentThread() == m_database->originThreadID());
+
+    m_database->connectionProxy().getAllRecords(operation, getAllRecordsData);
+}
+
+void IDBTransaction::didGetAllRecordsOnServer(IDBRequest& request, const IDBResultData& resultData)
+{
+    LOG(IndexedDB, "IDBTransaction::didGetAllRecordsOnServer");
+    ASSERT(currentThread() == m_database->originThreadID());
+
+    if (resultData.type() == IDBResultType::Error) {
+        request.requestCompleted(resultData);
+        return;
+    }
+
+    ASSERT(resultData.type() == IDBResultType::GetAllRecordsSuccess);
+
+    auto& getAllResult = resultData.getAllResult();
+    switch (getAllResult.type()) {
+    case IndexedDB::GetAllType::Keys:
+        request.setResult(getAllResult.keys());
+        break;
+    case IndexedDB::GetAllType::Values:
+        request.setResult(getAllResult.values());
+        break;
+    }
+
+    request.requestCompleted(resultData);
+}
+
 Ref<IDBRequest> IDBTransaction::requestGetRecord(ExecState& execState, IDBObjectStore& objectStore, const IDBGetRecordData& getRecordData)
 {
     LOG(IndexedDB, "IDBTransaction::requestGetRecord");
index bdfccfb..03c0c51 100644 (file)
@@ -30,6 +30,7 @@
 #include "EventTarget.h"
 #include "IDBActiveDOMObject.h"
 #include "IDBError.h"
+#include "IDBGetAllRecordsData.h"
 #include "IDBGetRecordData.h"
 #include "IDBKeyRangeData.h"
 #include "IDBOpenDBRequest.h"
@@ -113,6 +114,7 @@ public:
 
     Ref<IDBRequest> requestPutOrAdd(JSC::ExecState&, IDBObjectStore&, IDBKey*, SerializedScriptValue&, IndexedDB::ObjectStoreOverwriteMode);
     Ref<IDBRequest> requestGetRecord(JSC::ExecState&, IDBObjectStore&, const IDBGetRecordData&);
+    Ref<IDBRequest> requestGetAllObjectStoreRecords(JSC::ExecState&, IDBObjectStore&, const IDBKeyRangeData&, IndexedDB::GetAllType, Optional<uint32_t> count);
     Ref<IDBRequest> requestDeleteRecord(JSC::ExecState&, IDBObjectStore&, const IDBKeyRangeData&);
     Ref<IDBRequest> requestClearObjectStore(JSC::ExecState&, IDBObjectStore&);
     Ref<IDBRequest> requestCount(JSC::ExecState&, IDBObjectStore&, const IDBKeyRangeData&);
@@ -185,6 +187,9 @@ private:
     void getRecordOnServer(IDBClient::TransactionOperation&, const IDBGetRecordData&);
     void didGetRecordOnServer(IDBRequest&, const IDBResultData&);
 
+    void getAllRecordsOnServer(IDBClient::TransactionOperation&, const IDBGetAllRecordsData&);
+    void didGetAllRecordsOnServer(IDBRequest&, const IDBResultData&);
+
     void getCountOnServer(IDBClient::TransactionOperation&, const IDBKeyRangeData&);
     void didGetCountOnServer(IDBRequest&, const IDBResultData&);
 
index 84a116e..8fbc92b 100644 (file)
@@ -91,6 +91,11 @@ enum class RequestType {
     Other,
 };
 
+enum class GetAllType {
+    Keys,
+    Values,
+};
+
 } // namespace IndexedDB
 
 } // namespace WebCore
index ce77208..7988b2d 100644 (file)
@@ -189,6 +189,14 @@ void IDBConnectionProxy::getRecord(TransactionOperation& operation, const IDBGet
     callConnectionOnMainThread(&IDBConnectionToServer::getRecord, requestData, getRecordData);
 }
 
+void IDBConnectionProxy::getAllRecords(TransactionOperation& operation, const IDBGetAllRecordsData& getAllRecordsData)
+{
+    const IDBRequestData requestData(operation);
+    saveOperation(operation);
+
+    callConnectionOnMainThread(&IDBConnectionToServer::getAllRecords, requestData, getAllRecordsData);
+}
+
 void IDBConnectionProxy::getCount(TransactionOperation& operation, const IDBKeyRangeData& keyRange)
 {
     const IDBRequestData requestData(operation);
index 844885a..8061062 100644 (file)
@@ -73,6 +73,7 @@ public:
     void deleteIndex(TransactionOperation&, uint64_t objectStoreIdentifier, const String& indexName);
     void putOrAdd(TransactionOperation&, IDBKeyData&&, const IDBValue&, const IndexedDB::ObjectStoreOverwriteMode);
     void getRecord(TransactionOperation&, const IDBGetRecordData&);
+    void getAllRecords(TransactionOperation&, const IDBGetAllRecordsData&);
     void getCount(TransactionOperation&, const IDBKeyRangeData&);
     void deleteRecord(TransactionOperation&, const IDBKeyRangeData&);
     void openCursor(TransactionOperation&, const IDBCursorInfo&);
index a04ebff..cc36120 100644 (file)
@@ -215,6 +215,20 @@ void IDBConnectionToServer::didGetRecord(const IDBResultData& resultData)
     m_proxy->completeOperation(resultData);
 }
 
+void IDBConnectionToServer::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData)
+{
+    LOG(IndexedDB, "IDBConnectionToServer::getAllRecords");
+    ASSERT(isMainThread());
+
+    m_delegate->getAllRecords(requestData, getAllRecordsData);
+}
+
+void IDBConnectionToServer::didGetAllRecords(const IDBResultData& resultData)
+{
+    LOG(IndexedDB, "IDBConnectionToServer::didGetAllRecords");
+    m_proxy->completeOperation(resultData);
+}
+
 void IDBConnectionToServer::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
 {
     LOG(IndexedDB, "IDBConnectionToServer::getCount");
index d48a993..e85b4aa 100644 (file)
@@ -44,6 +44,7 @@ class IDBResultData;
 class IDBValue;
 class SecurityOrigin;
 
+struct IDBGetAllRecordsData;
 struct IDBGetRecordData;
 
 namespace IDBClient {
@@ -89,6 +90,9 @@ public:
     void getRecord(const IDBRequestData&, const IDBGetRecordData&);
     WEBCORE_EXPORT void didGetRecord(const IDBResultData&);
 
+    void getAllRecords(const IDBRequestData&, const IDBGetAllRecordsData&);
+    WEBCORE_EXPORT void didGetAllRecords(const IDBResultData&);
+
     void getCount(const IDBRequestData&, const IDBKeyRangeData&);
     WEBCORE_EXPORT void didGetCount(const IDBResultData&);
 
index 55a6f6b..d9fc771 100644 (file)
@@ -40,6 +40,7 @@ class IDBResourceIdentifier;
 class IDBTransactionInfo;
 class IDBValue;
 
+struct IDBGetAllRecordsData;
 struct IDBGetRecordData;
 struct SecurityOriginData;
 
@@ -70,6 +71,7 @@ public:
     virtual void renameIndex(const IDBRequestData&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName) = 0;
     virtual void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, const IndexedDB::ObjectStoreOverwriteMode) = 0;
     virtual void getRecord(const IDBRequestData&, const IDBGetRecordData&) = 0;
+    virtual void getAllRecords(const IDBRequestData&, const IDBGetAllRecordsData&) = 0;
     virtual void getCount(const IDBRequestData&, const IDBKeyRangeData&) = 0;
     virtual void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&) = 0;
     virtual void openCursor(const IDBRequestData&, const IDBCursorInfo&) = 0;
index 8f17a2f..66786f1 100644 (file)
@@ -34,6 +34,7 @@
 namespace WebCore {
 
 class IDBCursorInfo;
+class IDBGetAllResult;
 class IDBGetResult;
 class IDBIndexInfo;
 class IDBKeyData;
@@ -43,6 +44,7 @@ class IDBTransactionInfo;
 class IDBValue;
 class ThreadSafeDataBuffer;
 
+struct IDBGetAllRecordsData;
 struct IDBKeyRangeData;
 
 namespace IndexedDB {
@@ -79,6 +81,7 @@ public:
     virtual IDBError deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&) = 0;
     virtual IDBError addRecord(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo&, const IDBKeyData&, const IDBValue&) = 0;
     virtual IDBError getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, IDBGetResult& outValue) = 0;
+    virtual IDBError getAllRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData&, IDBGetAllResult& outValue) = 0;
     virtual IDBError getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&, IDBGetResult& outValue) = 0;
     virtual IDBError getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&, uint64_t& outCount) = 0;
     virtual IDBError generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber) = 0;
index 5300c01..55bea54 100644 (file)
@@ -108,6 +108,11 @@ void IDBConnectionToClient::didGetRecord(const IDBResultData& result)
     m_delegate->didGetRecord(result);
 }
 
+void IDBConnectionToClient::didGetAllRecords(const IDBResultData& result)
+{
+    m_delegate->didGetAllRecords(result);
+}
+
 void IDBConnectionToClient::didGetCount(const IDBResultData& result)
 {
     m_delegate->didGetCount(result);
index e3021bc..bcdf390 100644 (file)
@@ -62,6 +62,7 @@ public:
     void didRenameIndex(const IDBResultData&);
     void didPutOrAdd(const IDBResultData&);
     void didGetRecord(const IDBResultData&);
+    void didGetAllRecords(const IDBResultData&);
     void didGetCount(const IDBResultData&);
     void didDeleteRecord(const IDBResultData&);
     void didOpenCursor(const IDBResultData&);
index d767f68..6a41b45 100644 (file)
@@ -60,6 +60,7 @@ public:
     virtual void didRenameIndex(const IDBResultData&) = 0;
     virtual void didPutOrAdd(const IDBResultData&) = 0;
     virtual void didGetRecord(const IDBResultData&) = 0;
+    virtual void didGetAllRecords(const IDBResultData&) = 0;
     virtual void didGetCount(const IDBResultData&) = 0;
     virtual void didDeleteRecord(const IDBResultData&) = 0;
     virtual void didOpenCursor(const IDBResultData&) = 0;
index f73ea24..dfa7dc5 100644 (file)
@@ -294,6 +294,17 @@ void IDBServer::getRecord(const IDBRequestData& requestData, const IDBGetRecordD
     transaction->getRecord(requestData, getRecordData);
 }
 
+void IDBServer::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData)
+{
+    LOG(IndexedDB, "IDBServer::getAllRecords");
+
+    auto transaction = m_transactions.get(requestData.transactionIdentifier());
+    if (!transaction)
+        return;
+
+    transaction->getAllRecords(requestData, getAllRecordsData);
+}
+
 void IDBServer::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
 {
     LOG(IndexedDB, "IDBServer::getCount");
index b5918c0..2e6aa92 100644 (file)
@@ -74,6 +74,7 @@ public:
     WEBCORE_EXPORT void renameIndex(const IDBRequestData&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName);
     WEBCORE_EXPORT void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode);
     WEBCORE_EXPORT void getRecord(const IDBRequestData&, const IDBGetRecordData&);
+    WEBCORE_EXPORT void getAllRecords(const IDBRequestData&, const IDBGetAllRecordsData&);
     WEBCORE_EXPORT void getCount(const IDBRequestData&, const IDBKeyRangeData&);
     WEBCORE_EXPORT void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&);
     WEBCORE_EXPORT void openCursor(const IDBRequestData&, const IDBCursorInfo&);
index a2bf28f..d53640b 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(INDEXED_DATABASE)
 
 #include "IDBCursorInfo.h"
+#include "IDBGetAllRecordsData.h"
 #include "IDBGetResult.h"
 #include "IDBIndexInfo.h"
 #include "IDBKeyRangeData.h"
@@ -365,6 +366,23 @@ IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transacti
     return IDBError();
 }
 
+IDBError MemoryIDBBackingStore::getAllRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData, IDBGetAllResult& result)
+{
+    LOG(IndexedDB, "MemoryIDBBackingStore::getAllRecords");
+
+    ASSERT(getAllRecordsData.objectStoreIdentifier);
+
+    if (!m_transactions.contains(transactionIdentifier))
+        return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to get all records"));
+
+    MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(getAllRecordsData.objectStoreIdentifier);
+    if (!objectStore)
+        return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found"));
+
+    objectStore->getAllRecords(getAllRecordsData.keyRangeData, getAllRecordsData.count, getAllRecordsData.getAllType, result);
+    return { };
+}
+
 IDBError MemoryIDBBackingStore::getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range, IDBGetResult& outValue)
 {
     LOG(IndexedDB, "MemoryIDBBackingStore::getIndexRecord");
index a1424cd..8a05606 100644 (file)
@@ -63,6 +63,7 @@ public:
     IDBError deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&) final;
     IDBError addRecord(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo&, const IDBKeyData&, const IDBValue&) final;
     IDBError getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, IDBGetResult& outValue) final;
+    IDBError getAllRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData&, IDBGetAllResult& outValue) final;
     IDBError getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&, IDBGetResult& outValue) final;
     IDBError getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&, uint64_t& outCount) final;
     IDBError generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber) final;
index 41e4f40..fa44b7b 100644 (file)
@@ -31,6 +31,7 @@
 #include "IDBBindingUtilities.h"
 #include "IDBDatabaseException.h"
 #include "IDBError.h"
+#include "IDBGetAllResult.h"
 #include "IDBKeyRangeData.h"
 #include "IDBValue.h"
 #include "IndexKey.h"
@@ -407,6 +408,35 @@ ThreadSafeDataBuffer MemoryObjectStore::valueForKeyRange(const IDBKeyRangeData&
     return m_keyValueStore->get(key);
 }
 
+void MemoryObjectStore::getAllRecords(const IDBKeyRangeData& keyRangeData, Optional<uint32_t> count, IndexedDB::GetAllType type, IDBGetAllResult& result) const
+{
+    result = { type };
+
+    uint32_t targetCount;
+    if (count && count.value())
+        targetCount = count.value();
+    else
+        targetCount = std::numeric_limits<uint32_t>::max();
+
+    IDBKeyRangeData range = keyRangeData;
+    uint32_t currentCount = 0;
+    while (currentCount < targetCount) {
+        IDBKeyData key = lowestKeyWithRecordInRange(range);
+        if (key.isNull())
+            return;
+
+        range.lowerKey = key;
+        range.lowerOpen = true;
+
+        if (type == IndexedDB::GetAllType::Keys)
+            result.addKey(WTFMove(key));
+        else
+            result.addValue(valueForKey(key));
+
+        ++currentCount;
+    }
+}
+
 IDBGetResult MemoryObjectStore::indexValueForKeyRange(uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range) const
 {
     LOG(IndexedDB, "MemoryObjectStore::indexValueForKeyRange");
index 0bf57d9..f5fa605 100644 (file)
@@ -41,12 +41,14 @@ namespace WebCore {
 
 class IDBCursorInfo;
 class IDBError;
+class IDBGetAllResult;
 class IDBKeyData;
 class IDBValue;
 
 struct IDBKeyRangeData;
 
 namespace IndexedDB {
+enum class GetAllType;
 enum class IndexRecordType;
 }
 
@@ -87,6 +89,8 @@ public:
     IDBGetResult indexValueForKeyRange(uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&) const;
     uint64_t countForKeyRange(uint64_t indexIdentifier, const IDBKeyRangeData&) const;
 
+    void getAllRecords(const IDBKeyRangeData&, Optional<uint32_t> count, IndexedDB::GetAllType, IDBGetAllResult&) const;
+
     const IDBObjectStoreInfo& info() const { return m_info; }
 
     MemoryObjectStoreCursor* maybeOpenCursor(const IDBCursorInfo&);
index f2f41d0..d9d582d 100644 (file)
@@ -31,6 +31,8 @@
 #include "FileSystem.h"
 #include "IDBBindingUtilities.h"
 #include "IDBDatabaseException.h"
+#include "IDBGetAllRecordsData.h"
+#include "IDBGetAllResult.h"
 #include "IDBGetResult.h"
 #include "IDBKeyData.h"
 #include "IDBObjectStoreInfo.h"
@@ -1876,6 +1878,132 @@ IDBError SQLiteIDBBackingStore::getRecord(const IDBResourceIdentifier& transacti
     return { };
 }
 
+static const ASCIILiteral& queryForGetAllRecords(const IDBGetAllRecordsData& getAllRecordsData)
+{
+    static NeverDestroyed<const ASCIILiteral> lowerOpenUpperOpenKey("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
+    static NeverDestroyed<const ASCIILiteral> lowerOpenUpperClosedKey("SELECT key FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
+    static NeverDestroyed<const ASCIILiteral> lowerClosedUpperOpenKey("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
+    static NeverDestroyed<const ASCIILiteral> lowerClosedUpperClosedKey("SELECT key FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
+    static NeverDestroyed<const ASCIILiteral> lowerOpenUpperOpenValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
+    static NeverDestroyed<const ASCIILiteral> lowerOpenUpperClosedValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key > CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
+    static NeverDestroyed<const ASCIILiteral> lowerClosedUpperOpenValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key < CAST(? AS TEXT) ORDER BY key;");
+    static NeverDestroyed<const ASCIILiteral> lowerClosedUpperClosedValue("SELECT value, ROWID FROM Records WHERE objectStoreID = ? AND key >= CAST(? AS TEXT) AND key <= CAST(? AS TEXT) ORDER BY key;");
+
+    if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Keys) {
+        if (getAllRecordsData.keyRangeData.lowerOpen) {
+            if (getAllRecordsData.keyRangeData.upperOpen)
+                return lowerOpenUpperOpenKey.get();
+            return lowerOpenUpperClosedKey.get();
+        }
+
+        if (getAllRecordsData.keyRangeData.upperOpen)
+            return lowerClosedUpperOpenKey.get();
+        return lowerClosedUpperClosedKey.get();
+    }
+
+    if (getAllRecordsData.keyRangeData.lowerOpen) {
+        if (getAllRecordsData.keyRangeData.upperOpen)
+            return lowerOpenUpperOpenValue.get();
+        return lowerOpenUpperClosedValue.get();
+    }
+
+    if (getAllRecordsData.keyRangeData.upperOpen)
+        return lowerClosedUpperOpenValue.get();
+    return lowerClosedUpperClosedValue.get();
+}
+
+IDBError SQLiteIDBBackingStore::getAllRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData, IDBGetAllResult& result)
+{
+    LOG(IndexedDB, "SQLiteIDBBackingStore::getAllRecords");
+
+    ASSERT(m_sqliteDB);
+    ASSERT(m_sqliteDB->isOpen());
+
+    auto* transaction = m_transactions.get(transactionIdentifier);
+    if (!transaction || !transaction->inProgress()) {
+        LOG_ERROR("Attempt to get records from database without an in-progress transaction");
+        return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to get records from database without an in-progress transaction") };
+    }
+
+    auto key = getAllRecordsData.keyRangeData.lowerKey;
+    if (key.isNull())
+        key = IDBKeyData::minimum();
+    auto lowerBuffer = serializeIDBKeyData(key);
+    if (!lowerBuffer) {
+        LOG_ERROR("Unable to serialize lower IDBKey in lookup range");
+        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize lower IDBKey in lookup range") };
+    }
+
+    key = getAllRecordsData.keyRangeData.upperKey;
+    if (key.isNull())
+        key = IDBKeyData::maximum();
+    auto upperBuffer = serializeIDBKeyData(key);
+    if (!upperBuffer) {
+        LOG_ERROR("Unable to serialize upper IDBKey in lookup range");
+        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize upper IDBKey in lookup range") };
+    }
+
+    SQLiteStatement sql(*m_sqliteDB, queryForGetAllRecords(getAllRecordsData));
+    if (sql.prepare() != SQLITE_OK
+        || sql.bindInt64(1, getAllRecordsData.objectStoreIdentifier) != SQLITE_OK
+        || sql.bindBlob(2, lowerBuffer->data(), lowerBuffer->size()) != SQLITE_OK
+        || sql.bindBlob(3, upperBuffer->data(), upperBuffer->size()) != SQLITE_OK) {
+        LOG_ERROR("Could not get key range record from object store %" PRIi64 " from Records table (%i) - %s", getAllRecordsData.objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+        return { IDBDatabaseException::UnknownError, ASCIILiteral("Failed to look up record in object store by key range") };
+    }
+
+    result = { getAllRecordsData.getAllType };
+
+    int sqlResult = sql.step();
+    uint32_t returnedResults = 0;
+    uint32_t targetResults = getAllRecordsData.count ? getAllRecordsData.count.value() : 0;
+    if (!targetResults)
+        targetResults = std::numeric_limits<uint32_t>::max();
+
+    while (sqlResult == SQLITE_ROW && returnedResults < targetResults) {
+        if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Values) {
+            Vector<uint8_t> buffer;
+            sql.getColumnBlobAsVector(0, buffer);
+            ThreadSafeDataBuffer resultBuffer = ThreadSafeDataBuffer::adoptVector(buffer);
+
+            auto recordID = sql.getColumnInt64(1);
+
+            ASSERT(recordID);
+            Vector<String> blobURLs, blobFilePaths;
+            auto error = getBlobRecordsForObjectStoreRecord(recordID, blobURLs, blobFilePaths);
+            ASSERT(blobURLs.size() == blobFilePaths.size());
+
+            if (!error.isNull())
+                return error;
+
+            result.addValue({ resultBuffer, WTFMove(blobURLs), WTFMove(blobFilePaths) });
+        } else {
+            Vector<uint8_t> keyData;
+            IDBKeyData key;
+            sql.getColumnBlobAsVector(0, keyData);
+
+            if (!deserializeIDBKeyData(keyData.data(), keyData.size(), key)) {
+                LOG_ERROR("Unable to deserialize key data from database while getting all key records");
+                return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to deserialize key data while getting all key records") };
+            }
+
+            result.addKey(WTFMove(key));
+        }
+
+        ++returnedResults;
+        sqlResult = sql.step();
+    }
+
+    if (sqlResult == SQLITE_OK || sqlResult == SQLITE_DONE || sqlResult == SQLITE_ROW) {
+        // Finished getting results
+        return { };
+    }
+
+    // There was an error fetching records from the database.
+    LOG_ERROR("Could not get record from object store %" PRIi64 " from Records table (%i) - %s", getAllRecordsData.objectStoreIdentifier, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+    return { IDBDatabaseException::UnknownError, ASCIILiteral("Error looking up record in object store by key range") };
+}
+
 IDBError SQLiteIDBBackingStore::getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreID, uint64_t indexID, IndexedDB::IndexRecordType type, const IDBKeyRangeData& range, IDBGetResult& getResult)
 {
     LOG(IndexedDB, "SQLiteIDBBackingStore::getIndexRecord - %s", range.loggingString().utf8().data());
index 8c0c9be..2ef8586 100644 (file)
@@ -67,6 +67,7 @@ public:
     IDBError deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&) final;
     IDBError addRecord(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo&, const IDBKeyData&, const IDBValue&) final;
     IDBError getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, IDBGetResult& outValue) final;
+    IDBError getAllRecords(const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData&, IDBGetAllResult& outValue) final;
     IDBError getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&, IDBGetResult& outValue) final;
     IDBError getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&, uint64_t& outCount) final;
     IDBError generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber) final;
index 06b16fe..4ef69da 100644 (file)
@@ -29,6 +29,8 @@
 #if ENABLE(INDEXED_DATABASE)
 
 #include "IDBCursorInfo.h"
+#include "IDBGetAllRecordsData.h"
+#include "IDBGetAllResult.h"
 #include "IDBGetRecordData.h"
 #include "IDBKeyRangeData.h"
 #include "IDBResultData.h"
@@ -97,6 +99,7 @@ bool UniqueIDBDatabase::hasAnyPendingCallbacks() const
     return !m_errorCallbacks.isEmpty()
         || !m_keyDataCallbacks.isEmpty()
         || !m_getResultCallbacks.isEmpty()
+        || !m_getAllResultsCallbacks.isEmpty()
         || !m_countCallbacks.isEmpty();
 }
 
@@ -408,6 +411,19 @@ uint64_t UniqueIDBDatabase::storeCallbackOrFireError(GetResultCallback callback)
     return identifier;
 }
 
+uint64_t UniqueIDBDatabase::storeCallbackOrFireError(GetAllResultsCallback callback)
+{
+    if (m_hardClosedForUserDelete) {
+        callback(IDBError::userDeleteError(), { });
+        return 0;
+    }
+
+    uint64_t identifier = generateUniqueCallbackIdentifier();
+    ASSERT(!m_getAllResultsCallbacks.contains(identifier));
+    m_getAllResultsCallbacks.add(identifier, callback);
+    return identifier;
+}
+
 uint64_t UniqueIDBDatabase::storeCallbackOrFireError(CountCallback callback)
 {
     if (m_hardClosedForUserDelete) {
@@ -1028,6 +1044,18 @@ void UniqueIDBDatabase::getRecord(const IDBRequestData& requestData, const IDBGe
         postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetRecord, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), getRecordData.keyRangeData));
 }
 
+void UniqueIDBDatabase::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
+{
+    ASSERT(isMainThread());
+    LOG(IndexedDB, "(main) UniqueIDBDatabase::getAllRecords");
+
+    uint64_t callbackID = storeCallbackOrFireError(callback);
+    if (!callbackID)
+        return;
+
+    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performGetAllRecords, callbackID, requestData.transactionIdentifier(), getAllRecordsData));
+}
+
 void UniqueIDBDatabase::performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& keyRangeData)
 {
     ASSERT(!isMainThread());
@@ -1062,6 +1090,27 @@ void UniqueIDBDatabase::didPerformGetRecord(uint64_t callbackIdentifier, const I
     performGetResultCallback(callbackIdentifier, error, result);
 }
 
+void UniqueIDBDatabase::performGetAllRecords(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData& getAllRecordsData)
+{
+    ASSERT(!isMainThread());
+    LOG(IndexedDB, "(db) UniqueIDBDatabase::performGetAllRecords");
+
+    ASSERT(m_backingStore);
+
+    IDBGetAllResult result;
+    IDBError error = m_backingStore->getAllRecords(transactionIdentifier, getAllRecordsData, result);
+
+    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformGetAllRecords, callbackIdentifier, error, WTFMove(result)));
+}
+
+void UniqueIDBDatabase::didPerformGetAllRecords(uint64_t callbackIdentifier, const IDBError& error, const IDBGetAllResult& result)
+{
+    ASSERT(isMainThread());
+    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformGetAllRecords");
+
+    performGetAllResultsCallback(callbackIdentifier, error, result);
+}
+
 void UniqueIDBDatabase::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
 {
     ASSERT(isMainThread());
@@ -1801,6 +1850,14 @@ void UniqueIDBDatabase::performGetResultCallback(uint64_t callbackIdentifier, co
         callback(error, resultData);
 }
 
+void UniqueIDBDatabase::performGetAllResultsCallback(uint64_t callbackIdentifier, const IDBError& error, const IDBGetAllResult& resultData)
+{
+    auto callback = m_getAllResultsCallbacks.take(callbackIdentifier);
+    ASSERT(callback || m_hardClosedForUserDelete);
+    if (callback)
+        callback(error, resultData);
+}
+
 void UniqueIDBDatabase::performCountCallback(uint64_t callbackIdentifier, const IDBError& error, uint64_t count)
 {
     auto callback = m_countCallbacks.take(callbackIdentifier);
index 5ce6688..05f4582 100644 (file)
@@ -53,6 +53,7 @@ class VM;
 namespace WebCore {
 
 class IDBError;
+class IDBGetAllResult;
 class IDBRequestData;
 class IDBTransactionInfo;
 
@@ -68,6 +69,7 @@ class IDBServer;
 typedef std::function<void(const IDBError&)> ErrorCallback;
 typedef std::function<void(const IDBError&, const IDBKeyData&)> KeyDataCallback;
 typedef std::function<void(const IDBError&, const IDBGetResult&)> GetResultCallback;
+typedef std::function<void(const IDBError&, const IDBGetAllResult&)> GetAllResultsCallback;
 typedef std::function<void(const IDBError&, uint64_t)> CountCallback;
 
 class UniqueIDBDatabase : public ThreadSafeRefCounted<UniqueIDBDatabase> {
@@ -94,6 +96,7 @@ public:
     void renameIndex(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback);
     void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback);
     void getRecord(const IDBRequestData&, const IDBGetRecordData&, GetResultCallback);
+    void getAllRecords(const IDBRequestData&, const IDBGetAllRecordsData&, GetAllResultsCallback);
     void getCount(const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
     void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
     void openCursor(const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
@@ -153,6 +156,7 @@ private:
     void performRenameIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName);
     void performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode);
     void performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&);
+    void performGetAllRecords(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData&);
     void performGetIndexRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&);
     void performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&);
     void performDeleteRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&);
@@ -173,6 +177,7 @@ private:
     void didPerformRenameIndex(uint64_t callbackIdentifier, const IDBError&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName);
     void didPerformPutOrAdd(uint64_t callbackIdentifier, const IDBError&, const IDBKeyData&);
     void didPerformGetRecord(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
+    void didPerformGetAllRecords(uint64_t callbackIdentifier, const IDBError&, const IDBGetAllResult&);
     void didPerformGetCount(uint64_t callbackIdentifier, const IDBError&, uint64_t);
     void didPerformDeleteRecord(uint64_t callbackIdentifier, const IDBError&);
     void didPerformOpenCursor(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
@@ -184,12 +189,14 @@ private:
 
     uint64_t storeCallbackOrFireError(ErrorCallback);
     uint64_t storeCallbackOrFireError(KeyDataCallback);
+    uint64_t storeCallbackOrFireError(GetAllResultsCallback);
     uint64_t storeCallbackOrFireError(GetResultCallback);
     uint64_t storeCallbackOrFireError(CountCallback);
 
     void performErrorCallback(uint64_t callbackIdentifier, const IDBError&);
     void performKeyDataCallback(uint64_t callbackIdentifier, const IDBError&, const IDBKeyData&);
     void performGetResultCallback(uint64_t callbackIdentifier, const IDBError&, const IDBGetResult&);
+    void performGetAllResultsCallback(uint64_t callbackIdentifier, const IDBError&, const IDBGetAllResult&);
     void performCountCallback(uint64_t callbackIdentifier, const IDBError&, uint64_t);
 
     void forgetErrorCallback(uint64_t callbackIdentifier);
@@ -237,6 +244,7 @@ private:
     HashMap<uint64_t, ErrorCallback> m_errorCallbacks;
     HashMap<uint64_t, KeyDataCallback> m_keyDataCallbacks;
     HashMap<uint64_t, GetResultCallback> m_getResultCallbacks;
+    HashMap<uint64_t, GetAllResultsCallback> m_getAllResultsCallbacks;
     HashMap<uint64_t, CountCallback> m_countCallbacks;
 
     Timer m_operationAndTransactionTimer;
index 6028457..6412236 100644 (file)
@@ -257,6 +257,23 @@ void UniqueIDBDatabaseTransaction::getRecord(const IDBRequestData& requestData,
     });
 }
 
+void UniqueIDBDatabaseTransaction::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData)
+{
+    LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getAllRecords");
+
+    ASSERT(m_transactionInfo.identifier() == requestData.transactionIdentifier());
+
+    RefPtr<UniqueIDBDatabaseTransaction> protectedThis(this);
+    m_databaseConnection->database().getAllRecords(requestData, getAllRecordsData, [this, protectedThis, requestData](const IDBError& error, const IDBGetAllResult& result) {
+        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getAllRecords (callback)");
+
+        if (error.isNull())
+            m_databaseConnection->connectionToClient().didGetAllRecords(IDBResultData::getAllRecordsSuccess(requestData.requestIdentifier(), result));
+        else
+            m_databaseConnection->connectionToClient().didGetAllRecords(IDBResultData::error(requestData.requestIdentifier(), error));
+    });
+}
+
 void UniqueIDBDatabaseTransaction::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
 {
     LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getCount");
index 2326b30..be3b6c7 100644 (file)
@@ -43,6 +43,7 @@ class IDBObjectStoreInfo;
 class IDBRequestData;
 class IDBValue;
 
+struct IDBGetAllRecordsData;
 struct IDBGetRecordData;
 struct IDBKeyRangeData;
 
@@ -76,6 +77,7 @@ public:
     void renameIndex(const IDBRequestData&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName);
     void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode);
     void getRecord(const IDBRequestData&, const IDBGetRecordData&);
+    void getAllRecords(const IDBRequestData&, const IDBGetAllRecordsData&);
     void getCount(const IDBRequestData&, const IDBKeyRangeData&);
     void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&);
     void openCursor(const IDBRequestData&, const IDBCursorInfo&);
diff --git a/Source/WebCore/Modules/indexeddb/shared/IDBGetAllRecordsData.cpp b/Source/WebCore/Modules/indexeddb/shared/IDBGetAllRecordsData.cpp
new file mode 100644 (file)
index 0000000..6651bc2
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IDBGetAllRecordsData.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBKeyRangeData.h"
+
+namespace WebCore {
+
+IDBGetAllRecordsData IDBGetAllRecordsData::isolatedCopy() const
+{
+    return { keyRangeData.isolatedCopy(), getAllType, count, objectStoreIdentifier, indexIdentifier };
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/Modules/indexeddb/shared/IDBGetAllRecordsData.h b/Source/WebCore/Modules/indexeddb/shared/IDBGetAllRecordsData.h
new file mode 100644 (file)
index 0000000..f97f332
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBKeyRangeData.h"
+#include <wtf/Optional.h>
+
+namespace WebCore {
+
+namespace IndexedDB {
+enum class DataSource;
+enum class GetAllType;
+}
+
+struct IDBGetAllRecordsData {
+    IDBKeyRangeData keyRangeData;
+    IndexedDB::GetAllType getAllType;
+    Optional<uint32_t> count;
+    uint64_t objectStoreIdentifier;
+    uint64_t indexIdentifier;
+
+    IDBGetAllRecordsData isolatedCopy() const;
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static bool decode(Decoder&, IDBGetAllRecordsData&);
+};
+
+template<class Encoder>
+void IDBGetAllRecordsData::encode(Encoder& encoder) const
+{
+    encoder << keyRangeData;
+    encoder.encodeEnum(getAllType);
+    encoder << count << objectStoreIdentifier << indexIdentifier;
+}
+
+template<class Decoder>
+bool IDBGetAllRecordsData::decode(Decoder& decoder, IDBGetAllRecordsData& getAllRecordsData)
+{
+    if (!decoder.decode(getAllRecordsData.keyRangeData))
+        return false;
+
+    if (!decoder.decodeEnum(getAllRecordsData.getAllType))
+        return false;
+
+    if (!decoder.decode(getAllRecordsData.count))
+        return false;
+
+    if (!decoder.decode(getAllRecordsData.objectStoreIdentifier))
+        return false;
+
+    if (!decoder.decode(getAllRecordsData.indexIdentifier))
+        return false;
+
+    return true;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
index d9061ab..a8119dc 100644 (file)
@@ -64,6 +64,8 @@ IDBResultData::IDBResultData(const IDBResultData& other)
         m_resultKey = std::make_unique<IDBKeyData>(*other.m_resultKey);
     if (other.m_getResult)
         m_getResult = std::make_unique<IDBGetResult>(*other.m_getResult);
+    if (other.m_getAllResult)
+        m_getAllResult = std::make_unique<IDBGetAllResult>(*other.m_getAllResult);
 }
 
 IDBResultData::IDBResultData(const IDBResultData& that, IsolatedCopyTag)
@@ -178,6 +180,13 @@ IDBResultData IDBResultData::getRecordSuccess(const IDBResourceIdentifier& reque
     return result;
 }
 
+IDBResultData IDBResultData::getAllRecordsSuccess(const IDBResourceIdentifier& requestIdentifier, const IDBGetAllResult& getAllResult)
+{
+    IDBResultData result(IDBResultType::GetAllRecordsSuccess, requestIdentifier);
+    result.m_getAllResult = std::make_unique<IDBGetAllResult>(getAllResult);
+    return result;
+}
+
 IDBResultData IDBResultData::getCountSuccess(const IDBResourceIdentifier& requestIdentifier, uint64_t count)
 {
     IDBResultData result(IDBResultType::GetRecordSuccess, requestIdentifier);
@@ -222,6 +231,12 @@ const IDBGetResult& IDBResultData::getResult() const
     return *m_getResult;
 }
 
+const IDBGetAllResult& IDBResultData::getAllResult() const
+{
+    RELEASE_ASSERT(m_getAllResult);
+    return *m_getAllResult;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index 03bb225..b484bc4 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "IDBDatabaseInfo.h"
 #include "IDBError.h"
+#include "IDBGetAllResult.h"
 #include "IDBGetResult.h"
 #include "IDBKeyData.h"
 #include "IDBResourceIdentifier.h"
@@ -51,6 +52,7 @@ enum class IDBResultType {
     ClearObjectStoreSuccess,
     PutOrAddSuccess,
     GetRecordSuccess,
+    GetAllRecordsSuccess,
     GetCountSuccess,
     DeleteRecordSuccess,
     CreateIndexSuccess,
@@ -81,6 +83,7 @@ public:
     static IDBResultData renameIndexSuccess(const IDBResourceIdentifier&);
     static IDBResultData putOrAddSuccess(const IDBResourceIdentifier&, const IDBKeyData&);
     static IDBResultData getRecordSuccess(const IDBResourceIdentifier&, const IDBGetResult&);
+    static IDBResultData getAllRecordsSuccess(const IDBResourceIdentifier&, const IDBGetAllResult&);
     static IDBResultData getCountSuccess(const IDBResourceIdentifier&, uint64_t count);
     static IDBResultData deleteRecordSuccess(const IDBResourceIdentifier&);
     static IDBResultData openCursorSuccess(const IDBResourceIdentifier&, const IDBGetResult&);
@@ -105,6 +108,7 @@ public:
     uint64_t resultInteger() const { return m_resultInteger; }
 
     WEBCORE_EXPORT const IDBGetResult& getResult() const;
+    WEBCORE_EXPORT const IDBGetAllResult& getAllResult() const;
 
     WEBCORE_EXPORT IDBResultData();
     template<class Encoder> void encode(Encoder&) const;
@@ -125,6 +129,7 @@ private:
     std::unique_ptr<IDBTransactionInfo> m_transactionInfo;
     std::unique_ptr<IDBKeyData> m_resultKey;
     std::unique_ptr<IDBGetResult> m_getResult;
+    std::unique_ptr<IDBGetAllResult> m_getAllResult;
     uint64_t m_resultInteger { 0 };
 };
 
@@ -150,6 +155,10 @@ void IDBResultData::encode(Encoder& encoder) const
     encoder << !!m_getResult;
     if (m_getResult)
         encoder << *m_getResult;
+
+    encoder << !!m_getAllResult;
+    if (m_getAllResult)
+        encoder << *m_getAllResult;
 }
 
 template<class Decoder> bool IDBResultData::decode(Decoder& decoder, IDBResultData& result)
@@ -174,7 +183,7 @@ template<class Decoder> bool IDBResultData::decode(Decoder& decoder, IDBResultDa
     if (!decoder.decode(hasObject))
         return false;
     if (hasObject) {
-        std::unique_ptr<IDBDatabaseInfo> object = std::make_unique<IDBDatabaseInfo>();
+        auto object = std::make_unique<IDBDatabaseInfo>();
         if (!decoder.decode(*object))
             return false;
         result.m_databaseInfo = WTFMove(object);
@@ -183,7 +192,7 @@ template<class Decoder> bool IDBResultData::decode(Decoder& decoder, IDBResultDa
     if (!decoder.decode(hasObject))
         return false;
     if (hasObject) {
-        std::unique_ptr<IDBTransactionInfo> object = std::make_unique<IDBTransactionInfo>();
+        auto object = std::make_unique<IDBTransactionInfo>();
         if (!decoder.decode(*object))
             return false;
         result.m_transactionInfo = WTFMove(object);
@@ -192,7 +201,7 @@ template<class Decoder> bool IDBResultData::decode(Decoder& decoder, IDBResultDa
     if (!decoder.decode(hasObject))
         return false;
     if (hasObject) {
-        std::unique_ptr<IDBKeyData> object = std::make_unique<IDBKeyData>();
+        auto object = std::make_unique<IDBKeyData>();
         if (!decoder.decode(*object))
             return false;
         result.m_resultKey = WTFMove(object);
@@ -201,12 +210,21 @@ template<class Decoder> bool IDBResultData::decode(Decoder& decoder, IDBResultDa
     if (!decoder.decode(hasObject))
         return false;
     if (hasObject) {
-        std::unique_ptr<IDBGetResult> object = std::make_unique<IDBGetResult>();
+        auto object = std::make_unique<IDBGetResult>();
         if (!decoder.decode(*object))
             return false;
         result.m_getResult = WTFMove(object);
     }
 
+    if (!decoder.decode(hasObject))
+        return false;
+    if (hasObject) {
+        auto object = std::make_unique<IDBGetAllResult>();
+        if (!decoder.decode(*object))
+            return false;
+        result.m_getAllResult = WTFMove(object);
+    }
+
     return true;
 }
 
index dce4c34..7811aee 100644 (file)
@@ -195,6 +195,13 @@ void InProcessIDBServer::didGetRecord(const IDBResultData& resultData)
     });
 }
 
+void InProcessIDBServer::didGetAllRecords(const IDBResultData& resultData)
+{
+    RunLoop::current().dispatch([this, protectedThis = makeRef(*this), resultData] {
+        m_connectionToServer->didGetAllRecords(resultData);
+    });
+}
+
 void InProcessIDBServer::didGetCount(const IDBResultData& resultData)
 {
     RunLoop::current().dispatch([this, protectedThis = makeRef(*this), resultData] {
@@ -307,6 +314,13 @@ void InProcessIDBServer::getRecord(const IDBRequestData& requestData, const IDBG
     });
 }
 
+void InProcessIDBServer::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData)
+{
+    RunLoop::current().dispatch([this, protectedThis = makeRef(*this), requestData, getAllRecordsData] {
+        m_server->getAllRecords(requestData, getAllRecordsData);
+    });
+}
+
 void InProcessIDBServer::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData)
 {
     RunLoop::current().dispatch([this, protectedThis = makeRef(*this), requestData, keyRangeData] {
index 7835503..b57631a 100644 (file)
@@ -71,6 +71,7 @@ public:
     void renameIndex(const IDBRequestData&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName) final;
     void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, const IndexedDB::ObjectStoreOverwriteMode) final;
     void getRecord(const IDBRequestData&, const IDBGetRecordData&) final;
+    void getAllRecords(const IDBRequestData&, const IDBGetAllRecordsData&) final;
     void getCount(const IDBRequestData&, const IDBKeyRangeData&) final;
     void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&) final;
     void openCursor(const IDBRequestData&, const IDBCursorInfo&) final;
@@ -98,6 +99,7 @@ public:
     void didRenameIndex(const IDBResultData&) final;
     void didPutOrAdd(const IDBResultData&) final;
     void didGetRecord(const IDBResultData&) final;
+    void didGetAllRecords(const IDBResultData&) final;
     void didGetCount(const IDBResultData&) final;
     void didDeleteRecord(const IDBResultData&) final;
     void didOpenCursor(const IDBResultData&) final;
index ea97581..613a0cc 100644 (file)
                5198F7AD1BBDD3EB00E2CC5F /* IDBTransactionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 5198F7AB1BBDD3E300E2CC5F /* IDBTransactionInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5198F7C01BC4856700E2CC5F /* IDBConnectionToServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5185FCBC1BB5CB770012898F /* IDBConnectionToServer.cpp */; };
                5198F7C11BC4856700E2CC5F /* IDBConnectionToServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 510A58FD1BB07A9600C19282 /* IDBConnectionToServer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               519DBC6E1DC011A200329BF5 /* IDBGetAllRecordsData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 519DBC6D1DC00FB900329BF5 /* IDBGetAllRecordsData.cpp */; };
+               519DBC6F1DC011A700329BF5 /* IDBGetAllRecordsData.h in Headers */ = {isa = PBXBuildFile; fileRef = 519DBC6C1DC00FA000329BF5 /* IDBGetAllRecordsData.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               519DBC721DC10F5200329BF5 /* IDBGetAllResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 519DBC711DC10D3300329BF5 /* IDBGetAllResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               519DBC731DC10F5600329BF5 /* IDBGetAllResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 519DBC701DC10D3300329BF5 /* IDBGetAllResult.cpp */; };
                51A052331058774F00CC9E95 /* CredentialStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A052311058774F00CC9E95 /* CredentialStorage.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51A052341058774F00CC9E95 /* CredentialStorage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A052321058774F00CC9E95 /* CredentialStorage.cpp */; };
                51A052561058874000CC9E95 /* ProtectionSpaceHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A052551058874000CC9E95 /* ProtectionSpaceHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5198F7A71BBDD38100E2CC5F /* UniqueIDBDatabaseTransaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniqueIDBDatabaseTransaction.h; sourceTree = "<group>"; };
                5198F7AA1BBDD3E300E2CC5F /* IDBTransactionInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBTransactionInfo.cpp; sourceTree = "<group>"; };
                5198F7AB1BBDD3E300E2CC5F /* IDBTransactionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBTransactionInfo.h; sourceTree = "<group>"; };
+               519DBC6C1DC00FA000329BF5 /* IDBGetAllRecordsData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBGetAllRecordsData.h; sourceTree = "<group>"; };
+               519DBC6D1DC00FB900329BF5 /* IDBGetAllRecordsData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBGetAllRecordsData.cpp; sourceTree = "<group>"; };
+               519DBC701DC10D3300329BF5 /* IDBGetAllResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBGetAllResult.cpp; sourceTree = "<group>"; };
+               519DBC711DC10D3300329BF5 /* IDBGetAllResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBGetAllResult.h; sourceTree = "<group>"; };
                519FE0A10DAD446E00A08F21 /* HTMLAttributeNames.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLAttributeNames.in; sourceTree = "<group>"; };
                519FE0A20DAD446E00A08F21 /* HTMLTagNames.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLTagNames.in; sourceTree = "<group>"; };
                51A052311058774F00CC9E95 /* CredentialStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CredentialStorage.h; sourceTree = "<group>"; };
                                51BA4AC21BBB5CBF00DF3D6D /* IDBDatabaseInfo.h */,
                                5148453C1BB9D076006A72ED /* IDBError.cpp */,
                                5148453D1BB9D076006A72ED /* IDBError.h */,
+                               519DBC6D1DC00FB900329BF5 /* IDBGetAllRecordsData.cpp */,
+                               519DBC6C1DC00FA000329BF5 /* IDBGetAllRecordsData.h */,
                                5105F06A1D4BB0BC00FB80BC /* IDBGetRecordData.cpp */,
                                5105F0681D4BA54100FB80BC /* IDBGetRecordData.h */,
                                51F798EB1BE880D3008AE491 /* IDBIndexInfo.cpp */,
                                51645B461B9F889B00F789CE /* IDBFactory.cpp */,
                                51645B471B9F889B00F789CE /* IDBFactory.h */,
                                51D7198A181106DF0016DC51 /* IDBFactory.idl */,
+                               519DBC701DC10D3300329BF5 /* IDBGetAllResult.cpp */,
+                               519DBC711DC10D3300329BF5 /* IDBGetAllResult.h */,
                                512F1A771C07EA0D00908239 /* IDBGetResult.cpp */,
                                5123AF1C18918AE40031CDC9 /* IDBGetResult.h */,
                                51645B481B9F889B00F789CE /* IDBIndex.cpp */,
                                E16A84FA14C85CCC002977DF /* CSSBorderImage.h in Headers */,
                                BC274B2F140EBEB200EADFA6 /* CSSBorderImageSliceValue.h in Headers */,
                                49AE2D8F134EE50C0072920A /* CSSCalculationValue.h in Headers */,
+                               519DBC6F1DC011A700329BF5 /* IDBGetAllRecordsData.h in Headers */,
                                BC6049CC0DB560C200204739 /* CSSCanvasValue.h in Headers */,
                                BCEA4790097CAAC80094C9E4 /* CSSComputedStyleDeclaration.h in Headers */,
                                9DAC7C551AF2CAA200437C44 /* CSSContentDistributionValue.h in Headers */,
                                FFEFAB2A18380DA000514534 /* LineLayoutState.h in Headers */,
                                FFDBC047183D27B700407109 /* LineWidth.h in Headers */,
                                A7AD2F880EC89D07008AB002 /* LinkHash.h in Headers */,
+                               519DBC721DC10F5200329BF5 /* IDBGetAllResult.h in Headers */,
                                1A4DA4221CDD3A8300F4473C /* LinkIconCollector.h in Headers */,
                                1A250E0D1CDD632000D0BE63 /* LinkIconType.h in Headers */,
                                98CE432A129E00E5005821DC /* LinkLoader.h in Headers */,
                                CDEA76351460B71A008B31F1 /* Clock.cpp in Sources */,
                                CDEA76341460B56F008B31F1 /* ClockGeneric.cpp in Sources */,
                                9BD8A95A18BEFC7600987E9A /* CollectionIndexCache.cpp in Sources */,
+                               519DBC6E1DC011A200329BF5 /* IDBGetAllRecordsData.cpp in Sources */,
                                B27535660B053814002CE64F /* Color.cpp in Sources */,
                                0FCF33240F2B9715004B6795 /* ColorCG.cpp in Sources */,
                                1ABA76C911D20E47004C201C /* ColorData.cpp in Sources */,
                                A8EA7D320A19385500A8EF5F /* HTMLMapElement.cpp in Sources */,
                                A8EA7CAC0A192B9C00A8EF5F /* HTMLMarqueeElement.cpp in Sources */,
                                E44613A40CD6331000FADA75 /* HTMLMediaElement.cpp in Sources */,
+                               519DBC731DC10F5600329BF5 /* IDBGetAllResult.cpp in Sources */,
                                C968B2E81B1E778100EF1F81 /* HTMLMediaElementMediaSession.cpp in Sources */,
                                0779BF0D18453168000B6AE7 /* HTMLMediaElementMediaStream.cpp in Sources */,
                                A8EA79F80A1916DF00A8EF5F /* HTMLMenuElement.cpp in Sources */,
index d67c470..598e8e5 100644 (file)
@@ -301,7 +301,7 @@ bool canInjectIDBKeyIntoScriptValue(ExecState& exec, const JSValue& scriptValue,
     return canInjectNthValueOnKeyPath(exec, scriptValue, keyPathElements, keyPathElements.size() - 1);
 }
 
-JSValue deserializeIDBValueToJSValue(ExecState& exec, const IDBValue& value)
+static JSValue deserializeIDBValueToJSValue(ExecState& state, JSC::JSGlobalObject& globalObject, const IDBValue& value)
 {
     // FIXME: I think it's peculiar to use undefined to mean "null data" and null to mean "empty data".
     // But I am not changing this at the moment because at least some callers are specifically checking isUndefined.
@@ -315,14 +315,25 @@ JSValue deserializeIDBValueToJSValue(ExecState& exec, const IDBValue& value)
 
     auto serializedValue = SerializedScriptValue::createFromWireBytes(Vector<uint8_t>(data));
 
-    exec.vm().apiLock().lock();
+    state.vm().apiLock().lock();
     Vector<RefPtr<MessagePort>> messagePorts;
-    JSValue result = serializedValue->deserialize(exec, exec.lexicalGlobalObject(), messagePorts, value.blobURLs(), value.blobFilePaths(), NonThrowing);
-    exec.vm().apiLock().unlock();
+    JSValue result = serializedValue->deserialize(state, &globalObject, messagePorts, value.blobURLs(), value.blobFilePaths(), NonThrowing);
+    state.vm().apiLock().unlock();
 
     return result;
 }
 
+JSValue deserializeIDBValueToJSValue(ExecState& state, const IDBValue& value)
+{
+    return deserializeIDBValueToJSValue(state, *state.lexicalGlobalObject(), value);
+}
+
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, const IDBValue& value)
+{
+    ASSERT(state);
+    return deserializeIDBValueToJSValue(*state, *globalObject, value);
+}
+
 Ref<IDBKey> scriptValueToIDBKey(ExecState& exec, const JSValue& scriptValue)
 {
     return createIDBKeyFromValue(exec, scriptValue);
@@ -334,6 +345,14 @@ JSC::JSValue idbKeyDataToScriptValue(JSC::ExecState& exec, const IDBKeyData& key
     return toJS(exec, *exec.lexicalGlobalObject(), key.get());
 }
 
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, const IDBKeyData& keyData)
+{
+    ASSERT(state);
+    ASSERT(globalObject);
+
+    return toJS(*state, *globalObject, keyData.maybeCreateIDBKey().get());
+}
+
 static Vector<IDBKeyData> createKeyPathArray(ExecState& exec, JSValue value, const IDBIndexInfo& info)
 {
     auto visitor = WTF::makeVisitor([&](const String& string) -> Vector<IDBKeyData> {
index 757a29a..36c6e18 100644 (file)
@@ -62,6 +62,9 @@ JSC::JSValue deserializeIDBValueToJSValue(JSC::ExecState&, const IDBValue&);
 
 Ref<IDBKey> scriptValueToIDBKey(JSC::ExecState&, const JSC::JSValue&);
 
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const IDBKeyData&);
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const IDBValue&);
+
 }
 
 #endif // ENABLE(INDEXED_DATABASE)
index 8264670..a76d730 100644 (file)
@@ -1,3 +1,30 @@
+2016-10-31  Brady Eidson  <beidson@apple.com>
+
+        IndexedDB 2.0: Support IDBObjectStore getAll/getAllKeys.
+        <rdar://problem/28806934> and https://bugs.webkit.org/show_bug.cgi?id=164097
+
+        Reviewed by Darin Adler.
+
+        - Handle moving "Get All" requests to and from the DatabaseProcess.
+        - Handle the additional task of creating/passing Sandbox Extensions for
+          referenced files when necessary. 
+          
+        * DatabaseProcess/IndexedDB/WebIDBConnectionToClient.cpp:
+        (WebKit::WebIDBConnectionToClient::handleGetResult):
+        (WebKit::WebIDBConnectionToClient::didGetAllRecords):
+        (WebKit::WebIDBConnectionToClient::getAllRecords):
+        * DatabaseProcess/IndexedDB/WebIDBConnectionToClient.h:
+        * DatabaseProcess/IndexedDB/WebIDBConnectionToClient.messages.in:
+        
+        * Shared/WebCoreArgumentCoders.h:
+        
+        * WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.cpp:
+        (WebKit::WebIDBConnectionToServer::getAllRecords):
+        (WebKit::preregisterSandboxExtensionsIfNecessary):
+        (WebKit::WebIDBConnectionToServer::didGetAllRecords):
+        * WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.h:
+        * WebProcess/Databases/IndexedDB/WebIDBConnectionToServer.messages.in:
+
 2016-10-31  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         [WK1] Candidate visibility should not update as a result of selection during a dictionary lookup
index 309f37f..8064ab4 100644 (file)
@@ -144,7 +144,12 @@ template<class MessageType> void WebIDBConnectionToClient::handleGetResult(const
         return;
     }
 
-    auto& blobFilePaths = resultData.getResult().value().blobFilePaths();
+    if (resultData.type() == IDBResultType::GetAllRecordsSuccess && resultData.getAllResult().type() == IndexedDB::GetAllType::Keys) {
+        send(MessageType(resultData));
+        return;
+    }
+
+    auto blobFilePaths = resultData.type() == IDBResultType::GetAllRecordsSuccess ? resultData.getAllResult().allBlobFilePaths() : resultData.getResult().value().blobFilePaths();
     if (blobFilePaths.isEmpty()) {
         send(MessageType(resultData));
         return;
@@ -165,6 +170,11 @@ void WebIDBConnectionToClient::didGetRecord(const WebCore::IDBResultData& result
     handleGetResult<Messages::WebIDBConnectionToServer::DidGetRecord>(resultData);
 }
 
+void WebIDBConnectionToClient::didGetAllRecords(const WebCore::IDBResultData& resultData)
+{
+    handleGetResult<Messages::WebIDBConnectionToServer::DidGetAllRecords>(resultData);
+}
+
 void WebIDBConnectionToClient::didGetCount(const WebCore::IDBResultData& resultData)
 {
     send(Messages::WebIDBConnectionToServer::DidGetCount(resultData));
@@ -290,6 +300,11 @@ void WebIDBConnectionToClient::getRecord(const IDBRequestData& request, const ID
     DatabaseProcess::singleton().idbServer().getRecord(request, getRecordData);
 }
 
+void WebIDBConnectionToClient::getAllRecords(const IDBRequestData& request, const IDBGetAllRecordsData& getAllRecordsData)
+{
+    DatabaseProcess::singleton().idbServer().getAllRecords(request, getAllRecordsData);
+}
+
 void WebIDBConnectionToClient::getCount(const IDBRequestData& request, const IDBKeyRangeData& range)
 {
     DatabaseProcess::singleton().idbServer().getCount(request, range);
index 2c8e4da..e54ef90 100644 (file)
@@ -40,6 +40,7 @@ class IDBRequestData;
 class IDBTransactionInfo;
 class IDBValue;
 class SerializedScriptValue;
+struct IDBGetAllRecordsData;
 struct IDBGetRecordData;
 struct IDBKeyRangeData;
 struct SecurityOriginData;
@@ -71,6 +72,7 @@ public:
     void didRenameIndex(const WebCore::IDBResultData&) final;
     void didPutOrAdd(const WebCore::IDBResultData&) final;
     void didGetRecord(const WebCore::IDBResultData&) final;
+    void didGetAllRecords(const WebCore::IDBResultData&) final;
     void didGetCount(const WebCore::IDBResultData&) final;
     void didDeleteRecord(const WebCore::IDBResultData&) final;
     void didOpenCursor(const WebCore::IDBResultData&) final;
@@ -101,6 +103,7 @@ public:
     void renameIndex(const WebCore::IDBRequestData&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName);
     void putOrAdd(const WebCore::IDBRequestData&, const WebCore::IDBKeyData&, const WebCore::IDBValue&, unsigned overwriteMode);
     void getRecord(const WebCore::IDBRequestData&, const WebCore::IDBGetRecordData&);
+    void getAllRecords(const WebCore::IDBRequestData&, const WebCore::IDBGetAllRecordsData&);
     void getCount(const WebCore::IDBRequestData&, const WebCore::IDBKeyRangeData&);
     void deleteRecord(const WebCore::IDBRequestData&, const WebCore::IDBKeyRangeData&);
     void openCursor(const WebCore::IDBRequestData&, const WebCore::IDBCursorInfo&);
index d9fabd7..e33731b 100644 (file)
@@ -37,6 +37,7 @@ messages -> WebIDBConnectionToClient {
     RenameIndex(WebCore::IDBRequestData requestData, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, String newName);
     PutOrAdd(WebCore::IDBRequestData requestData, WebCore::IDBKeyData key, WebCore::IDBValue value, unsigned overwriteMode);
     GetRecord(WebCore::IDBRequestData requestData, struct WebCore::IDBGetRecordData getRecordData);
+    GetAllRecords(WebCore::IDBRequestData requestData, struct WebCore::IDBGetAllRecordsData getAllRecordsData);
     GetCount(WebCore::IDBRequestData requestData, struct WebCore::IDBKeyRangeData range);
     DeleteRecord(WebCore::IDBRequestData requestData, struct WebCore::IDBKeyRangeData range);
     OpenCursor(WebCore::IDBRequestData requestData, WebCore::IDBCursorInfo info);
index 0dbb710..0568ace 100644 (file)
@@ -34,6 +34,7 @@
 #include <wtf/HashSet.h>
 #include <wtf/OptionSet.h>
 #include <wtf/Optional.h>
+#include <wtf/Variant.h>
 #include <wtf/Vector.h>
 
 namespace IPC {
index 604dc97..f0e83a7 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "ArgumentCoders.h"
 #include <WebCore/FrameLoaderTypes.h>
+#include <WebCore/IndexedDB.h>
 #include <WebCore/PaymentHeaders.h>
 
 namespace WebCore {
@@ -574,4 +575,14 @@ template<> struct EnumTraits<WebCore::HasInsecureContent> {
     >;
 };
 
+#if ENABLE(INDEXED_DATABASE)
+template<> struct EnumTraits<WebCore::IndexedDB::GetAllType> {
+    using values = EnumValues<
+        WebCore::IndexedDB::GetAllType,
+        WebCore::IndexedDB::GetAllType::Keys,
+        WebCore::IndexedDB::GetAllType::Values
+    >;
+};
+#endif
+
 } // namespace WTF
index f6defce..2ca351b 100644 (file)
@@ -154,6 +154,11 @@ void WebIDBConnectionToServer::getRecord(const IDBRequestData& requestData, cons
     send(Messages::WebIDBConnectionToClient::GetRecord(requestData, getRecordData));
 }
 
+void WebIDBConnectionToServer::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData)
+{
+    send(Messages::WebIDBConnectionToClient::GetAllRecords(requestData, getAllRecordsData));
+}
+
 void WebIDBConnectionToServer::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& range)
 {
     send(Messages::WebIDBConnectionToClient::GetCount(requestData, range));
@@ -272,12 +277,12 @@ void WebIDBConnectionToServer::didPutOrAdd(const IDBResultData& result)
 static void preregisterSandboxExtensionsIfNecessary(const WebIDBResult& result)
 {
     auto resultType = result.resultData().type();
-    if (resultType != IDBResultType::GetRecordSuccess && resultType != IDBResultType::OpenCursorSuccess && resultType != IDBResultType::IterateCursorSuccess) {
+    if (resultType != IDBResultType::GetRecordSuccess && resultType != IDBResultType::OpenCursorSuccess && resultType != IDBResultType::IterateCursorSuccess && resultType != IDBResultType::GetAllRecordsSuccess) {
         ASSERT(resultType == IDBResultType::Error);
         return;
     }
 
-    const auto& filePaths = result.resultData().getResult().value().blobFilePaths();
+    const auto filePaths = resultType == IDBResultType::GetAllRecordsSuccess ? result.resultData().getAllResult().allBlobFilePaths() : result.resultData().getResult().value().blobFilePaths();
 
 #if ENABLE(SANDBOX_EXTENSIONS)
     ASSERT(filePaths.size() == result.handles().size());
@@ -293,6 +298,13 @@ void WebIDBConnectionToServer::didGetRecord(const WebIDBResult& result)
     m_connectionToServer->didGetRecord(result.resultData());
 }
 
+void WebIDBConnectionToServer::didGetAllRecords(const WebIDBResult& result)
+{
+    if (result.resultData().getAllResult().type() == IndexedDB::GetAllType::Values)
+        preregisterSandboxExtensionsIfNecessary(result);
+    m_connectionToServer->didGetAllRecords(result.resultData());
+}
+
 void WebIDBConnectionToServer::didGetCount(const IDBResultData& result)
 {
     m_connectionToServer->didGetCount(result);
index 08e82b6..8b17831 100644 (file)
@@ -60,6 +60,7 @@ public:
     void renameIndex(const WebCore::IDBRequestData&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName) final;
     void putOrAdd(const WebCore::IDBRequestData&, const WebCore::IDBKeyData&, const WebCore::IDBValue&, const WebCore::IndexedDB::ObjectStoreOverwriteMode) final;
     void getRecord(const WebCore::IDBRequestData&, const WebCore::IDBGetRecordData&) final;
+    void getAllRecords(const WebCore::IDBRequestData&, const WebCore::IDBGetAllRecordsData&) final;
     void getCount(const WebCore::IDBRequestData&, const WebCore::IDBKeyRangeData&) final;
     void deleteRecord(const WebCore::IDBRequestData&, const WebCore::IDBKeyRangeData&) final;
     void openCursor(const WebCore::IDBRequestData&, const WebCore::IDBCursorInfo&) final;
@@ -90,6 +91,7 @@ public:
     void didRenameIndex(const WebCore::IDBResultData&);
     void didPutOrAdd(const WebCore::IDBResultData&);
     void didGetRecord(const WebIDBResult&);
+    void didGetAllRecords(const WebIDBResult&);
     void didGetCount(const WebCore::IDBResultData&);
     void didDeleteRecord(const WebCore::IDBResultData&);
     void didOpenCursor(const WebIDBResult&);
index 39800d1..b701074 100644 (file)
@@ -36,6 +36,7 @@ messages -> WebIDBConnectionToServer {
     DidRenameIndex(WebCore::IDBResultData result)
     DidPutOrAdd(WebCore::IDBResultData result)
     DidGetRecord(WebKit::WebIDBResult result)
+    DidGetAllRecords(WebKit::WebIDBResult result)
     DidGetCount(WebCore::IDBResultData result)
     DidDeleteRecord(WebCore::IDBResultData result)
     DidOpenCursor(WebKit::WebIDBResult result)