IDB: "Put" support
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Jan 2014 23:48:27 +0000 (23:48 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Jan 2014 23:48:27 +0000 (23:48 +0000)
<rdar://problem/15779643> and https://bugs.webkit.org/show_bug.cgi?id=127401

Reviewed by Alexey Proskuryakov.

Source/WebCore:

Add persistent encode/decode for storage to the database:
* Modules/indexeddb/IDBKey.cpp:
(WebCore::IDBKey::encode):
(WebCore::IDBKey::decode):
* Modules/indexeddb/IDBKey.h:

Add a data class to represent IDBKey suitable for crossing IPC:
* Modules/indexeddb/IDBKeyData.cpp: Added.
(WebCore::IDBKeyData::IDBKeyData):
(WebCore::IDBKeyData::maybeCreateIDBKey):
(WebCore::IDBKeyData::isolatedCopy):
* Modules/indexeddb/IDBKeyData.h: Added.
(WebCore::IDBKeyData::IDBKeyData):

* platform/CrossThreadCopier.cpp:
(WebCore::IDBKeyData>::copy):
* platform/CrossThreadCopier.h:

* WebCore.exp.in:
* WebCore.xcodeproj/project.pbxproj:

Source/WebKit2:

Ship putRecord requests over to the DatabaseProcess, and listen for completion from the DatabaseProcess:
* WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp:
(WebKit::WebIDBServerConnection::put):
(WebKit::WebIDBServerConnection::didPutRecord):
* WebProcess/Databases/IndexedDB/WebIDBServerConnection.h:
* WebProcess/Databases/IndexedDB/WebIDBServerConnection.messages.in:

Pass off the putRecord request to the Unique IDBDatabase:
* DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.cpp:
(WebKit::DatabaseProcessIDBConnection::putRecord):
* DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.h:
* DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.messages.in:

Pass off the putRecord request to the backing store:
* DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp:
(WebKit::UniqueIDBDatabase::putRecord):
(WebKit::UniqueIDBDatabase::putRecordInBackingStore):
(WebKit::UniqueIDBDatabase::didPutRecordInBackingStore):
* DatabaseProcess/IndexedDB/UniqueIDBDatabase.h:

Add backing store methods related to putRecord, though only one is critical right now:
* DatabaseProcess/IndexedDB/UniqueIDBDatabaseBackingStore.h:
* DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::createAndPopulateInitialMetadata):
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::generateKey):
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::keyExistsInObjectStore):
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::putRecord):
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::updateKeyGenerator):
* DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h:

Add the IDBKeyData type to IPC:
* Scripts/webkit2/messages.py:
(struct_or_class):

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<IDBKeyData>::encode):
(IPC::ArgumentCoder<IDBKeyData>::decode):
* Shared/WebCoreArgumentCoders.h:

* DatabaseProcess/IndexedDB/IDBSerialization.cpp:
(WebKit::serializeIDBKey):
* DatabaseProcess/IndexedDB/IDBSerialization.h:

Implement more cross-thread copying:
* Shared/WebCrossThreadCopier.cpp:
(WebCore::Vector<uint8_t>>::copy):
(WebCore::Vector<Vector<IDBKeyData>>>::copy):
(WebCore::ASCIILiteral>::copy):
* Shared/WebCrossThreadCopier.h:

Implement more numbers of generic AsyncTask templates:
* Shared/AsyncTask.h:
(WebKit::createAsyncTask):

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

33 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Modules/indexeddb/IDBKey.cpp
Source/WebCore/Modules/indexeddb/IDBKey.h
Source/WebCore/Modules/indexeddb/IDBKeyData.cpp [new file with mode: 0644]
Source/WebCore/Modules/indexeddb/IDBKeyData.h [new file with mode: 0644]
Source/WebCore/Modules/indexeddb/IDBTransactionBackendOperations.cpp
Source/WebCore/WebCore.exp.in
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/CrossThreadCopier.cpp
Source/WebCore/platform/CrossThreadCopier.h
Source/WebKit2/ChangeLog
Source/WebKit2/DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.h
Source/WebKit2/DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.messages.in
Source/WebKit2/DatabaseProcess/IndexedDB/IDBSerialization.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/IDBSerialization.h
Source/WebKit2/DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/UniqueIDBDatabase.h
Source/WebKit2/DatabaseProcess/IndexedDB/UniqueIDBDatabaseBackingStore.h
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h
Source/WebKit2/Scripts/webkit2/messages.py
Source/WebKit2/Shared/AsyncTask.h
Source/WebKit2/Shared/WebCoreArgumentCoders.cpp
Source/WebKit2/Shared/WebCoreArgumentCoders.h
Source/WebKit2/Shared/WebCrossThreadCopier.cpp
Source/WebKit2/Shared/WebCrossThreadCopier.h
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBServerConnection.h
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBServerConnection.messages.in

index 1644b7c..5feb077 100644 (file)
@@ -811,6 +811,7 @@ set(WebCore_SOURCES
     Modules/indexeddb/IDBFactoryBackendInterface.cpp
     Modules/indexeddb/IDBIndex.cpp
     Modules/indexeddb/IDBKey.cpp
+    Modules/indexeddb/IDBKeyData.cpp
     Modules/indexeddb/IDBKeyPath.cpp
     Modules/indexeddb/IDBKeyRange.cpp
     Modules/indexeddb/IDBObjectStore.cpp
index 7ba4e03..cdf5b37 100644 (file)
@@ -1,3 +1,31 @@
+2014-01-21  Brady Eidson  <beidson@apple.com>
+
+        IDB: "Put" support
+        <rdar://problem/15779643> and https://bugs.webkit.org/show_bug.cgi?id=127401
+
+        Reviewed by Alexey Proskuryakov.
+
+        Add persistent encode/decode for storage to the database:
+        * Modules/indexeddb/IDBKey.cpp:
+        (WebCore::IDBKey::encode):
+        (WebCore::IDBKey::decode):
+        * Modules/indexeddb/IDBKey.h:
+
+        Add a data class to represent IDBKey suitable for crossing IPC:
+        * Modules/indexeddb/IDBKeyData.cpp: Added.
+        (WebCore::IDBKeyData::IDBKeyData):
+        (WebCore::IDBKeyData::maybeCreateIDBKey):
+        (WebCore::IDBKeyData::isolatedCopy):
+        * Modules/indexeddb/IDBKeyData.h: Added.
+        (WebCore::IDBKeyData::IDBKeyData):
+
+        * platform/CrossThreadCopier.cpp:
+        (WebCore::IDBKeyData>::copy):
+        * platform/CrossThreadCopier.h:
+
+        * WebCore.exp.in:
+        * WebCore.xcodeproj/project.pbxproj:
+
 2014-01-22  Dean Jackson  <dino@apple.com>
 
         [WebGL] Implement ANGLE_instanced_arrays
index 03a1c7a..e1b07ca 100644 (file)
@@ -25,7 +25,7 @@ webcore_built_sources += \
        DerivedSources/WebCore/InspectorWebBackendDispatchers.cpp \
        DerivedSources/WebCore/InspectorWebBackendDispatchers.h \
        DerivedSources/WebCore/InspectorWebFrontendDispatchers.cpp \
-       DerivedSources/WebCore/InspectorWebFrontendDispatchers.h \
+       DerivedSources/WebCore/InspectorWebFrontendDispatchers.h \    
        DerivedSources/WebCore/InspectorWebTypeBuilders.cpp \
        DerivedSources/WebCore/InspectorWebTypeBuilders.h \
        DerivedSources/WebCore/JSANGLEInstancedArrays.cpp \
@@ -1845,6 +1845,8 @@ webcore_modules_sources += \
        Source/WebCore/Modules/indexeddb/IDBIndex.h \
        Source/WebCore/Modules/indexeddb/IDBKey.cpp \
        Source/WebCore/Modules/indexeddb/IDBKey.h \
+       Source/WebCore/Modules/indexeddb/IDBKeyData.cpp \
+       Source/WebCore/Modules/indexeddb/IDBKeyData.h \
        Source/WebCore/Modules/indexeddb/IDBKeyPath.cpp \
        Source/WebCore/Modules/indexeddb/IDBKeyPath.h \
        Source/WebCore/Modules/indexeddb/IDBKeyRange.cpp \
index 633c835..375a1c3 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "KeyedCoding.h"
+
 namespace WebCore {
 
 IDBKey::~IDBKey()
@@ -96,6 +98,41 @@ bool IDBKey::isEqual(const IDBKey* other) const
     return !compare(other);
 }
 
+void IDBKey::encode(KeyedEncoder& encoder) const
+{
+    encoder.encodeEnum("type", m_type);
+
+    switch (m_type) {
+    case InvalidType:
+        return;
+    case ArrayType:
+        encoder.encodeObjects("array", m_array.begin(), m_array.end(), [](WebCore::KeyedEncoder& encoder, const RefPtr<IDBKey>& key) {
+            encoder.encodeObject("idbKey", *key, [](KeyedEncoder& encoder, const IDBKey& key) {
+                key.encode(encoder);
+            });
+        });
+        return;
+    case StringType:
+        encoder.encodeString("string", m_string);
+        return;
+    case DateType:
+    case NumberType:
+        encoder.encodeDouble("number", m_number);
+        return;
+    case MinType:
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+}
+
+bool IDBKey::decode(KeyedDecoder&, IDBKey&)
+{
+    // FIXME: Implement when IDB Get support is implemented (<rdar://problem/15779644>)
+    return false;
+}
+
 } // namespace WebCore
 
 #endif
index 90b62d5..6176d09 100644 (file)
@@ -35,6 +35,9 @@
 
 namespace WebCore {
 
+class KeyedDecoder;
+class KeyedEncoder;
+
 class IDBKey : public RefCounted<IDBKey> {
 public:
     typedef Vector<RefPtr<IDBKey>> KeyArray;
@@ -147,6 +150,9 @@ public:
     using RefCounted<IDBKey>::ref;
     using RefCounted<IDBKey>::deref;
 
+    void encode(KeyedEncoder&) const;
+    static bool decode(KeyedDecoder&, IDBKey&);
+
 private:
     IDBKey() : m_type(InvalidType), m_number(0), m_sizeEstimate(OverheadSize) { }
     IDBKey(Type type, double number) : m_type(type), m_number(number), m_sizeEstimate(OverheadSize + sizeof(double)) { }
diff --git a/Source/WebCore/Modules/indexeddb/IDBKeyData.cpp b/Source/WebCore/Modules/indexeddb/IDBKeyData.cpp
new file mode 100644 (file)
index 0000000..1fc82cd
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2014 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 "IDBKeyData.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+namespace WebCore {
+
+IDBKeyData::IDBKeyData(IDBKey* key)
+    : type(IDBKey::InvalidType)
+    , numberValue(0)
+    , isNull(false)
+{
+    if (!key) {
+        isNull = true;
+        return;
+    }
+
+    type = key->type();
+    numberValue = 0;
+
+    switch (type) {
+    case IDBKey::InvalidType:
+        break;
+    case IDBKey::ArrayType:
+        for (auto key2 : key->array())
+            arrayValue.append(IDBKeyData(key2.get()));
+        break;
+    case IDBKey::StringType:
+        stringValue = key->string();
+        break;
+    case IDBKey::DateType:
+        numberValue = key->date();
+        break;
+    case IDBKey::NumberType:
+        numberValue = key->number();
+        break;
+    case IDBKey::MinType:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+PassRefPtr<IDBKey> IDBKeyData::maybeCreateIDBKey() const
+{
+    if (isNull)
+        return nullptr;
+
+    switch (type) {
+    case IDBKey::InvalidType:
+        return IDBKey::createInvalid();
+    case IDBKey::ArrayType:
+        {
+            IDBKey::KeyArray array;
+            for (auto keyData : arrayValue) {
+                array.append(keyData.maybeCreateIDBKey());
+                ASSERT(array.last());
+            }
+            return IDBKey::createArray(array);
+        }
+    case IDBKey::StringType:
+        return IDBKey::createString(stringValue);
+    case IDBKey::DateType:
+        return IDBKey::createDate(numberValue);
+    case IDBKey::NumberType:
+        return IDBKey::createNumber(numberValue);
+    case IDBKey::MinType:
+        ASSERT_NOT_REACHED();
+        return nullptr;
+    }
+
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+IDBKeyData IDBKeyData::isolatedCopy() const
+{
+    IDBKeyData result;
+    result.type = type;
+    result.isNull = isNull;
+
+    switch (type) {
+    case IDBKey::InvalidType:
+        return result;
+    case IDBKey::ArrayType:
+        for (auto key : arrayValue)
+            result.arrayValue.append(key.isolatedCopy());
+        return result;
+    case IDBKey::StringType:
+        result.stringValue = stringValue.isolatedCopy();
+        return result;
+    case IDBKey::DateType:
+    case IDBKey::NumberType:
+        result.numberValue = numberValue;
+        return result;
+    case IDBKey::MinType:
+        ASSERT_NOT_REACHED();
+        return result;
+    }
+
+    ASSERT_NOT_REACHED();
+    return result;
+}
+
+}
+
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/Modules/indexeddb/IDBKeyData.h b/Source/WebCore/Modules/indexeddb/IDBKeyData.h
new file mode 100644 (file)
index 0000000..4639e62
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IDBKeyData_h
+#define IDBKeyData_h
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBKey.h"
+
+namespace WebCore {
+
+struct IDBKeyData {
+    IDBKeyData()
+        : type(IDBKey::InvalidType)
+        , numberValue(0)
+        , isNull(true)
+    {
+    }
+
+    IDBKeyData(IDBKey*);
+
+    PassRefPtr<IDBKey> maybeCreateIDBKey() const;
+
+    IDBKeyData isolatedCopy() const;
+
+    IDBKey::Type type;
+    Vector<IDBKeyData> arrayValue;
+    String stringValue;
+    double numberValue;
+    bool isNull;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
+#endif // IDBKeyData_h
index 9dc5a24..8b8bacd 100644 (file)
@@ -106,7 +106,8 @@ void PutOperation::perform(std::function<void()> completionCallback)
     RefPtr<PutOperation> operation(this);
     STANDARD_DATABASE_ERROR_CALLBACK;
 
-    m_transaction->database().serverConnection().put(*m_transaction, *this, [this, operation, operationCallback](PassRefPtr<IDBKey> key, PassRefPtr<IDBDatabaseError> error) {
+    m_transaction->database().serverConnection().put(*m_transaction, *this, [this, operation, operationCallback](PassRefPtr<IDBKey> key, PassRefPtr<IDBDatabaseError> prpError) {
+        RefPtr<IDBDatabaseError> error = prpError;
         if (key) {
             ASSERT(!error);
             m_callbacks->onSuccess(key);
@@ -114,6 +115,7 @@ void PutOperation::perform(std::function<void()> completionCallback)
             ASSERT(error);
             m_callbacks->onError(error);
         }
+        operationCallback(error.release());
     });
 }
 
index 8ba638e..884fd2f 100644 (file)
@@ -3077,13 +3077,19 @@ __ZN7WebCore26MockMediaPlayerMediaSource19registerMediaEngineEPFvPFN3WTF10PassOw
 #endif
 
 #if ENABLE(INDEXED_DATABASE)
+__ZNK7WebCore10IDBKeyData17maybeCreateIDBKeyEv
 __ZNK7WebCore10IDBKeyPath6encodeERNS_12KeyedEncoderE
+__ZNK7WebCore6IDBKey6encodeERNS_12KeyedEncoderE
+__ZNK7WebCore6IDBKey7isValidEv
+__ZN7WebCore10IDBKeyDataC1EPNS_6IDBKeyE
 __ZN7WebCore10IDBKeyPathC1ERKN3WTF6StringE
 __ZN7WebCore10IDBKeyPathC1ERKN3WTF6VectorINS1_6StringELm0ENS1_15CrashOnOverflowEEE
 __ZN7WebCore10IDBKeyPath6decodeERNS_12KeyedDecoderERS0_
 __ZN7WebCore18IDBDatabaseBackend14openConnectionEN3WTF10PassRefPtrINS_12IDBCallbacksEEENS2_INS_20IDBDatabaseCallbacksEEExy
 __ZN7WebCore18IDBDatabaseBackend6createERKN3WTF6StringES4_PNS_26IDBFactoryBackendInterfaceERNS_19IDBServerConnectionE
 __ZN7WebCore18IDBDatabaseBackendD1Ev
+__ZN7WebCore21CrossThreadCopierBaseILb0ELb0ENS_10IDBKeyDataEE4copyERKS1_
 __ZN7WebCore21CrossThreadCopierBaseILb0ELb0ENS_22IDBObjectStoreMetadataEE4copyERKS1_
 __ZN7WebCore21CrossThreadCopierBaseILb0ELb0ENS_9IndexedDB15TransactionModeEE4copyERKS2_
+__ZN7WebCore6IDBKeyD1Ev
 #endif
index a5b4b9d..1d07fe5 100644 (file)
     <ClCompile Include="..\Modules\indexeddb\IDBFactoryBackendInterface.cpp" />
     <ClCompile Include="..\Modules\indexeddb\IDBIndex.cpp" />
     <ClCompile Include="..\Modules\indexeddb\IDBKey.cpp" />
+    <ClCompile Include="..\Modules\indexeddb\IDBKeyData.cpp" />
     <ClCompile Include="..\Modules\indexeddb\IDBKeyRange.cpp" />
     <ClCompile Include="..\Modules\indexeddb\IDBObjectStore.cpp" />
     <ClCompile Include="..\Modules\indexeddb\IDBRequest.cpp" />
index d8b28a7..2cd9dca 100644 (file)
                510D4A38103165EE0049EA54 /* SocketStreamHandleClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 510D4A32103165EE0049EA54 /* SocketStreamHandleClient.h */; };
                5112935F3D54B4B52FAF973F /* InspectorHeapProfilerAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 511293613D6DB4B52FAF973F /* InspectorHeapProfilerAgent.cpp */; };
                511293603D60B4B52FAF973F /* InspectorHeapProfilerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 511293623D85B4B52FAF973F /* InspectorHeapProfilerAgent.h */; };
+               511EC1A6188DACA400BA3EB6 /* IDBKeyData.h in Headers */ = {isa = PBXBuildFile; fileRef = 511EC1A5188DACA400BA3EB6 /* IDBKeyData.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               511EC1A8188DAE7B00BA3EB6 /* IDBKeyData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 511EC1A7188DAE7B00BA3EB6 /* IDBKeyData.cpp */; };
                511EF2C017F0FD3500E4FA16 /* JSIDBAny.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 511EF2A817F0FC4800E4FA16 /* JSIDBAny.cpp */; };
                511EF2C117F0FD3500E4FA16 /* JSIDBCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 511EF2A917F0FC4800E4FA16 /* JSIDBCursor.cpp */; };
                511EF2C217F0FD3500E4FA16 /* JSIDBCursorWithValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 511EF2AA17F0FC4800E4FA16 /* JSIDBCursorWithValue.cpp */; };
                510D4A32103165EE0049EA54 /* SocketStreamHandleClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketStreamHandleClient.h; sourceTree = "<group>"; };
                511293613D6DB4B52FAF973F /* InspectorHeapProfilerAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorHeapProfilerAgent.cpp; sourceTree = "<group>"; };
                511293623D85B4B52FAF973F /* InspectorHeapProfilerAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorHeapProfilerAgent.h; sourceTree = "<group>"; };
+               511EC1A5188DACA400BA3EB6 /* IDBKeyData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBKeyData.h; sourceTree = "<group>"; };
+               511EC1A7188DAE7B00BA3EB6 /* IDBKeyData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBKeyData.cpp; sourceTree = "<group>"; };
                511EF2A817F0FC4800E4FA16 /* JSIDBAny.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSIDBAny.cpp; sourceTree = "<group>"; };
                511EF2A917F0FC4800E4FA16 /* JSIDBCursor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSIDBCursor.cpp; sourceTree = "<group>"; };
                511EF2AA17F0FC4800E4FA16 /* JSIDBCursorWithValue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSIDBCursorWithValue.cpp; sourceTree = "<group>"; };
                                51ABB5B6186D0ED1008391A1 /* IDBIndexMetadata.h */,
                                51D71991181106E00016DC51 /* IDBKey.cpp */,
                                51D71992181106E00016DC51 /* IDBKey.h */,
+                               511EC1A7188DAE7B00BA3EB6 /* IDBKeyData.cpp */,
+                               511EC1A5188DACA400BA3EB6 /* IDBKeyData.h */,
                                51D71993181106E00016DC51 /* IDBKeyPath.cpp */,
                                51D71994181106E00016DC51 /* IDBKeyPath.h */,
                                51D71995181106E00016DC51 /* IDBKeyRange.cpp */,
                                CD8B5A49180E138B008B8E65 /* TextTrackMediaSource.h in Headers */,
                                A8EA7CAF0A192B9C00A8EF5F /* HTMLHRElement.h in Headers */,
                                A871DE270A152AC800B12A68 /* HTMLHtmlElement.h in Headers */,
+                               511EC1A6188DACA400BA3EB6 /* IDBKeyData.h in Headers */,
                                07969DB417D14151007FF842 /* JSRTCPeerConnectionErrorCallback.h in Headers */,
                                A871DE2A0A152AC800B12A68 /* HTMLIFrameElement.h in Headers */,
                                A8EA7D2D0A19385500A8EF5F /* HTMLImageElement.h in Headers */,
                                51771C8E182DB4B7008E781E /* IDBDatabaseBackend.cpp in Sources */,
                                1A22464B0CC98DDB00C05240 /* SQLiteStatement.cpp in Sources */,
                                1A22464D0CC98DDB00C05240 /* SQLiteTransaction.cpp in Sources */,
+                               511EC1A8188DAE7B00BA3EB6 /* IDBKeyData.cpp in Sources */,
                                97BC6A411505F081001B74AC /* SQLResultSet.cpp in Sources */,
                                97BC6A441505F081001B74AC /* SQLResultSetRowList.cpp in Sources */,
                                97BC6A471505F081001B74AC /* SQLStatement.cpp in Sources */,
index 0aaea79..b0e3a27 100644 (file)
@@ -42,6 +42,7 @@
 
 #if ENABLE(INDEXED_DATABASE)
 #include "IDBDatabaseMetadata.h"
+#include "IDBKeyData.h"
 #endif
 
 namespace WebCore {
@@ -98,6 +99,11 @@ CrossThreadCopierBase<false, false, IDBIndexMetadata>::Type CrossThreadCopierBas
     return metadata.isolatedCopy();
 }
 
+CrossThreadCopierBase<false, false, IDBKeyData>::Type CrossThreadCopierBase<false, false, IDBKeyData>::copy(const IDBKeyData& keyData)
+{
+    return keyData.isolatedCopy();
+}
+
 CrossThreadCopierBase<false, false, IDBObjectStoreMetadata>::Type CrossThreadCopierBase<false, false, IDBObjectStoreMetadata>::copy(const IDBObjectStoreMetadata& metadata)
 {
     return metadata.isolatedCopy();
index 59d0ac2..032a27c 100644 (file)
@@ -173,6 +173,12 @@ namespace WebCore {
         static Type copy(const IDBIndexMetadata&);
     };
 
+    struct IDBKeyData;
+    template<> struct CrossThreadCopierBase<false, false, IDBKeyData> {
+        typedef IDBKeyData Type;
+        static Type copy(const IDBKeyData&);
+    };
+
     struct IDBObjectStoreMetadata;
     template<> struct CrossThreadCopierBase<false, false, IDBObjectStoreMetadata> {
         typedef IDBObjectStoreMetadata Type;
index 6908c17..211032b 100644 (file)
@@ -1,3 +1,64 @@
+2014-01-21  Brady Eidson  <beidson@apple.com>
+
+        IDB: "Put" support
+        <rdar://problem/15779643> and https://bugs.webkit.org/show_bug.cgi?id=127401
+
+        Reviewed by Alexey Proskuryakov.
+
+        Ship putRecord requests over to the DatabaseProcess, and listen for completion from the DatabaseProcess:
+        * WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp:
+        (WebKit::WebIDBServerConnection::put):
+        (WebKit::WebIDBServerConnection::didPutRecord):
+        * WebProcess/Databases/IndexedDB/WebIDBServerConnection.h:
+        * WebProcess/Databases/IndexedDB/WebIDBServerConnection.messages.in:
+
+        Pass off the putRecord request to the Unique IDBDatabase:
+        * DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.cpp:
+        (WebKit::DatabaseProcessIDBConnection::putRecord):
+        * DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.h:
+        * DatabaseProcess/IndexedDB/DatabaseProcessIDBConnection.messages.in:
+
+        Pass off the putRecord request to the backing store:
+        * DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp:
+        (WebKit::UniqueIDBDatabase::putRecord):
+        (WebKit::UniqueIDBDatabase::putRecordInBackingStore):
+        (WebKit::UniqueIDBDatabase::didPutRecordInBackingStore):
+        * DatabaseProcess/IndexedDB/UniqueIDBDatabase.h:
+
+        Add backing store methods related to putRecord, though only one is critical right now:
+        * DatabaseProcess/IndexedDB/UniqueIDBDatabaseBackingStore.h:
+        * DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::createAndPopulateInitialMetadata):
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::generateKey):
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::keyExistsInObjectStore):
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::putRecord):
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::updateKeyGenerator):
+        * DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h:
+
+        Add the IDBKeyData type to IPC:
+        * Scripts/webkit2/messages.py:
+        (struct_or_class):
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<IDBKeyData>::encode):
+        (IPC::ArgumentCoder<IDBKeyData>::decode):
+        * Shared/WebCoreArgumentCoders.h:
+
+        * DatabaseProcess/IndexedDB/IDBSerialization.cpp:
+        (WebKit::serializeIDBKey):
+        * DatabaseProcess/IndexedDB/IDBSerialization.h:
+
+        Implement more cross-thread copying:
+        * Shared/WebCrossThreadCopier.cpp:
+        (WebCore::Vector<uint8_t>>::copy):
+        (WebCore::Vector<Vector<IDBKeyData>>>::copy):
+        (WebCore::ASCIILiteral>::copy):
+        * Shared/WebCrossThreadCopier.h:
+
+        Implement more numbers of generic AsyncTask templates:
+        * Shared/AsyncTask.h:
+        (WebKit::createAsyncTask):
+
 2014-01-22  Anders Carlsson  <andersca@apple.com>
 
         WKProcessClass should create a WebContext
index 5196d48..5f80731 100644 (file)
@@ -177,6 +177,18 @@ void DatabaseProcessIDBConnection::deleteObjectStore(uint64_t requestID, int64_t
     });
 }
 
+void DatabaseProcessIDBConnection::putRecord(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, const WebCore::IDBKeyData& key, const IPC::DataReference& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<WebCore::IDBKeyData>>& indexKeys)
+{
+    ASSERT(m_uniqueIDBDatabase);
+
+    LOG(IDB, "DatabaseProcess putRecord request ID %llu, object store id %lli", requestID, objectStoreID);
+    RefPtr<DatabaseProcessIDBConnection> connection(this);
+    m_uniqueIDBDatabase->putRecord(IDBTransactionIdentifier(*this, transactionID), objectStoreID, key, value, putMode, indexIDs, indexKeys, [connection, requestID](const IDBKeyData& keyData, uint32_t errorCode, const String& errorMessage) {
+        connection->send(Messages::WebIDBServerConnection::DidPutRecord(requestID, keyData, errorCode, errorMessage));
+    });
+}
+
+
 IPC::Connection* DatabaseProcessIDBConnection::messageSenderConnection()
 {
     return m_connection->connection();
index 4d6fa53..ac21921 100644 (file)
 #include "UniqueIDBDatabaseIdentifier.h"
 #include <wtf/text/WTFString.h>
 
+namespace WebCore {
+struct IDBKeyData;
+}
+
 namespace WebKit {
 
 class DatabaseToWebProcessConnection;
@@ -71,6 +75,7 @@ private:
     void changeDatabaseVersion(uint64_t requestID, int64_t transactionID, uint64_t newVersion);
     void createObjectStore(uint64_t requestID, int64_t transactionID, WebCore::IDBObjectStoreMetadata);
     void deleteObjectStore(uint64_t requestID, int64_t transactionID, int64_t objectStoreID);
+    void putRecord(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, const WebCore::IDBKeyData&, const IPC::DataReference& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<WebCore::IDBKeyData>>& indexKeys);
 
     Ref<DatabaseToWebProcessConnection> m_connection;
     uint64_t m_serverConnectionIdentifier;
index d3d6584..a938411 100644 (file)
@@ -35,6 +35,7 @@ messages -> DatabaseProcessIDBConnection LegacyReceiver {
     ChangeDatabaseVersion(uint64_t requestID, int64_t transactionID, uint64_t newVersion)
     CreateObjectStore(uint64_t requestID, int64_t transactionID, WebCore::IDBObjectStoreMetadata objectStoreMetadata)
     DeleteObjectStore(uint64_t requestID, int64_t transactionID, int64_t objectStoreID)
+    PutRecord(uint64_t requestID, int64_t transactionID, int64_t objectStoreID, WebCore::IDBKeyData key, IPC::DataReference value, int64_t putMode, Vector<int64_t> indexIDs, Vector<Vector<WebCore::IDBKeyData>> indexKeys)
 }
 
 #endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
index 620a186..1af7208 100644 (file)
 #include "ArgumentEncoder.h"
 #include "KeyedDecoder.h"
 #include "KeyedEncoder.h"
+#include <WebCore/IDBKey.h>
 #include <WebCore/IDBKeyPath.h>
 
 using namespace WebCore;
 
 namespace WebKit {
 
-RefPtr<SharedBuffer> serializeIDBKeyPath(const WebCore::IDBKeyPath& keyPath)
+RefPtr<SharedBuffer> serializeIDBKeyPath(const IDBKeyPath& keyPath)
 {
     KeyedEncoder encoder;
     keyPath.encode(encoder);
@@ -53,6 +54,13 @@ std::unique_ptr<WebCore::IDBKeyPath> deserializeIDBKeyPath(const uint8_t* data,
     return result;
 }
 
+RefPtr<WebCore::SharedBuffer> serializeIDBKey(const IDBKey& key)
+{
+    KeyedEncoder encoder;
+    key.encode(encoder);
+    return encoder.finishEncoding();
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(INDEXED_DATABASE)
index a6c73df..55ba17e 100644 (file)
@@ -32,6 +32,7 @@
 #include <wtf/Vector.h>
 
 namespace WebCore {
+class IDBKey;
 class IDBKeyPath;
 }
 
@@ -40,6 +41,9 @@ namespace WebKit {
 RefPtr<WebCore::SharedBuffer> serializeIDBKeyPath(const WebCore::IDBKeyPath&);
 std::unique_ptr<WebCore::IDBKeyPath> deserializeIDBKeyPath(const uint8_t* buffer, size_t bufferSize);
 
+RefPtr<WebCore::SharedBuffer> serializeIDBKey(const WebCore::IDBKey&);
+PassRefPtr<WebCore::IDBKey> deserializeIDBKey(const uint8_t* buffer, size_t bufferSize);
+
 } // namespace WebKit
 
 #endif // ENABLE(INDEXED_DATABASE)
index 7778112..83022a0 100644 (file)
 
 #include "AsyncRequest.h"
 #include "AsyncTask.h"
+#include "DataReference.h"
 #include "DatabaseProcess.h"
 #include "DatabaseProcessIDBConnection.h"
 #include "UniqueIDBDatabaseBackingStoreSQLite.h"
 #include "WebCrossThreadCopier.h"
 #include <WebCore/FileSystem.h>
+#include <WebCore/IDBDatabaseBackend.h>
 #include <WebCore/IDBDatabaseMetadata.h>
+#include <WebCore/IDBKeyData.h>
 #include <wtf/MainThread.h>
+#include <wtf/text/WTFString.h>
 
 using namespace WebCore;
 
@@ -222,7 +226,7 @@ void UniqueIDBDatabase::didOpenBackingStoreAndReadMetadata(const IDBDatabaseMeta
     }
 }
 
-void UniqueIDBDatabase::openTransaction(const IDBTransactionIdentifier& identifier, const Vector<int64_t>& objectStoreIDs, WebCore::IndexedDB::TransactionMode mode, std::function<void(bool)> successCallback)
+void UniqueIDBDatabase::openTransaction(const IDBTransactionIdentifier& identifier, const Vector<int64_t>& objectStoreIDs, IndexedDB::TransactionMode mode, std::function<void(bool)> successCallback)
 {
     postTransactionOperation(identifier, createAsyncTask(*this, &UniqueIDBDatabase::openBackingStoreTransaction, identifier, objectStoreIDs, mode), successCallback);
 }
@@ -334,7 +338,7 @@ void UniqueIDBDatabase::didCompleteBoolRequest(uint64_t requestID, bool success)
     request->completeRequest(success);
 }
 
-void UniqueIDBDatabase::createObjectStore(const IDBTransactionIdentifier& identifier, const WebCore::IDBObjectStoreMetadata& metadata, std::function<void(bool)> successCallback)
+void UniqueIDBDatabase::createObjectStore(const IDBTransactionIdentifier& identifier, const IDBObjectStoreMetadata& metadata, std::function<void(bool)> successCallback)
 {
     ASSERT(isMainThread());
 
@@ -389,7 +393,30 @@ void UniqueIDBDatabase::deleteObjectStore(const IDBTransactionIdentifier& identi
     postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::deleteObjectStoreInBackingStore, requestID, identifier, objectStoreID));
 }
 
-void UniqueIDBDatabase::openBackingStoreTransaction(const IDBTransactionIdentifier& identifier, const Vector<int64_t>& objectStoreIDs, WebCore::IndexedDB::TransactionMode mode)
+void UniqueIDBDatabase::putRecord(const IDBTransactionIdentifier& identifier, int64_t objectStoreID, const IDBKeyData& keyData, const IPC::DataReference& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<IDBKeyData>>& indexKeys, std::function<void(const IDBKeyData&, uint32_t, const String&)> callback)
+{
+    ASSERT(isMainThread());
+
+    if (!m_acceptingNewRequests) {
+        callback(IDBKeyData(), INVALID_STATE_ERR, "Unable to put record into database because it has shut down");
+        return;
+    }
+
+    ASSERT(m_metadata->objectStores.contains(objectStoreID));
+
+    RefPtr<AsyncRequest> request = AsyncRequestImpl<const IDBKeyData&, uint32_t, const String&>::create([this, callback](const IDBKeyData& keyData, uint32_t errorCode, const String& errorMessage) {
+        callback(keyData, errorCode, errorMessage);
+    }, [this, callback]() {
+        callback(IDBKeyData(), INVALID_STATE_ERR, "Unable to put record into database");
+    });
+
+    uint64_t requestID = request->requestID();
+    m_pendingDatabaseTasks.add(requestID, request.release());
+
+    postDatabaseTask(createAsyncTask(*this, &UniqueIDBDatabase::putRecordInBackingStore, requestID, identifier, m_metadata->objectStores.get(objectStoreID), keyData, value.vector(), putMode, indexIDs, indexKeys));
+}
+
+void UniqueIDBDatabase::openBackingStoreTransaction(const IDBTransactionIdentifier& identifier, const Vector<int64_t>& objectStoreIDs, IndexedDB::TransactionMode mode)
 {
     ASSERT(!isMainThread());
     ASSERT(m_backingStore);
@@ -469,6 +496,62 @@ void UniqueIDBDatabase::deleteObjectStoreInBackingStore(uint64_t requestID, cons
     postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didDeleteObjectStore, requestID, success));
 }
 
+void UniqueIDBDatabase::putRecordInBackingStore(uint64_t requestID, const IDBTransactionIdentifier& transaction, const IDBObjectStoreMetadata& objectStoreMetadata, const IDBKeyData& keyData, const Vector<uint8_t>& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<IDBKeyData>>& indexKeys)
+{
+    ASSERT(!isMainThread());
+    ASSERT(m_backingStore);
+
+    bool keyWasGenerated = false;
+    RefPtr<IDBKey> key;
+
+    if (putMode != IDBDatabaseBackend::CursorUpdate && objectStoreMetadata.autoIncrement && keyData.isNull) {
+        key = m_backingStore->generateKey(transaction, objectStoreMetadata.id);
+        keyWasGenerated = true;
+    } else
+        key = keyData.maybeCreateIDBKey();
+
+    ASSERT(key);
+    ASSERT(key->isValid());
+
+    if (putMode == IDBDatabaseBackend::AddOnly) {
+        bool keyExists;
+        if (!m_backingStore->keyExistsInObjectStore(transaction, objectStoreMetadata.id, *key, keyExists)) {
+            postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::UnknownError, ASCIILiteral("Internal backing store error checking for key existence")));
+            return;
+        }
+        if (keyExists) {
+            postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::ConstraintError, ASCIILiteral("Key already exists in the object store")));
+            return;
+        }
+    }
+
+    // FIXME: The LevelDB port performs "makeIndexWriters" here. Necessary?
+
+    if (!m_backingStore->putRecord(transaction, objectStoreMetadata.id, *key, value.data(), value.size())) {
+        postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::UnknownError, ASCIILiteral("Internal backing store error putting a record")));
+        return;
+    }
+
+    // FIXME: The LevelDB port updates index keys here. Necessary?
+
+    if (putMode != IDBDatabaseBackend::CursorUpdate && objectStoreMetadata.autoIncrement && key->type() == IDBKey::NumberType) {
+        if (!m_backingStore->updateKeyGenerator(transaction, objectStoreMetadata.id, *key, keyWasGenerated)) {
+            postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(), IDBDatabaseException::UnknownError, ASCIILiteral("Internal backing store error updating key generator")));
+            return;
+        }
+    }
+
+    postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didPutRecordInBackingStore, requestID, IDBKeyData(key.get()), 0, String(StringImpl::empty())));
+}
+
+void UniqueIDBDatabase::didPutRecordInBackingStore(uint64_t requestID, const IDBKeyData& keyData, uint32_t errorCode, const String& errorMessage)
+{
+    RefPtr<AsyncRequest> request = m_pendingDatabaseTasks.take(requestID);
+    ASSERT(request);
+
+    request->completeRequest(keyData, errorCode, errorMessage);
+}
+
 String UniqueIDBDatabase::absoluteDatabaseDirectory() const
 {
     ASSERT(isMainThread());
index bedcd58..ba9b55b 100644 (file)
@@ -40,6 +40,7 @@
 
 namespace WebCore {
 struct IDBDatabaseMetadata;
+struct IDBKeyData;
 }
 
 namespace WebKit {
@@ -76,6 +77,7 @@ public:
     void changeDatabaseVersion(const IDBTransactionIdentifier&, uint64_t newVersion, std::function<void(bool)> successCallback);
     void createObjectStore(const IDBTransactionIdentifier&, const WebCore::IDBObjectStoreMetadata&, std::function<void(bool)> successCallback);
     void deleteObjectStore(const IDBTransactionIdentifier&, int64_t objectStoreID, std::function<void(bool)> successCallback);
+    void putRecord(const IDBTransactionIdentifier&, int64_t objectStoreID, const WebCore::IDBKeyData&, const IPC::DataReference& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<WebCore::IDBKeyData>>& indexKeys, std::function<void(const WebCore::IDBKeyData&, uint32_t, const String&)> callback);
 
 private:
     UniqueIDBDatabase(const UniqueIDBDatabaseIdentifier&);
@@ -117,6 +119,8 @@ private:
     void changeDatabaseVersionInBackingStore(uint64_t requestID, const IDBTransactionIdentifier&, uint64_t newVersion);
     void createObjectStoreInBackingStore(uint64_t requestID, const IDBTransactionIdentifier&, const WebCore::IDBObjectStoreMetadata&);
     void deleteObjectStoreInBackingStore(uint64_t requestID, const IDBTransactionIdentifier&, int64_t objectStoreID);
+    void putRecordInBackingStore(uint64_t requestID, const IDBTransactionIdentifier&, const WebCore::IDBObjectStoreMetadata&, const WebCore::IDBKeyData&, const Vector<uint8_t>& value, int64_t putMode, const Vector<int64_t>& indexIDs, const Vector<Vector<WebCore::IDBKeyData>>& indexKeys);
+
 
     void shutdownBackingStore();
 
@@ -127,6 +131,7 @@ private:
     void didChangeDatabaseVersion(uint64_t requestID, bool success);
     void didCreateObjectStore(uint64_t requestID, bool success);
     void didDeleteObjectStore(uint64_t requestID, bool success);
+    void didPutRecordInBackingStore(uint64_t requestID, const WebCore::IDBKeyData&, uint32_t errorCode, const String& errorMessage);
     void didShutdownBackingStore();
     void didCompleteBoolRequest(uint64_t requestID, bool success);
 
index abf183d..8daed71 100644 (file)
@@ -32,6 +32,8 @@
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
+class IDBKey;
+
 struct IDBDatabaseMetadata;
 struct IDBObjectStoreMetadata;
 }
@@ -55,6 +57,13 @@ public:
     virtual bool changeDatabaseVersion(const IDBTransactionIdentifier&, uint64_t newVersion) = 0;
     virtual bool createObjectStore(const IDBTransactionIdentifier&, const WebCore::IDBObjectStoreMetadata&) = 0;
     virtual bool deleteObjectStore(const IDBTransactionIdentifier&, int64_t objectStoreID) = 0;
+
+    virtual PassRefPtr<WebCore::IDBKey> generateKey(const IDBTransactionIdentifier&, int64_t objectStoreID) = 0;
+    virtual bool keyExistsInObjectStore(const IDBTransactionIdentifier&, int64_t objectStoreID, const WebCore::IDBKey&, bool& keyExists) = 0;
+    virtual bool putRecord(const IDBTransactionIdentifier&, int64_t objectStoreID, const WebCore::IDBKey&, const uint8_t* valueBuffer, size_t valueSize) = 0;
+    virtual bool updateKeyGenerator(const IDBTransactionIdentifier&, int64_t objectStoreId, const WebCore::IDBKey&, bool checkCurrent) = 0;
+
+
 };
 
 } // namespace WebKit
index 9dc82b6..7a2f91a 100644 (file)
@@ -33,6 +33,7 @@
 #include "SQLiteIDBTransaction.h"
 #include <WebCore/FileSystem.h>
 #include <WebCore/IDBDatabaseMetadata.h>
+#include <WebCore/IDBKeyData.h>
 #include <WebCore/SQLiteDatabase.h>
 #include <WebCore/SQLiteStatement.h>
 #include <wtf/MainThread.h>
@@ -89,6 +90,12 @@ std::unique_ptr<WebCore::IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLit
         return nullptr;
     }
 
+    if (!m_sqliteDB->executeCommand("CREATE TABLE Records (objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key BLOB NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, value BLOB NOT NULL ON CONFLICT FAIL);")) {
+        LOG_ERROR("Could not create Records table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+        m_sqliteDB = nullptr;
+        return nullptr;
+    }
+
     {
         SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO IDBDatabaseInfo VALUES ('MetadataVersion', ?);"));
         if (sql.prepare() != SQLResultOk
@@ -415,6 +422,60 @@ bool UniqueIDBDatabaseBackingStoreSQLite::deleteObjectStore(const IDBTransaction
     return true;
 }
 
+PassRefPtr<IDBKey> UniqueIDBDatabaseBackingStoreSQLite::generateKey(const IDBTransactionIdentifier&, int64_t objectStoreID)
+{
+    // FIXME (<rdar://problem/15877909>): Implement
+    return nullptr;
+}
+
+bool UniqueIDBDatabaseBackingStoreSQLite::keyExistsInObjectStore(const IDBTransactionIdentifier&, int64_t objectStoreID, const IDBKey&, bool& keyExists)
+{
+    // FIXME: When Get support is implemented, we need to implement this also (<rdar://problem/15779644>)
+    return false;
+}
+
+bool UniqueIDBDatabaseBackingStoreSQLite::putRecord(const IDBTransactionIdentifier& identifier, int64_t objectStoreID, const IDBKey& key, const uint8_t* valueBuffer, size_t valueSize)
+{
+    ASSERT(!isMainThread());
+    ASSERT(m_sqliteDB);
+    ASSERT(m_sqliteDB->isOpen());
+
+    SQLiteIDBTransaction* transaction = m_transactions.get(identifier);
+    if (!transaction || !transaction->inProgress()) {
+        LOG_ERROR("Attempt to put a record into database without an established, in-progress transaction");
+        return false;
+    }
+    if (transaction->mode() == IndexedDB::TransactionMode::ReadOnly) {
+        LOG_ERROR("Attempt to put a record into database during read-only transaction");
+        return false;
+    }
+
+    RefPtr<SharedBuffer> keyBuffer = serializeIDBKey(key);
+    if (!keyBuffer) {
+        LOG_ERROR("Unable to serialize IDBKey to be stored in the database");
+        return false;
+    }
+    {
+        SQLiteStatement sql(*m_sqliteDB, ASCIILiteral("INSERT INTO Records VALUES (?, ?, ?);"));
+        if (sql.prepare() != SQLResultOk
+            || sql.bindInt64(1, objectStoreID) != SQLResultOk
+            || sql.bindBlob(2, keyBuffer->data(), keyBuffer->size()) != SQLResultOk
+            || sql.bindBlob(3, valueBuffer, valueSize) != SQLResultOk
+            || sql.step() != SQLResultDone) {
+            LOG_ERROR("Could not put record for object store %lli in Records table (%i) - %s", objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool UniqueIDBDatabaseBackingStoreSQLite::updateKeyGenerator(const IDBTransactionIdentifier&, int64_t objectStoreId, const IDBKey&, bool checkCurrent)
+{
+    // FIXME (<rdar://problem/15877909>): Implement
+    return false;
+}
+
 
 } // namespace WebKit
 
index 891c98d..64503b5 100644 (file)
@@ -64,6 +64,11 @@ public:
     virtual bool createObjectStore(const IDBTransactionIdentifier&, const WebCore::IDBObjectStoreMetadata&) override;
     virtual bool deleteObjectStore(const IDBTransactionIdentifier&, int64_t objectStoreID) override;
 
+    virtual PassRefPtr<WebCore::IDBKey> generateKey(const IDBTransactionIdentifier&, int64_t objectStoreID) override;
+    virtual bool keyExistsInObjectStore(const IDBTransactionIdentifier&, int64_t objectStoreID, const WebCore::IDBKey&, bool& keyExists) override;
+    virtual bool putRecord(const IDBTransactionIdentifier&, int64_t objectStoreID, const WebCore::IDBKey&, const uint8_t* valueBuffer, size_t valueSize) override;
+    virtual bool updateKeyGenerator(const IDBTransactionIdentifier&, int64_t objectStoreId, const WebCore::IDBKey&, bool checkCurrent) override;
+
 private:
     UniqueIDBDatabaseBackingStoreSQLite(const UniqueIDBDatabaseIdentifier&, const String& databaseDirectory);
 
index ed405fd..2d6476c 100644 (file)
@@ -177,6 +177,7 @@ def struct_or_class(namespace, type):
         'WebCore::FileChooserSettings',
         'WebCore::GrammarDetail',
         'WebCore::IDBDatabaseMetadata',
+        'WebCore::IDBKeyData',
         'WebCore::IDBObjectStoreMetadata',
         'WebCore::IdentityTransformOperation',
         'WebCore::KeypressCommand',
index 187a63b..bedd8c1 100644 (file)
@@ -116,6 +116,50 @@ std::unique_ptr<AsyncTask> createAsyncTask(
         WebCore::CrossThreadCopier<P3>::copy(parameter3));
 }
 
+template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4>
+std::unique_ptr<AsyncTask> createAsyncTask(
+    T& callee,
+    void (T::*method)(MP1, MP2, MP3, MP4),
+    const P1& parameter1,
+    const P2& parameter2,
+    const P3& parameter3,
+    const P4& parameter4)
+{
+    return std::make_unique<AsyncTaskImpl<T, MP1, MP2, MP3, MP4>>(
+        &callee,
+        method,
+        WebCore::CrossThreadCopier<P1>::copy(parameter1),
+        WebCore::CrossThreadCopier<P2>::copy(parameter2),
+        WebCore::CrossThreadCopier<P3>::copy(parameter3),
+        WebCore::CrossThreadCopier<P4>::copy(parameter4));
+}
+
+template<typename T, typename P1, typename MP1, typename P2, typename MP2, typename P3, typename MP3, typename P4, typename MP4, typename P5, typename MP5, typename P6, typename MP6, typename P7, typename MP7, typename P8, typename MP8>
+std::unique_ptr<AsyncTask> createAsyncTask(
+    T& callee,
+    void (T::*method)(MP1, MP2, MP3, MP4, MP5, MP6, MP7, MP8),
+    const P1& parameter1,
+    const P2& parameter2,
+    const P3& parameter3,
+    const P4& parameter4,
+    const P5& parameter5,
+    const P6& parameter6,
+    const P7& parameter7,
+    const P8& parameter8)
+{
+    return std::make_unique<AsyncTaskImpl<T, MP1, MP2, MP3, MP4, MP5, MP6, MP7, MP8>>(
+        &callee,
+        method,
+        WebCore::CrossThreadCopier<P1>::copy(parameter1),
+        WebCore::CrossThreadCopier<P2>::copy(parameter2),
+        WebCore::CrossThreadCopier<P3>::copy(parameter3),
+        WebCore::CrossThreadCopier<P4>::copy(parameter4),
+        WebCore::CrossThreadCopier<P5>::copy(parameter5),
+        WebCore::CrossThreadCopier<P6>::copy(parameter6),
+        WebCore::CrossThreadCopier<P7>::copy(parameter7),
+        WebCore::CrossThreadCopier<P8>::copy(parameter8));
+}
+
 } // namespace WebKit
 
 #endif // AsyncTask_h
index d4d5f88..6fbf844 100644 (file)
@@ -42,6 +42,7 @@
 #include <WebCore/GraphicsContext.h>
 #include <WebCore/GraphicsLayer.h>
 #include <WebCore/IDBDatabaseMetadata.h>
+#include <WebCore/IDBKeyData.h>
 #include <WebCore/IDBKeyPath.h>
 #include <WebCore/Image.h>
 #include <WebCore/Length.h>
@@ -1622,6 +1623,68 @@ bool ArgumentCoder<IDBIndexMetadata>::decode(ArgumentDecoder& decoder, IDBIndexM
     return true;
 }
 
+void ArgumentCoder<IDBKeyData>::encode(ArgumentEncoder& encoder, const IDBKeyData& keyData)
+{
+    encoder << keyData.isNull;
+    if (keyData.isNull)
+        return;
+
+    encoder.encodeEnum(keyData.type);
+
+    switch (keyData.type) {
+    case IDBKey::InvalidType:
+        break;
+    case IDBKey::ArrayType:
+        encoder << keyData.arrayValue;
+        break;
+    case IDBKey::StringType:
+        encoder << keyData.stringValue;
+        break;
+    case IDBKey::DateType:
+    case IDBKey::NumberType:
+        encoder << keyData.numberValue;
+        break;
+    case IDBKey::MinType:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+bool ArgumentCoder<IDBKeyData>::decode(ArgumentDecoder& decoder, IDBKeyData& keyData)
+{
+    if (!decoder.decode(keyData.isNull))
+        return false;
+
+    if (keyData.isNull)
+        return true;
+
+    if (!decoder.decodeEnum(keyData.type))
+        return false;
+
+    switch (keyData.type) {
+    case IDBKey::InvalidType:
+        break;
+    case IDBKey::ArrayType:
+        if (!decoder.decode(keyData.arrayValue))
+            return false;
+        break;
+    case IDBKey::StringType:
+        if (!decoder.decode(keyData.stringValue))
+            return false;
+        break;
+    case IDBKey::DateType:
+    case IDBKey::NumberType:
+        if (!decoder.decode(keyData.numberValue))
+            return false;
+        break;
+    case IDBKey::MinType:
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    return true;
+}
+
 void ArgumentCoder<IDBKeyPath>::encode(ArgumentEncoder& encoder, const IDBKeyPath& keyPath)
 {
     encoder.encodeEnum(keyPath.type());
index 8ef9053..573f244 100644 (file)
@@ -66,6 +66,7 @@ struct DragSession;
 struct FileChooserSettings;
 struct IDBDatabaseMetadata;
 struct IDBIndexMetadata;
+struct IDBKeyData;
 struct IDBObjectStoreMetadata;
 struct Length;
 struct GrammarDetail;
@@ -364,6 +365,11 @@ template<> struct ArgumentCoder<WebCore::IDBIndexMetadata> {
     static bool decode(ArgumentDecoder&, WebCore::IDBIndexMetadata&);
 };
 
+template<> struct ArgumentCoder<WebCore::IDBKeyData> {
+    static void encode(ArgumentEncoder&, const WebCore::IDBKeyData&);
+    static bool decode(ArgumentDecoder&, WebCore::IDBKeyData&);
+};
+
 template<> struct ArgumentCoder<WebCore::IDBKeyPath> {
     static void encode(ArgumentEncoder&, const WebCore::IDBKeyPath&);
     static bool decode(ArgumentDecoder&, WebCore::IDBKeyPath&);
index 5c33c28..c7b0669 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "IDBTransactionIdentifier.h"
 #include "UniqueIDBDatabaseIdentifier.h"
+#include <WebCore/IDBKeyData.h>
 
 using namespace WebKit;
 
@@ -51,6 +52,31 @@ Vector<int64_t> CrossThreadCopierBase<false, false, Vector<int64_t>>::copy(const
     return result;
 }
 
+Vector<uint8_t> CrossThreadCopierBase<false, false, Vector<uint8_t>>::copy(const Vector<uint8_t>& vector)
+{
+    Vector<uint8_t> result;
+    result.appendVector(vector);
+    return result;
+}
+
+Vector<Vector<IDBKeyData>> CrossThreadCopierBase<false, false, Vector<Vector<IDBKeyData>>>::copy(const Vector<Vector<IDBKeyData>>& vector)
+{
+    Vector<Vector<IDBKeyData>> result;
+
+    for (auto keys : vector) {
+        result.append(Vector<IDBKeyData>());
+        for (auto key : keys)
+            result.last().append(WebCore::CrossThreadCopier<IDBKeyData>::copy(key));
+    }
+
+    return result;
+}
+
+ASCIILiteral CrossThreadCopierBase<false, false, ASCIILiteral>::copy(const ASCIILiteral& literal)
+{
+    return literal;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index b12038f..a5d0c58 100644 (file)
@@ -36,6 +36,10 @@ class IDBTransactionIdentifier;
 class UniqueIDBDatabaseIdentifier;
 }
 
+namespace WTF {
+class ASCIILiteral;
+}
+
 namespace WebCore {
 
 template<> struct CrossThreadCopierBase<false, false, WebKit::UniqueIDBDatabaseIdentifier> {
@@ -50,6 +54,18 @@ template<> struct CrossThreadCopierBase<false, false, Vector<int64_t>> {
     static Vector<int64_t> copy(const Vector<int64_t>&);
 };
 
+template<> struct CrossThreadCopierBase<false, false, Vector<uint8_t>> {
+    static Vector<uint8_t> copy(const Vector<uint8_t>&);
+};
+
+template<> struct CrossThreadCopierBase<false, false, Vector<Vector<IDBKeyData>>> {
+    static Vector<Vector<IDBKeyData>> copy(const Vector<Vector<IDBKeyData>>&);
+};
+
+template<> struct CrossThreadCopierBase<false, false, WTF::ASCIILiteral> {
+    static WTF::ASCIILiteral copy(const WTF::ASCIILiteral&);
+};
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
index 1a2f53f..0001406 100644 (file)
@@ -30,6 +30,7 @@
 #if ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)
 
 #include "AsyncRequest.h"
+#include "DataReference.h"
 #include "DatabaseProcessIDBConnectionMessages.h"
 #include "DatabaseToWebProcessConnectionMessages.h"
 #include "Logging.h"
@@ -300,8 +301,45 @@ void WebIDBServerConnection::get(IDBTransactionBackend&, const GetOperation&, st
 {
 }
 
-void WebIDBServerConnection::put(IDBTransactionBackend&, const PutOperation&, std::function<void(PassRefPtr<IDBKey>, PassRefPtr<IDBDatabaseError>)> completionCallback)
+void WebIDBServerConnection::put(IDBTransactionBackend& transaction, const PutOperation& operation, std::function<void(PassRefPtr<IDBKey>, PassRefPtr<IDBDatabaseError>)> completionCallback)
 {
+    RefPtr<AsyncRequest> serverRequest = AsyncRequestImpl<PassRefPtr<IDBKey>, PassRefPtr<IDBDatabaseError>>::create(completionCallback);
+
+    serverRequest->setAbortHandler([completionCallback]() {
+        completionCallback(nullptr, IDBDatabaseError::create(IDBDatabaseException::UnknownError, "Unknown error occured putting record"));
+    });
+
+    uint64_t requestID = serverRequest->requestID();
+    ASSERT(!m_serverRequests.contains(requestID));
+    m_serverRequests.add(requestID, serverRequest.release());
+
+    LOG(IDB, "WebProcess put request ID %llu", requestID);
+
+    ASSERT(operation.key());
+    ASSERT(operation.value());
+
+    IPC::DataReference value(reinterpret_cast<const uint8_t*>(operation.value()->data()), operation.value()->size());
+
+    Vector<Vector<IDBKeyData>> indexKeys;
+    for (auto keys : operation.indexKeys()) {
+        indexKeys.append(Vector<IDBKeyData>());
+        for (auto key : keys)
+            indexKeys.last().append(IDBKeyData(key.get()));
+    }
+
+    send(Messages::DatabaseProcessIDBConnection::PutRecord(requestID, transaction.id(), operation.objectStore().id, IDBKeyData(operation.key()), value, operation.putMode(), operation.indexIDs(), indexKeys));
+}
+
+void WebIDBServerConnection::didPutRecord(uint64_t requestID, const WebCore::IDBKeyData& resultKey, uint32_t errorCode, const String& errorMessage)
+{
+    LOG(IDB, "WebProcess didPutRecord request ID %llu (error - %s)", requestID, errorMessage.utf8().data());
+
+    RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);
+
+    if (!serverRequest)
+        return;
+
+    serverRequest->completeRequest(resultKey.isNull ? nullptr : resultKey.maybeCreateIDBKey(), errorCode ? IDBDatabaseError::create(errorCode, errorMessage) : nullptr);
 }
 
 void WebIDBServerConnection::openCursor(IDBTransactionBackend&, const OpenCursorOperation&, std::function<void(PassRefPtr<IDBDatabaseError>)> completionCallback)
index 354ec55..6676930 100644 (file)
 #include <WebCore/IDBDatabaseMetadata.h>
 #include <WebCore/IDBServerConnection.h>
 
+namespace WebCore {
+struct IDBKeyData;
+}
+
 namespace WebKit {
 
 class AsyncRequest;
@@ -102,6 +106,7 @@ private:
     void didChangeDatabaseVersion(uint64_t requestID, bool success);
     void didCreateObjectStore(uint64_t requestID, bool success);
     void didDeleteObjectStore(uint64_t requestID, bool success);
+    void didPutRecord(uint64_t requestID, const WebCore::IDBKeyData&, uint32_t errorCode, const String& errorMessage);
 
     uint64_t m_serverConnectionIdentifier;
 
index e2a0d50..b0ba108 100644 (file)
@@ -34,6 +34,7 @@ messages -> WebIDBServerConnection LegacyReceiver {
     DidChangeDatabaseVersion(uint64_t requestID, bool success)
     DidCreateObjectStore(uint64_t requestID, bool success)
     DidDeleteObjectStore(uint64_t requestID, bool success)
+    DidPutRecord(uint64_t requestID, WebCore::IDBKeyData resultKey, uint32_t errorCode, String errorMessage)
 }
 
 #endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS)