Modified: trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp (284198 => 284199)
--- trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp 2021-10-14 21:18:44 UTC (rev 284198)
+++ trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp 2021-10-14 21:22:13 UTC (rev 284199)
@@ -36,6 +36,8 @@
#include "MessageArgumentDescriptions.h"
#include "NetworkProcessConnection.h"
#include "RemoteRenderingBackendCreationParameters.h"
+#include "StreamClientConnection.h"
+#include "StreamConnectionBuffer.h"
#include "WebCoreArgumentCoders.h"
#include "WebFrame.h"
#include "WebPage.h"
@@ -93,6 +95,61 @@
IPC::Semaphore m_semaphore;
};
+class JSIPCStreamClientConnection : public RefCounted<JSIPCStreamClientConnection> {
+public:
+ static Ref<JSIPCStreamClientConnection> create(IPC::Connection& connection, size_t bufferSize)
+ {
+ return adoptRef(*new JSIPCStreamClientConnection(connection, bufferSize));
+ }
+
+ JSObjectRef createJSWrapper(JSContextRef);
+ static JSIPCStreamClientConnection* toWrapped(JSContextRef, JSValueRef);
+
+ IPC::StreamClientConnection& connection() { return m_streamConnection; }
+
+private:
+ JSIPCStreamClientConnection(IPC::Connection& connection, size_t bufferSize)
+ : m_streamConnection { connection, bufferSize }
+ { }
+
+ static JSClassRef wrapperClass();
+ static JSIPCStreamClientConnection* unwrap(JSObjectRef);
+ static void initialize(JSContextRef, JSObjectRef);
+ static void finalize(JSObjectRef);
+
+ static const JSStaticFunction* staticFunctions();
+ static JSValueRef streamBuffer(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+ IPC::StreamClientConnection m_streamConnection;
+};
+
+class JSIPCStreamConnectionBuffer : public RefCounted<JSIPCStreamConnectionBuffer> {
+public:
+ static Ref<JSIPCStreamConnectionBuffer> create(JSIPCStreamClientConnection& streamConnection)
+ {
+ return adoptRef(*new JSIPCStreamConnectionBuffer(streamConnection));
+ }
+
+ JSObjectRef createJSWrapper(JSContextRef);
+ static JSIPCStreamConnectionBuffer* toWrapped(JSContextRef, JSValueRef);
+
+ void encode(IPC::Encoder& encoder) const { m_streamConnection->connection().streamBuffer().encode(encoder); }
+
+private:
+ JSIPCStreamConnectionBuffer(JSIPCStreamClientConnection& streamConnection)
+ : m_streamConnection(streamConnection)
+ { }
+
+ static JSClassRef wrapperClass();
+ static JSIPCStreamConnectionBuffer* unwrap(JSObjectRef);
+ static void initialize(JSContextRef, JSObjectRef);
+ static void finalize(JSObjectRef);
+
+ static const JSStaticFunction* staticFunctions();
+
+ Ref<JSIPCStreamClientConnection> m_streamConnection;
+};
+
class JSSharedMemory : public RefCounted<JSSharedMemory> {
public:
static Ref<JSSharedMemory> create(size_t size)
@@ -185,6 +242,7 @@
static JSValueRef sendMessage(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
static JSValueRef sendSyncMessage(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+ static JSValueRef createStreamClientConnection(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
static JSValueRef createSemaphore(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
static JSValueRef createSharedMemory(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
@@ -281,6 +339,132 @@
return functions;
}
+JSObjectRef JSIPCStreamClientConnection::createJSWrapper(JSContextRef context)
+{
+ auto* globalObject = toJS(context);
+ auto& vm = globalObject->vm();
+ JSC::JSLockHolder lock(vm);
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ JSObjectRef wrapperObject = JSObjectMake(toGlobalRef(globalObject), wrapperClass(), this);
+ scope.clearException();
+ return wrapperObject;
+}
+
+JSClassRef JSIPCStreamClientConnection::wrapperClass()
+{
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.className = "StreamClientConnection";
+ definition.parentClass = nullptr;
+ definition.staticValues = nullptr;
+ definition.staticFunctions = staticFunctions();
+ definition.initialize = initialize;
+ definition.finalize = finalize;
+ jsClass = JSClassCreate(&definition);
+ }
+ return jsClass;
+}
+
+inline JSIPCStreamClientConnection* JSIPCStreamClientConnection::unwrap(JSObjectRef object)
+{
+ return static_cast<JSIPCStreamClientConnection*>(JSObjectGetPrivate(object));
+}
+
+JSIPCStreamClientConnection* JSIPCStreamClientConnection::toWrapped(JSContextRef context, JSValueRef value)
+{
+ if (!context || !value || !JSValueIsObjectOfClass(context, value, wrapperClass()))
+ return nullptr;
+ return unwrap(JSValueToObject(context, value, nullptr));
+}
+
+void JSIPCStreamClientConnection::initialize(JSContextRef, JSObjectRef object)
+{
+ unwrap(object)->ref();
+}
+
+void JSIPCStreamClientConnection::finalize(JSObjectRef object)
+{
+ unwrap(object)->deref();
+}
+
+const JSStaticFunction* JSIPCStreamClientConnection::staticFunctions()
+{
+ static const JSStaticFunction functions[] = {
+ { "streamBuffer", streamBuffer, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+ { 0, 0, 0 }
+ };
+ return functions;
+}
+
+JSValueRef JSIPCStreamClientConnection::streamBuffer(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ RefPtr jsStreamConnection = toWrapped(context, thisObject);
+ if (!jsStreamConnection) {
+ *exception = createTypeError(context, "Wrong type"_s);
+ return JSValueMakeUndefined(context);
+ }
+
+ return JSIPCStreamConnectionBuffer::create(*jsStreamConnection)->createJSWrapper(context);
+}
+
+JSObjectRef JSIPCStreamConnectionBuffer::createJSWrapper(JSContextRef context)
+{
+ auto* globalObject = toJS(context);
+ auto& vm = globalObject->vm();
+ JSC::JSLockHolder lock(vm);
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ JSObjectRef wrapperObject = JSObjectMake(toGlobalRef(globalObject), wrapperClass(), this);
+ scope.clearException();
+ return wrapperObject;
+}
+
+JSClassRef JSIPCStreamConnectionBuffer::wrapperClass()
+{
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.className = "StreamConnectionBuffer";
+ definition.parentClass = nullptr;
+ definition.staticValues = nullptr;
+ definition.staticFunctions = staticFunctions();
+ definition.initialize = initialize;
+ definition.finalize = finalize;
+ jsClass = JSClassCreate(&definition);
+ }
+ return jsClass;
+}
+
+inline JSIPCStreamConnectionBuffer* JSIPCStreamConnectionBuffer::unwrap(JSObjectRef object)
+{
+ return static_cast<JSIPCStreamConnectionBuffer*>(JSObjectGetPrivate(object));
+}
+
+JSIPCStreamConnectionBuffer* JSIPCStreamConnectionBuffer::toWrapped(JSContextRef context, JSValueRef value)
+{
+ if (!context || !value || !JSValueIsObjectOfClass(context, value, wrapperClass()))
+ return nullptr;
+ return unwrap(JSValueToObject(context, value, nullptr));
+}
+
+void JSIPCStreamConnectionBuffer::initialize(JSContextRef, JSObjectRef object)
+{
+ unwrap(object)->ref();
+}
+
+void JSIPCStreamConnectionBuffer::finalize(JSObjectRef object)
+{
+ unwrap(object)->deref();
+}
+
+const JSStaticFunction* JSIPCStreamConnectionBuffer::staticFunctions()
+{
+ static const JSStaticFunction functions[] = {
+ { 0, 0, 0 }
+ };
+ return functions;
+}
+
JSValueRef JSIPCSemaphore::signal(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
auto* globalObject = toJS(context);
@@ -576,6 +760,7 @@
{ "addOutgoingMessageListener", addOutgoingMessageListener, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
{ "sendMessage", sendMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
{ "sendSyncMessage", sendSyncMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+ { "createStreamClientConnection", createStreamClientConnection, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
{ "createSemaphore", createSemaphore, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
{ "createSharedMemory", createSharedMemory, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
{ 0, 0, 0 }
@@ -812,6 +997,16 @@
return true;
}
+static bool encodeStreamConnectionBuffer(IPC::Encoder& encoder, JSC::JSGlobalObject* globalObject, JSC::JSValue jsValue, JSC::CatchScope& scope)
+{
+ RefPtr jsIPCStreamConnectionBuffer = JSIPCStreamConnectionBuffer::toWrapped(toRef(globalObject), toRef(jsValue));
+ if (!jsIPCStreamConnectionBuffer)
+ return false;
+
+ jsIPCStreamConnectionBuffer->encode(encoder);
+ return true;
+}
+
static bool encodeSemaphore(IPC::Encoder& encoder, JSC::JSGlobalObject* globalObject, JSC::JSValue jsValue, JSC::CatchScope& scope)
{
RefPtr jsIPCSemaphore = JSIPCSemaphore::toWrapped(toRef(globalObject), toRef(jsValue));
@@ -966,6 +1161,14 @@
if (scope.exception())
return false;
+ if (type == "StreamConnectionBuffer") {
+ if (!encodeStreamConnectionBuffer(encoder, globalObject, jsValue, scope)) {
+ *exception = createTypeError(context, "Failed to convert StreamConnectionBuffer"_s);
+ return false;
+ }
+ return true;
+ }
+
if (type == "Semaphore") {
if (!encodeSemaphore(encoder, globalObject, jsValue, scope)) {
*exception = createTypeError(context, "Failed to convert Semaphore"_s);
@@ -1245,6 +1448,34 @@
return JSValueMakeUndefined(context);
}
+JSValueRef JSIPC::createStreamClientConnection(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ auto* globalObject = toJS(context);
+ JSC::JSLockHolder lock(globalObject->vm());
+ RefPtr jsIPC = toWrapped(context, thisObject);
+ if (!jsIPC) {
+ *exception = createTypeError(context, "Wrong type"_s);
+ return JSValueMakeUndefined(context);
+ }
+
+ if (argumentCount < 2) {
+ *exception = createTypeError(context, "Must specify the target process and buffer size as the first two arguments"_s);
+ return JSValueMakeUndefined(context);
+ }
+
+ auto connection = processTargetFromArgument(globalObject, arguments[0], exception);
+ if (!connection)
+ return JSValueMakeUndefined(context);
+
+ auto bufferSize = argumentCount ? convertToUint64(toJS(globalObject, arguments[1])) : std::optional<uint64_t> { };
+ if (!bufferSize) {
+ *exception = createTypeError(context, "Must specify the size"_s);
+ return JSValueMakeUndefined(context);
+ }
+
+ return JSIPCStreamClientConnection::create(*connection, *bufferSize)->createJSWrapper(context);
+}
+
JSValueRef JSIPC::createSemaphore(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
return JSIPCSemaphore::create()->createJSWrapper(context);
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm (284198 => 284199)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm 2021-10-14 21:18:44 UTC (rev 284198)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm 2021-10-14 21:22:13 UTC (rev 284199)
@@ -291,14 +291,19 @@
[webView setUIDelegate:delegate.get()];
done = false;
- [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>"
- "const semaphore = IPC.createSemaphore();"
- "IPC.sendMessage('GPU', 0, IPC.messages.GPUConnectionToWebProcess_CreateRenderingBackend.name,"
- " [{type: 'RemoteRenderingBackendCreationParameters', 'identifier': 123, semaphore, 'pageProxyID': IPC.webPageProxyID, 'pageID': IPC.pageID}]);"
+ auto html = @"<!DOCTYPE html>"
+ "<script>"
+ "const bufferSize = 1 << 16;"
+ "const streamConnection = IPC.createStreamClientConnection('GPU', bufferSize);"
+ "IPC.sendMessage('GPU', 0, IPC.messages.GPUConnectionToWebProcess_CreateRenderingBackend.name, ["
+ " { type: 'RemoteRenderingBackendCreationParameters', 'identifier': 123, 'pageProxyID': IPC.webPageProxyID, 'pageID': IPC.pageID },"
+ " { type: 'StreamConnectionBuffer', value: streamConnection.streamBuffer() },"
+ "]);"
"const result = IPC.sendSyncMessage('GPU', 123, IPC.messages.RemoteRenderingBackend_SemaphoreForGetPixelBuffer.name, 100, []);"
"semaphore.signal();"
"alert(result.arguments.length + ':' + result.arguments[0].type + ':' + result.arguments[0].value.waitFor(100));"
- "</script>"];
+ "</script>";
+ [webView synchronouslyLoadHTMLString:html];
TestWebKitAPI::Util::run(&done);
EXPECT_STREQ([alertMessage UTF8String], "1:Semaphore:false");
@@ -311,13 +316,17 @@
auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]);
[webView setUIDelegate:delegate.get()];
- auto* html = @R"HTML(<!DOCTYPE html>
-<script>
-IPC.sendMessage('GPU', 0, IPC.messages.GPUConnectionToWebProcess_CreateRenderingBackend.name,
- [{type: 'RemoteRenderingBackendCreationParameters', 'identifier': 123, semaphore: IPC.createSemaphore(), 'pageProxyID': IPC.webPageProxyID, 'pageID': IPC.pageID}]);
-const result = IPC.sendSyncMessage('GPU', 123, IPC.messages.RemoteRenderingBackend_UpdateSharedMemoryForGetPixelBuffer.name, 100, [{type: 'uint32_t', value: 8}]);
-alert(result.arguments.length);
-</script>)HTML";
+ auto html = @"<!DOCTYPE html>"
+ "<script>"
+ "const bufferSize = 1 << 16;"
+ "const streamConnection = IPC.createStreamClientConnection('GPU', bufferSize);"
+ "IPC.sendMessage('GPU', 0, IPC.messages.GPUConnectionToWebProcess_CreateRenderingBackend.name, ["
+ " { type: 'RemoteRenderingBackendCreationParameters', 'identifier': 123, 'pageProxyID': IPC.webPageProxyID, 'pageID': IPC.pageID },"
+ " { type: 'StreamConnectionBuffer', value: streamConnection.streamBuffer() },"
+ "]);"
+ "const result = IPC.sendSyncMessage('GPU', 123, IPC.messages.RemoteRenderingBackend_UpdateSharedMemoryForGetPixelBuffer.name, 100, [{type: 'uint32_t', value: 8}]);"
+ "alert(result.arguments.length);"
+ "</script>";
done = false;
[webView synchronouslyLoadHTMLString:html];