Title: [277199] trunk
Revision
277199
Author
rn...@webkit.org
Date
2021-05-07 14:32:50 -0700 (Fri, 07 May 2021)

Log Message

IPC testing API should have the ability to create and receive IPC::Semaphore
https://bugs.webkit.org/show_bug.cgi?id=225537

Reviewed by Wenson Hsieh.

Source/WebKit:

This patch adds the capability to create IPC::Semaphore for IPC testing purposes.
It adds IPC.createSemaphore which creates a _javascript_ object representing a semaphore
with signal and waitFor methods like IPC::Semaphore but waitFor taking milliseconds
to be consistent with other _javascript_ APIs.

This patch also adds the support for encoding RemoteRenderingBackendCreationParameters
to facilitate creating a remote rendering backend during IPC testing.

Tests: TestWebKitAPI.IPCTestingAPI.CanReceiveIPCSemaphore
       TestWebKitAPI.IPCTestingAPI.CanCreateIPCSemaphore

* Platform/IPC/JSIPCBinding.cpp:
(IPC::jsValueForDecodedArgumentValue): Takes r-value reference since IPC::Semaphore
doesn't have a copy constructor.
* Platform/IPC/JSIPCBinding.h:
(IPC::jsValueForDecodedArgumentValue): Ditto. Added a specialization for IPC::Semaphore.
(IPC::putJSValueForDecodeArgumentInArray):
* WebProcess/WebPage/IPCTestingAPI.cpp:
(WebKit::IPCTestingAPI::JSIPCSemaphore): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::create): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::exchange): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::JSIPCSemaphore): Added.
(WebKit::IPCTestingAPI::createTypeError): Moved up.
(WebKit::IPCTestingAPI::JSIPCSemaphore::createJSWrapper): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::wrapperClass): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::unwrap): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::toWrapped): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::initialize): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::finalize): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::staticFunctions): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::signal): Added.
(WebKit::IPCTestingAPI::JSIPCSemaphore::waitFor): Added.
(WebKit::IPCTestingAPI::JSIPC::wrapperClass):
(WebKit::IPCTestingAPI::JSIPC::staticFunctions): Added IPC.createSemaphore.
(WebKit::IPCTestingAPI::getObjectIdentifierFromProperty): Added.
(WebKit::IPCTestingAPI::encodeRemoteRenderingBackendCreationParameters): Added.
(WebKit::IPCTestingAPI::encodeArgument): Added the support for encoding
RemoteRenderingBackendCreationParameters as an IPC argument.
(WebKit::IPCTestingAPI::JSIPC::createSemaphore): Added.
(IPC::jsValueForDecodedArgumentValue): Defined the aforementioned specialization for
IPC::Semaphore with IPCTestingAPI .

Tools:

Added tests to make sure IPC testing API allows creation of a semaphore,
and receiving one as a reply to an IPC message.

* TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm:
(IPCTestingAPI.CanReceiveIPCSemaphore): Added.
(IPCTestingAPI.CanCreateIPCSemaphore): Added.

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (277198 => 277199)


--- trunk/Source/WebKit/ChangeLog	2021-05-07 21:28:46 UTC (rev 277198)
+++ trunk/Source/WebKit/ChangeLog	2021-05-07 21:32:50 UTC (rev 277199)
@@ -1,3 +1,52 @@
+2021-05-07  Ryosuke Niwa  <rn...@webkit.org>
+
+        IPC testing API should have the ability to create and receive IPC::Semaphore
+        https://bugs.webkit.org/show_bug.cgi?id=225537
+
+        Reviewed by Wenson Hsieh.
+
+        This patch adds the capability to create IPC::Semaphore for IPC testing purposes.
+        It adds IPC.createSemaphore which creates a _javascript_ object representing a semaphore
+        with signal and waitFor methods like IPC::Semaphore but waitFor taking milliseconds
+        to be consistent with other _javascript_ APIs.
+
+        This patch also adds the support for encoding RemoteRenderingBackendCreationParameters
+        to facilitate creating a remote rendering backend during IPC testing.
+
+        Tests: TestWebKitAPI.IPCTestingAPI.CanReceiveIPCSemaphore
+               TestWebKitAPI.IPCTestingAPI.CanCreateIPCSemaphore
+
+        * Platform/IPC/JSIPCBinding.cpp:
+        (IPC::jsValueForDecodedArgumentValue): Takes r-value reference since IPC::Semaphore
+        doesn't have a copy constructor.
+        * Platform/IPC/JSIPCBinding.h:
+        (IPC::jsValueForDecodedArgumentValue): Ditto. Added a specialization for IPC::Semaphore.
+        (IPC::putJSValueForDecodeArgumentInArray):
+        * WebProcess/WebPage/IPCTestingAPI.cpp:
+        (WebKit::IPCTestingAPI::JSIPCSemaphore): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::create): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::exchange): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::JSIPCSemaphore): Added.
+        (WebKit::IPCTestingAPI::createTypeError): Moved up.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::createJSWrapper): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::wrapperClass): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::unwrap): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::toWrapped): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::initialize): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::finalize): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::staticFunctions): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::signal): Added.
+        (WebKit::IPCTestingAPI::JSIPCSemaphore::waitFor): Added.
+        (WebKit::IPCTestingAPI::JSIPC::wrapperClass):
+        (WebKit::IPCTestingAPI::JSIPC::staticFunctions): Added IPC.createSemaphore.
+        (WebKit::IPCTestingAPI::getObjectIdentifierFromProperty): Added.
+        (WebKit::IPCTestingAPI::encodeRemoteRenderingBackendCreationParameters): Added.
+        (WebKit::IPCTestingAPI::encodeArgument): Added the support for encoding
+        RemoteRenderingBackendCreationParameters as an IPC argument.
+        (WebKit::IPCTestingAPI::JSIPC::createSemaphore): Added.
+        (IPC::jsValueForDecodedArgumentValue): Defined the aforementioned specialization for
+        IPC::Semaphore with IPCTestingAPI .
+
 2021-05-07  Wenson Hsieh  <wenson_hs...@apple.com>
 
         [macOS] Set the -isSourceEditable property when presenting webpage translation popup

Modified: trunk/Source/WebKit/Platform/IPC/JSIPCBinding.cpp (277198 => 277199)


--- trunk/Source/WebKit/Platform/IPC/JSIPCBinding.cpp	2021-05-07 21:28:46 UTC (rev 277198)
+++ trunk/Source/WebKit/Platform/IPC/JSIPCBinding.cpp	2021-05-07 21:32:50 UTC (rev 277199)
@@ -51,19 +51,19 @@
 }
 
 template<>
-JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const String& value)
+JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, String&& value)
 {
     return jsValueForDecodedStringArgumentValue(globalObject, value, "String"_s);
 }
 
 template<>
-JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const URL& value)
+JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, URL&& value)
 {
     return jsValueForDecodedStringArgumentValue(globalObject, value.string(), "URL"_s);
 }
 
 template<>
-JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const WebCore::RegistrableDomain& value)
+JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, WebCore::RegistrableDomain&& value)
 {
     return jsValueForDecodedStringArgumentValue(globalObject, value.string(), "RegistrableDomain"_s);
 }
@@ -183,13 +183,13 @@
 }
 
 template<>
-JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const WebCore::IntRect& value)
+JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, WebCore::IntRect&& value)
 {
     return jsValueForDecodedArgumentRect(globalObject, value, "IntRect");
 }
 
 template<>
-JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const WebCore::FloatRect& value)
+JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, WebCore::FloatRect&& value)
 {
     return jsValueForDecodedArgumentRect(globalObject, value, "FloatRect");
 }

Modified: trunk/Source/WebKit/Platform/IPC/JSIPCBinding.h (277198 => 277199)


--- trunk/Source/WebKit/Platform/IPC/JSIPCBinding.h	2021-05-07 21:28:46 UTC (rev 277198)
+++ trunk/Source/WebKit/Platform/IPC/JSIPCBinding.h	2021-05-07 21:32:50 UTC (rev 277199)
@@ -53,16 +53,20 @@
 
 namespace IPC {
 
+class Semaphore;
+
 template<typename T, std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value>* = nullptr>
-JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, const T&)
+JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, T&&)
 {
     return JSC::jsUndefined();
 }
 
-template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, const String&);
-template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, const URL&);
-template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, const WebCore::RegistrableDomain&);
+template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, String&&);
+template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, URL&&);
+template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, WebCore::RegistrableDomain&&);
 
+template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, IPC::Semaphore&&);
+
 template<typename T, std::enable_if_t<std::is_arithmetic<T>::value>* = nullptr>
 JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, T)
 {
@@ -89,16 +93,16 @@
 template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, size_t);
 
 template<typename U>
-JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const ObjectIdentifier<U>& value)
+JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, ObjectIdentifier<U>&& value)
 {
     return jsValueForDecodedArgumentValue(globalObject, value.toUInt64());
 }
 
-template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, const WebCore::IntRect&);
-template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, const WebCore::FloatRect&);
+template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, WebCore::IntRect&&);
+template<> JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, WebCore::FloatRect&&);
 
 template<typename U>
-JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const OptionSet<U>& value)
+JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, OptionSet<U>&& value)
 {    
     auto& vm = globalObject->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -129,7 +133,7 @@
     if (!value)
         return WTF::nullopt;
 
-    auto jsValue = jsValueForDecodedArgumentValue(globalObject, *value);
+    auto jsValue = jsValueForDecodedArgumentValue(globalObject, WTFMove(*value));
     if (jsValue.isEmpty())
         return jsValue;
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp (277198 => 277199)


--- trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp	2021-05-07 21:28:46 UTC (rev 277198)
+++ trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp	2021-05-07 21:32:50 UTC (rev 277199)
@@ -31,8 +31,11 @@
 #include "Encoder.h"
 #include "FrameInfoData.h"
 #include "GPUProcessConnection.h"
+#include "IPCSemaphore.h"
+#include "JSIPCBinding.h"
 #include "MessageArgumentDescriptions.h"
 #include "NetworkProcessConnection.h"
+#include "RemoteRenderingBackendCreationParameters.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebFrame.h"
 #include "WebPage.h"
@@ -50,11 +53,46 @@
 #include <WebCore/Frame.h>
 #include <WebCore/RegistrableDomain.h>
 #include <WebCore/ScriptController.h>
+#include <wtf/PageBlock.h>
 
 namespace WebKit {
 
 namespace IPCTestingAPI {
 
+class JSIPCSemaphore : public RefCounted<JSIPCSemaphore> {
+public:
+    static Ref<JSIPCSemaphore> create(IPC::Semaphore&& semaphore = { })
+    {
+        return adoptRef(*new JSIPCSemaphore(WTFMove(semaphore)));
+    }
+
+    JSObjectRef createJSWrapper(JSContextRef);
+
+    static JSIPCSemaphore* toWrapped(JSContextRef, JSValueRef);
+
+    IPC::Semaphore exchange(IPC::Semaphore&& semaphore = { })
+    {
+        return std::exchange(m_semaphore, WTFMove(semaphore));
+    }
+
+private:
+    JSIPCSemaphore(IPC::Semaphore&& semaphore)
+        : m_semaphore(WTFMove(semaphore))
+    { }
+
+    static JSClassRef wrapperClass();
+    static JSIPCSemaphore* unwrap(JSObjectRef);
+    static void initialize(JSContextRef, JSObjectRef);
+    static void finalize(JSObjectRef);
+
+    static const JSStaticFunction* staticFunctions();
+
+    static JSValueRef signal(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef waitFor(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+    IPC::Semaphore m_semaphore;
+};
+
 class JSIPC;
 
 class JSMessageListener final : public IPC::Connection::MessageObserver {
@@ -106,6 +144,8 @@
     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 createSemaphore(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
     static JSValueRef visitedLinkStoreID(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception);
     static JSValueRef webPageProxyID(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception);
     static JSValueRef sessionID(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception);
@@ -120,6 +160,118 @@
     Vector<UniqueRef<JSMessageListener>> m_messageListeners;
 };
 
+static JSValueRef createTypeError(JSContextRef context, const String& message)
+{
+    JSC::JSLockHolder lock(toJS(context)->vm());
+    return toRef(JSC::createTypeError(toJS(context), message));
+}
+
+JSObjectRef JSIPCSemaphore::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 JSIPCSemaphore::wrapperClass()
+{
+    static JSClassRef jsClass;
+    if (!jsClass) {
+        JSClassDefinition definition = kJSClassDefinitionEmpty;
+        definition.className = "Semaphore";
+        definition.parentClass = nullptr;
+        definition.staticValues = nullptr;
+        definition.staticFunctions = staticFunctions();
+        definition.initialize = initialize;
+        definition.finalize = finalize;
+        jsClass = JSClassCreate(&definition);
+    }
+    return jsClass;
+}
+
+inline JSIPCSemaphore* JSIPCSemaphore::unwrap(JSObjectRef object)
+{
+    return static_cast<JSIPCSemaphore*>(JSObjectGetPrivate(object));
+}
+
+JSIPCSemaphore* JSIPCSemaphore::toWrapped(JSContextRef context, JSValueRef value)
+{
+    if (!context || !value || !JSValueIsObjectOfClass(context, value, wrapperClass()))
+        return nullptr;
+    return unwrap(JSValueToObject(context, value, 0));
+}
+
+void JSIPCSemaphore::initialize(JSContextRef, JSObjectRef object)
+{
+    unwrap(object)->ref();
+}
+
+void JSIPCSemaphore::finalize(JSObjectRef object)
+{
+    unwrap(object)->deref();
+}
+
+const JSStaticFunction* JSIPCSemaphore::staticFunctions()
+{
+    static const JSStaticFunction functions[] = {
+        { "signal", signal, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { "waitFor", waitFor, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 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);
+    JSC::JSLockHolder lock(globalObject->vm());
+    auto isIPCSemaphore = makeRefPtr(toWrapped(context, thisObject));
+    if (!isIPCSemaphore) {
+        *exception = createTypeError(context, "Wrong type"_s);
+        return JSValueMakeUndefined(context);
+    }
+
+    isIPCSemaphore->m_semaphore.signal();
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSIPCSemaphore::waitFor(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    auto* globalObject = toJS(context);
+    JSC::JSLockHolder lock(globalObject->vm());
+    auto isIPCSemaphore = makeRefPtr(toWrapped(context, thisObject));
+    if (!isIPCSemaphore) {
+        *exception = createTypeError(context, "Wrong type"_s);
+        return JSValueMakeUndefined(context);
+    }
+
+    if (argumentCount < 1) {
+        *exception = createTypeError(context, "Must specify the timeout in milliseconds as the first argument"_s);
+        return JSValueMakeUndefined(context);
+    }
+
+    auto jsValue = toJS(globalObject, arguments[0]);
+    Seconds timeout;
+    if (jsValue.isNumber()) {
+        double milliseconds = jsValue.asNumber();
+        if (std::isfinite(milliseconds) && milliseconds > 0)
+            timeout = Seconds::fromMilliseconds(milliseconds);
+    }
+    if (!timeout) {
+        *exception = createTypeError(context, "Timeout must be a positive number"_s);
+        return JSValueMakeUndefined(context);
+    }
+
+    auto result = isIPCSemaphore->m_semaphore.waitFor(timeout);
+
+    return JSValueMakeBoolean(context, result);
+}
+
 JSClassRef JSIPC::wrapperClass()
 {
     static JSClassRef jsClass;
@@ -126,7 +278,7 @@
     if (!jsClass) {
         JSClassDefinition definition = kJSClassDefinitionEmpty;
         definition.className = "IPC";
-        definition.parentClass = 0;
+        definition.parentClass = nullptr;
         definition.staticValues = staticValues();
         definition.staticFunctions = staticFunctions();
         definition.initialize = initialize;
@@ -165,6 +317,7 @@
         { "addOutgoingMessageListener", addOutgoingMessageListener, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
         { "sendMessage", sendMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
         { "sendSyncMessage", sendSyncMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { "createSemaphore", createSemaphore, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
         { 0, 0, 0 }
     };
     return functions;
@@ -197,12 +350,6 @@
     return WTF::nullopt;
 }
 
-static JSValueRef createTypeError(JSContextRef context, const String& message)
-{
-    JSC::JSLockHolder lock(toJS(context)->vm());
-    return toRef(JSC::createTypeError(toJS(context), message));
-}
-
 static RefPtr<IPC::Connection> processTargetFromArgument(JSC::JSGlobalObject* globalObject, JSValueRef valueRef, JSValueRef* exception)
 {
     auto scope = DECLARE_CATCH_SCOPE(globalObject->vm());
@@ -363,6 +510,49 @@
     return true;
 }
 
+#if ENABLE(GPU_PROCESS)
+template <typename ObjectIdentifierType>
+Optional<ObjectIdentifier<ObjectIdentifierType>> getObjectIdentifierFromProperty(JSC::JSGlobalObject* globalObject, JSC::JSObject* jsObject, ASCIILiteral propertyName, JSC::CatchScope& scope)
+{
+    auto jsPropertyValue = jsObject->get(globalObject, JSC::Identifier::fromString(globalObject->vm(), propertyName));
+    if (scope.exception())
+        return WTF::nullopt;
+    if (jsPropertyValue.isBigInt()) 
+        return makeObjectIdentifier<ObjectIdentifierType>(JSC::JSBigInt::toBigUInt64(jsPropertyValue));
+    if (jsPropertyValue.isNumber())
+        return makeObjectIdentifier<ObjectIdentifierType>(jsPropertyValue.asNumber());
+    return WTF::nullopt;
+}
+
+static bool encodeRemoteRenderingBackendCreationParameters(IPC::Encoder& encoder, JSC::JSGlobalObject* globalObject, JSC::JSObject* jsObject, JSC::CatchScope& scope)
+{
+    auto identifier = getObjectIdentifierFromProperty<RenderingBackendIdentifierType>(globalObject, jsObject, "identifier"_s, scope);
+    if (!identifier)
+        return false;
+
+    auto jsSemaphore = jsObject->get(globalObject, JSC::Identifier::fromString(globalObject->vm(), "semaphore"_s));
+    if (scope.exception())
+        return false;
+    auto semaphoreObject = makeRefPtr(JSIPCSemaphore::toWrapped(toRef(globalObject), toRef(jsSemaphore)));
+    if (!semaphoreObject)
+        return false;
+
+    auto pageProxyID = getObjectIdentifierFromProperty<WebPageProxyIdentifierType>(globalObject, jsObject, "pageProxyID"_s, scope);
+    if (!pageProxyID)
+        return false;
+
+    auto pageID = getObjectIdentifierFromProperty<WebCore::PageIdentifierType>(globalObject, jsObject, "pageID"_s, scope);
+    if (!pageID)
+        return false;
+
+    auto semaphore = semaphoreObject->exchange();
+    RemoteRenderingBackendCreationParameters parameters { *identifier, WTFMove(semaphore), *pageProxyID, *pageID };
+    encoder << parameters;
+    semaphoreObject->exchange(WTFMove(parameters.resumeDisplayListSemaphore));
+    return true;
+}
+#endif
+
 static bool encodeArgument(IPC::Encoder&, JSIPC&, JSContextRef, JSValueRef, JSValueRef* exception);
 
 struct VectorEncodeHelper {
@@ -475,6 +665,16 @@
         return true;
     }
 
+#if ENABLE(GPU_PROCESS)
+    if (type == "RemoteRenderingBackendCreationParameters") {
+        if (!encodeRemoteRenderingBackendCreationParameters(encoder, globalObject, jsObject, scope)) {
+            *exception = createTypeError(context, "Failed to convert RemoteRenderingBackendCreationParameters"_s);
+            return false;
+        }
+        return true;
+    }
+#endif
+
     if (type == "FrameInfoData") {
         auto webFrame = makeRefPtr(jsIPC.webFrame());
         if (!webFrame) {
@@ -760,6 +960,11 @@
     return JSValueMakeUndefined(context);
 }
 
+JSValueRef JSIPC::createSemaphore(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    return JSIPCSemaphore::create()->createJSWrapper(context);
+}
+
 JSValueRef JSIPC::visitedLinkStoreID(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef* exception)
 {
     return retrieveID(context, thisObject, exception, [](JSIPC& wrapped) {
@@ -1017,4 +1222,23 @@
 
 } // namespace WebKit
 
+namespace IPC {
+
+template<>
+JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, IPC::Semaphore&& value)
+{
+    auto& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    auto* object = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype());
+    RETURN_IF_EXCEPTION(scope, JSC::JSValue());
+    object->putDirect(vm, JSC::Identifier::fromString(vm, "type"_s), JSC::jsNontrivialString(vm, "Semaphore"));
+    RETURN_IF_EXCEPTION(scope, JSC::JSValue());
+    auto jsValue = toJS(globalObject, WebKit::IPCTestingAPI::JSIPCSemaphore::create(WTFMove(value))->createJSWrapper(toRef(globalObject)));
+    object->putDirect(vm, JSC::Identifier::fromString(vm, "value"_s), jsValue);
+    RETURN_IF_EXCEPTION(scope, JSC::JSValue());
+    return object;
+}
+
+} // namespace IPC
+
 #endif

Modified: trunk/Tools/ChangeLog (277198 => 277199)


--- trunk/Tools/ChangeLog	2021-05-07 21:28:46 UTC (rev 277198)
+++ trunk/Tools/ChangeLog	2021-05-07 21:32:50 UTC (rev 277199)
@@ -1,3 +1,17 @@
+2021-05-07  Ryosuke Niwa  <rn...@webkit.org>
+
+        IPC testing API should have the ability to create and receive IPC::Semaphore
+        https://bugs.webkit.org/show_bug.cgi?id=225537
+
+        Reviewed by Wenson Hsieh.
+
+        Added tests to make sure IPC testing API allows creation of a semaphore,
+        and receiving one as a reply to an IPC message.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm:
+        (IPCTestingAPI.CanReceiveIPCSemaphore): Added.
+        (IPCTestingAPI.CanCreateIPCSemaphore): Added.
+
 2021-05-07  Aakash Jain  <aakash_j...@apple.com>
 
         Use test-tube emoji for EWS status bubbles for tester queues

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm (277198 => 277199)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm	2021-05-07 21:28:46 UTC (rev 277198)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm	2021-05-07 21:32:50 UTC (rev 277199)
@@ -209,8 +209,43 @@
     EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"result.arguments[0].type"].UTF8String, "bool");
     EXPECT_FALSE([webView stringByEvaluatingJavaScript:@"result.arguments[0].value"].boolValue);
 }
+
+TEST(IPCTestingAPI, CanReceiveIPCSemaphore)
+{
+    auto webView = createWebViewWithIPCTestingAPI();
+
+    auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]);
+    [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}]);"
+        "const result = IPC.sendSyncMessage('GPU', 123, IPC.messages.RemoteRenderingBackend_SemaphoreForGetImageData.name, 100, []);"
+        "semaphore.signal();"
+        "alert(result.arguments.length + ':' + result.arguments[0].type + ':' + result.arguments[0].value.waitFor(100));"
+        "</script>"];
+    TestWebKitAPI::Util::run(&done);
+
+    EXPECT_STREQ([alertMessage UTF8String], "1:Semaphore:false");
+}
 #endif
 
+TEST(IPCTestingAPI, CanCreateIPCSemaphore)
+{
+    auto webView = createWebViewWithIPCTestingAPI();
+
+    auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]);
+    [webView setUIDelegate:delegate.get()];
+
+    done = false;
+    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>alert(IPC.createSemaphore().waitFor(100));</script>"];
+    TestWebKitAPI::Util::run(&done);
+
+    EXPECT_FALSE([alertMessage boolValue]);
+}
+
 TEST(IPCTestingAPI, DecodesReplyArgumentsForPrompt)
 {
     auto webView = createWebViewWithIPCTestingAPI();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to