Changeset 268848 in webkit
- Timestamp:
- Oct 21, 2020, 5:41:50 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/Platform/IPC/Connection.cpp (modified) (4 diffs)
-
Source/WebKit/Platform/IPC/Connection.h (modified) (3 diffs)
-
Source/WebKit/Platform/IPC/JSIPCBinding.h (modified) (6 diffs)
-
Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp (modified) (8 diffs)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r268842 r268848 1 2020-10-21 Ryosuke Niwa <rniwa@webkit.org> 2 3 IPC testing API should have the capability to observe messages being sent and received 4 https://bugs.webkit.org/show_bug.cgi?id=217870 5 6 Reviewed by Darin Adler. 7 8 Added IPC.addIncomingMessageListener and IPC.addOutgoingMessageListener which allows JavaScript 9 to observe IPC messages being sent or received by WebContent process. We use the generated code 10 added in r268503 to decode the IPC arguments. 11 12 Tests: TestWebKitAPI.IPCTestingAPI.CanInterceptAlert 13 TestWebKitAPI.IPCTestingAPI.CanInterceptHasStorageAccess 14 TestWebKitAPI.IPCTestingAPI.CanInterceptFindString 15 16 * Platform/IPC/Connection.cpp: 17 (IPC::Connection::sendMessage): Added the code to invoke MessageObserver::willSendMessage. 18 Also remove any stale MessageObserver as neded. 19 (IPC::Connection::addMessageObserver): Added. 20 (IPC::Connection::dispatchMessage): Added the code to invoke MessageObserver::didReceiveMessage. 21 Also remove any stale MessageObserver as neded. 22 * Platform/IPC/Connection.h: 23 (IPC::Connection::MessageObserver): Added. A pure virtual interface for observing IPC messages. 24 * Platform/IPC/JSIPCBinding.h: 25 (IPC::jsValueForDecodedStringArgumentValue): Extracted from jsValueForDecodedArgumentValue<String>. 26 Now takes the type name as an argument. 27 (IPC::jsValueForDecodedArgumentValue<URL>): Use "URL" as the type name. 28 (IPC::jsValueForDecodedArgumentValue<RegistrableDomain>): Use "RegistrableDomain" as the type name. 29 (IPC::jsValueForDecodedArgumentValue<OptionSet<U>>): Added. Specializations for OptionSet<U> 30 * WebProcess/WebPage/IPCTestingAPI.cpp: 31 (WebKit::IPCTestingAPI::JSMessageListener): Added. Implements IPC::MessageObserver. 32 (WebKit::IPCTestingAPI::JSIPC::staticFunctions): 33 (WebKit::IPCTestingAPI::createTypeError): Moved. 34 (WebKit::IPCTestingAPI::JSIPC::addMessageListener): Added. 35 (WebKit::IPCTestingAPI::JSIPC::addIncomingMessageListener): Added. 36 (WebKit::IPCTestingAPI::JSIPC::addOutgoingMessageListener): Added. 37 (WebKit::IPCTestingAPI::JSMessageListener::JSMessageListener): Added. 38 (WebKit::IPCTestingAPI::JSMessageListener::didReceiveMessage): Added. 39 (WebKit::IPCTestingAPI::JSMessageListener::willSendMessage): Added. 40 (WebKit::IPCTestingAPI::JSMessageListener::jsDescriptionFromDecoder): Added. 41 1 42 2020-10-21 Aditya Keerthi <akeerthi@apple.com> 2 43 -
trunk/Source/WebKit/Platform/IPC/Connection.cpp
r268504 r268848 454 454 return false; 455 455 456 #if ENABLE(IPC_TESTING_API) 457 if (isMainThread()) { 458 bool hasDeadObservers = false; 459 for (auto& observerWeakPtr : m_messageObservers) { 460 if (auto* observer = observerWeakPtr.get()) 461 observer->willSendMessage(*encoder, sendOptions); 462 else 463 hasDeadObservers = true; 464 } 465 if (hasDeadObservers) 466 m_messageObservers.removeAllMatching([](auto& observer) { return !observer; }); 467 } 468 #endif 469 456 470 if (isMainThread() && m_inDispatchMessageMarkedToUseFullySynchronousModeForTesting && !encoder->isSyncMessage() && !(encoder->messageReceiverName() == ReceiverName::IPC) && !sendOptions.contains(SendOption::IgnoreFullySynchronousMode)) { 457 471 uint64_t syncRequestID; … … 468 482 else if (sendOptions.contains(SendOption::DispatchMessageEvenWhenWaitingForUnboundedSyncReply)) 469 483 encoder->setShouldDispatchMessageWhenWaitingForSyncReply(ShouldDispatchWhenWaitingForSyncReply::YesDuringUnboundedIPC); 484 485 #if ENABLE(IPC_TESTING_API) 486 #endif 470 487 471 488 { … … 823 840 } 824 841 842 #if ENABLE(IPC_TESTING_API) 843 void Connection::addMessageObserver(const MessageObserver& observer) 844 { 845 m_messageObservers.append(makeWeakPtr(observer)); 846 } 847 #endif 848 825 849 void Connection::postConnectionDidCloseOnConnectionWorkQueue() 826 850 { … … 1007 1031 return; 1008 1032 } 1033 1034 #if ENABLE(IPC_TESTING_API) 1035 if (isMainThread()) { 1036 bool hasDeadObservers = false; 1037 for (auto& observerWeakPtr : m_messageObservers) { 1038 if (auto* observer = observerWeakPtr.get()) 1039 observer->didReceiveMessage(decoder); 1040 else 1041 hasDeadObservers = true; 1042 } 1043 if (hasDeadObservers) 1044 m_messageObservers.removeAllMatching([](auto& observer) { return !observer; }); 1045 } 1046 #endif 1009 1047 1010 1048 m_client.didReceiveMessage(*this, decoder); -
trunk/Source/WebKit/Platform/IPC/Connection.h
r268690 r268848 140 140 }; 141 141 142 #if ENABLE(IPC_TESTING_API) 143 class MessageObserver : public CanMakeWeakPtr<MessageObserver> { 144 public: 145 virtual ~MessageObserver() = default; 146 virtual void willSendMessage(const Encoder&, OptionSet<SendOption>) = 0; 147 virtual void didReceiveMessage(const Decoder&) = 0; 148 }; 149 #endif 150 142 151 #if USE(UNIX_DOMAIN_SOCKETS) 143 152 typedef int Identifier; … … 289 298 290 299 #if ENABLE(IPC_TESTING_API) 300 void addMessageObserver(const MessageObserver&); 301 291 302 void setIgnoreInvalidMessageForTesting() { m_ignoreInvalidMessageForTesting = true; } 292 303 bool ignoreInvalidMessageForTesting() const { return m_ignoreInvalidMessageForTesting; } … … 419 430 420 431 #if ENABLE(IPC_TESTING_API) 432 Vector<WeakPtr<MessageObserver>> m_messageObservers; 421 433 bool m_ignoreInvalidMessageForTesting { false }; 422 434 #endif -
trunk/Source/WebKit/Platform/IPC/JSIPCBinding.h
r268503 r268848 39 39 #include <wtf/text/WTFString.h> 40 40 41 namespace IPC { 42 41 43 template<typename T, std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value>* = nullptr> 42 44 JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject*, const T&) … … 45 47 } 46 48 49 inline JSC::JSValue jsValueForDecodedStringArgumentValue(JSC::JSGlobalObject* globalObject, const String& value, ASCIILiteral type) 50 { 51 auto& vm = globalObject->vm(); 52 auto scope = DECLARE_THROW_SCOPE(vm); 53 auto* object = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype()); 54 RETURN_IF_EXCEPTION(scope, JSC::JSValue()); 55 object->putDirect(vm, JSC::Identifier::fromString(vm, "type"_s), JSC::jsNontrivialString(vm, type)); 56 RETURN_IF_EXCEPTION(scope, JSC::JSValue()); 57 object->putDirect(vm, JSC::Identifier::fromString(vm, "value"_s), value.isNull() ? JSC::jsNull() : JSC::jsString(vm, value)); 58 RETURN_IF_EXCEPTION(scope, JSC::JSValue()); 59 return object; 60 } 61 47 62 template<> 48 63 JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const String& value) 49 64 { 50 auto& vm = globalObject->vm(); 51 auto scope = DECLARE_THROW_SCOPE(vm); 52 auto* object = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype()); 53 RETURN_IF_EXCEPTION(scope, JSC::JSValue()); 54 object->putDirect(vm, JSC::Identifier::fromString(vm, "type"_s), JSC::jsNontrivialString(vm, "String"_s)); 55 RETURN_IF_EXCEPTION(scope, JSC::JSValue()); 56 object->putDirect(vm, JSC::Identifier::fromString(vm, "value"_s), JSC::jsNontrivialString(vm, value)); 57 RETURN_IF_EXCEPTION(scope, JSC::JSValue()); 58 return object; 65 return jsValueForDecodedStringArgumentValue(globalObject, value, "String"_s); 59 66 } 60 67 … … 62 69 JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const URL& value) 63 70 { 64 return jsValueForDecoded ArgumentValue(globalObject, value.string());71 return jsValueForDecodedStringArgumentValue(globalObject, value.string(), "URL"_s); 65 72 } 66 73 … … 68 75 JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const WebCore::RegistrableDomain& value) 69 76 { 70 return jsValueForDecoded ArgumentValue(globalObject, value.string());77 return jsValueForDecodedStringArgumentValue(globalObject, value.string(), "RegistrableDomain"_s); 71 78 } 72 79 … … 206 213 { 207 214 return jsValueForDecodedArgumentRect(globalObject, value, "FloatRect"); 215 } 216 217 template<typename U> 218 JSC::JSValue jsValueForDecodedArgumentValue(JSC::JSGlobalObject* globalObject, const OptionSet<U>& value) 219 { 220 auto& vm = globalObject->vm(); 221 auto scope = DECLARE_THROW_SCOPE(vm); 222 auto result = jsValueForDecodedArgumentValue(globalObject, value.toRaw()); 223 RETURN_IF_EXCEPTION(scope, JSC::JSValue()); 224 result.getObject()->putDirect(vm, JSC::Identifier::fromString(vm, "isOptionSet"_s), JSC::jsBoolean(true)); 225 RETURN_IF_EXCEPTION(scope, JSC::JSValue()); 226 return result; 208 227 } 209 228 … … 254 273 return jsValueForArgumentTuple(globalObject, *arguments); 255 274 } 275 276 } -
trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp
r268633 r268848 55 55 namespace IPCTestingAPI { 56 56 57 class JSIPC : public RefCounted<JSIPC> { 57 class JSIPC; 58 59 class JSMessageListener final : public IPC::Connection::MessageObserver { 60 WTF_MAKE_FAST_ALLOCATED; 61 public: 62 enum class Type { Incoming, Outgoing }; 63 64 JSMessageListener(JSIPC&, Type, JSContextRef, JSObjectRef callback); 65 66 private: 67 void willSendMessage(const IPC::Encoder&, OptionSet<IPC::SendOption>) override; 68 void didReceiveMessage(const IPC::Decoder&) override; 69 JSC::JSObject* jsDescriptionFromDecoder(JSC::JSGlobalObject*, IPC::Decoder&); 70 71 WeakPtr<JSIPC> m_jsIPC; 72 Type m_type; 73 JSContextRef m_context; 74 JSObjectRef m_callback; 75 }; 76 77 class JSIPC : public RefCounted<JSIPC>, public CanMakeWeakPtr<JSIPC> { 58 78 public: 59 79 static Ref<JSIPC> create(WebPage& webPage, WebFrame& webFrame) … … 79 99 static const JSStaticValue* staticValues(); 80 100 101 static void addMessageListener(JSMessageListener::Type, JSContextRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); 102 static JSValueRef addIncomingMessageListener(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); 103 static JSValueRef addOutgoingMessageListener(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); 104 81 105 static JSValueRef sendMessage(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); 82 106 static JSValueRef sendSyncMessage(JSContextRef, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); … … 93 117 WeakPtr<WebPage> m_webPage; 94 118 WeakPtr<WebFrame> m_webFrame; 119 Vector<UniqueRef<JSMessageListener>> m_messageListeners; 95 120 }; 96 121 … … 136 161 { 137 162 static const JSStaticFunction functions[] = { 163 { "addIncomingMessageListener", addIncomingMessageListener, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 164 { "addOutgoingMessageListener", addOutgoingMessageListener, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 138 165 { "sendMessage", sendMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 139 166 { "sendSyncMessage", sendSyncMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, … … 170 197 } 171 198 199 static JSValueRef createTypeError(JSContextRef context, const String& message) 200 { 201 JSC::JSLockHolder lock(toJS(context)->vm()); 202 return toRef(JSC::createTypeError(toJS(context), message)); 203 } 204 172 205 static RefPtr<IPC::Connection> processTargetFromArgument(JSC::JSGlobalObject* globalObject, JSValueRef valueRef, JSValueRef* exception) 173 206 { … … 190 223 } 191 224 225 void JSIPC::addMessageListener(JSMessageListener::Type type, JSContextRef context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 226 { 227 auto* globalObject = toJS(context); 228 JSC::JSLockHolder lock(globalObject->vm()); 229 auto jsIPC = makeRefPtr(toWrapped(context, thisObject)); 230 if (!jsIPC) { 231 *exception = createTypeError(context, "Wrong type"_s); 232 return; 233 } 234 235 if (argumentCount < 1) { 236 *exception = createTypeError(context, "Must specify the target process as the first argument"_s); 237 return; 238 } 239 240 auto connection = processTargetFromArgument(globalObject, arguments[0], exception); 241 if (!connection) 242 return; 243 244 std::unique_ptr<JSMessageListener> listener; 245 if (argumentCount >= 2 && JSValueIsObject(context, arguments[1])) { 246 auto listenerObjectRef = JSValueToObject(context, arguments[1], exception); 247 if (JSObjectIsFunction(context, listenerObjectRef)) 248 listener = makeUnique<JSMessageListener>(*jsIPC, type, context, listenerObjectRef); 249 } 250 251 if (!listener) { 252 *exception = createTypeError(context, "Must specify a callback function as the second argument"_s); 253 return; 254 } 255 256 connection->addMessageObserver(*listener); 257 jsIPC->m_messageListeners.append(makeUniqueRefFromNonNullUniquePtr(WTFMove(listener))); 258 } 259 260 JSValueRef JSIPC::addIncomingMessageListener(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 261 { 262 addMessageListener(JSMessageListener::Type::Incoming, context, thisObject, argumentCount, arguments, exception); 263 return JSValueMakeUndefined(context); 264 } 265 266 JSValueRef JSIPC::addOutgoingMessageListener(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 267 { 268 addMessageListener(JSMessageListener::Type::Outgoing, context, thisObject, argumentCount, arguments, exception); 269 return JSValueMakeUndefined(context); 270 } 271 192 272 static Optional<uint64_t> destinationIDFromArgument(JSC::JSGlobalObject* globalObject, JSValueRef valueRef, JSValueRef* exception) 193 273 { … … 234 314 encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(buffer), bufferSize, 1); 235 315 return true; 236 }237 238 static JSValueRef createTypeError(JSContextRef context, const String& message)239 {240 JSC::JSLockHolder lock(toJS(context)->vm());241 return toRef(JSC::createTypeError(toJS(context), message));242 316 } 243 317 … … 805 879 } 806 880 881 JSMessageListener::JSMessageListener(JSIPC& jsIPC, Type type, JSContextRef context, JSObjectRef callback) 882 : m_jsIPC(makeWeakPtr(jsIPC)) 883 , m_type(type) 884 , m_context(context) 885 , m_callback(callback) 886 { 887 auto* globalObject = toJS(context); 888 auto& vm = globalObject->vm(); 889 JSC::JSLockHolder lock(vm); 890 891 auto catchScope = DECLARE_CATCH_SCOPE(vm); 892 893 // We can't retain the global context here as that would cause a leak 894 // since this object is supposed to live as long as the global object is alive. 895 JSC::PrivateName uniquePrivateName; 896 globalObject->putDirect(vm, uniquePrivateName, toJS(globalObject, callback)); 897 } 898 899 void JSMessageListener::didReceiveMessage(const IPC::Decoder& decoder) 900 { 901 if (m_type != Type::Incoming) 902 return; 903 904 RELEASE_ASSERT(m_jsIPC); 905 auto protectOwnerOfThis = makeRef(*m_jsIPC); 906 auto* globalObject = toJS(m_context); 907 JSC::JSLockHolder lock(globalObject->vm()); 908 909 auto mutableDecoder = IPC::Decoder::create(decoder.buffer(), decoder.length(), nullptr, { }); 910 auto* description = jsDescriptionFromDecoder(globalObject, *mutableDecoder); 911 912 JSValueRef arguments[] = { description ? toRef(globalObject, description) : JSValueMakeUndefined(m_context) }; 913 JSObjectCallAsFunction(m_context, m_callback, m_callback, std::size(arguments), arguments, nullptr); 914 } 915 916 void JSMessageListener::willSendMessage(const IPC::Encoder& encoder, OptionSet<IPC::SendOption>) 917 { 918 if (m_type != Type::Outgoing) 919 return; 920 921 RELEASE_ASSERT(m_jsIPC); 922 auto protectOwnerOfThis = makeRef(*m_jsIPC); 923 auto* globalObject = toJS(m_context); 924 JSC::JSLockHolder lock(globalObject->vm()); 925 926 auto decoder = IPC::Decoder::create(encoder.buffer(), encoder.bufferSize(), nullptr, { }); 927 auto* description = jsDescriptionFromDecoder(globalObject, *decoder); 928 929 JSValueRef arguments[] = { description ? toRef(globalObject, description) : JSValueMakeUndefined(m_context) }; 930 JSObjectCallAsFunction(m_context, m_callback, m_callback, WTF_ARRAY_LENGTH(arguments), arguments, nullptr); 931 } 932 933 JSC::JSObject* JSMessageListener::jsDescriptionFromDecoder(JSC::JSGlobalObject* globalObject, IPC::Decoder& decoder) 934 { 935 auto& vm = globalObject->vm(); 936 auto scope = DECLARE_CATCH_SCOPE(vm); 937 938 auto* jsResult = constructEmptyObject(globalObject, globalObject->objectPrototype()); 939 RETURN_IF_EXCEPTION(scope, nullptr); 940 941 jsResult->putDirect(vm, JSC::Identifier::fromString(vm, "name"), JSC::JSValue(static_cast<unsigned>(decoder.messageName()))); 942 RETURN_IF_EXCEPTION(scope, nullptr); 943 944 jsResult->putDirect(vm, JSC::Identifier::fromString(vm, "description"), JSC::jsString(vm, IPC::description(decoder.messageName()))); 945 RETURN_IF_EXCEPTION(scope, nullptr); 946 947 jsResult->putDirect(vm, JSC::Identifier::fromString(vm, "destinationID"), JSC::JSValue(decoder.destinationID())); 948 RETURN_IF_EXCEPTION(scope, nullptr); 949 950 if (decoder.isSyncMessage()) { 951 if (uint64_t syncRequestID = 0; decoder.decode(syncRequestID)) { 952 jsResult->putDirect(vm, JSC::Identifier::fromString(vm, "syncRequestID"), JSC::JSValue(syncRequestID)); 953 RETURN_IF_EXCEPTION(scope, nullptr); 954 } 955 } else if (messageReplyArgumentDescriptions(decoder.messageName())) { 956 if (uint64_t listenerID = 0; decoder.decode(listenerID)) { 957 jsResult->putDirect(vm, JSC::Identifier::fromString(vm, "listenerID"), JSC::JSValue(listenerID)); 958 RETURN_IF_EXCEPTION(scope, nullptr); 959 } 960 } 961 962 auto arrayBuffer = JSC::ArrayBuffer::create(decoder.buffer(), decoder.length()); 963 if (auto* structure = globalObject->arrayBufferStructure(arrayBuffer->sharingMode())) { 964 if (auto* jsArrayBuffer = JSC::JSArrayBuffer::create(vm, structure, WTFMove(arrayBuffer))) { 965 jsResult->putDirect(vm, JSC::Identifier::fromString(vm, "buffer"), jsArrayBuffer); 966 RETURN_IF_EXCEPTION(scope, nullptr); 967 } 968 } 969 970 auto jsReplyArguments = jsValueForArguments(globalObject, decoder.messageName(), decoder); 971 if (jsReplyArguments) { 972 jsResult->putDirect(vm, vm.propertyNames->arguments, jsReplyArguments->isEmpty() ? JSC::jsNull() : *jsReplyArguments); 973 RETURN_IF_EXCEPTION(scope, nullptr); 974 } 975 976 return jsResult; 977 } 978 807 979 void inject(WebPage& webPage, WebFrame& webFrame, WebCore::DOMWrapperWorld& world) 808 980 { -
trunk/Tools/ChangeLog
r268844 r268848 1 2020-10-21 Ryosuke Niwa <rniwa@webkit.org> 2 3 IPC testing API should have the capability to observe messages being sent and received 4 https://bugs.webkit.org/show_bug.cgi?id=217870 5 6 Reviewed by Darin Adler. 7 8 Added tests to intercept IPC messages sent and received by WebContent process. 9 10 * TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm: 11 (IPCTestingAPI.CanInterceptAlert): 12 (IPCTestingAPI.CanInterceptHasStorageAccess): 13 (IPCTestingAPI.CanInterceptFindString): 14 1 15 2020-10-21 Jonathan Bedard <jbedard@apple.com> 2 16 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm
r268633 r268848 209 209 } 210 210 211 TEST(IPCTestingAPI, CanInterceptAlert) 212 { 213 auto webView = createWebViewWithIPCTestingAPI(); 214 215 auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]); 216 [webView setUIDelegate:delegate.get()]; 217 218 done = false; 219 [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>messages = []; IPC.addOutgoingMessageListener('UI', (message) => messages.push(message)); alert('ok');</script>"]; 220 TestWebKitAPI::Util::run(&done); 221 222 EXPECT_STREQ([alertMessage UTF8String], "ok"); 223 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"messages = messages.filter((message) => message.name == IPC.messages.WebPageProxy_RunJavaScriptAlert.name); messages.length"].UTF8String, "1"); 224 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"messages[0].description"].UTF8String, "WebPageProxy_RunJavaScriptAlert"); 225 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"messages[0].arguments.length"].intValue, 3); 226 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"typeof(messages[0].syncRequestID)"].UTF8String, "number"); 227 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"messages[0].destinationID"].intValue, 228 [webView stringByEvaluatingJavaScript:@"IPC.webPageProxyID.toString()"].intValue); 229 } 230 231 #if ENABLE(RESOURCE_LOAD_STATISTICS) 232 TEST(IPCTestingAPI, CanInterceptHasStorageAccess) 233 { 234 auto webView = createWebViewWithIPCTestingAPI(); 235 236 auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]); 237 [webView setUIDelegate:delegate.get()]; 238 239 done = false; 240 promptResult = @"foo"; 241 [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>let targetMessage = {}; const messageName = IPC.messages.NetworkConnectionToWebProcess_HasStorageAccess.name;" 242 "IPC.addOutgoingMessageListener('Networking', (currentMessage) => { if (currentMessage.name == messageName) targetMessage = currentMessage; });" 243 "IPC.sendMessage('Networking', 0, messageName, [{type: 'RegistrableDomain', value: 'https://ipctestingapi.com'}, {type: 'RegistrableDomain', value: 'https://webkit.org'}," 244 "{type: 'uint64_t', value: IPC.frameID}, {type: 'uint64_t', value: IPC.pageID}]).then((result) => alert(JSON.stringify(result.arguments)));</script>"]; 245 TestWebKitAPI::Util::run(&done); 246 247 EXPECT_STREQ([alertMessage UTF8String], "[{\"type\":\"bool\",\"value\":false}]"); 248 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"targetMessage.description"].UTF8String, "NetworkConnectionToWebProcess_HasStorageAccess"); 249 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"targetMessage.arguments.length"].intValue, 4); 250 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"targetMessage.arguments[0].type"].UTF8String, "RegistrableDomain"); 251 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"targetMessage.arguments[0].value"].UTF8String, "ipctestingapi.com"); 252 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"targetMessage.arguments[1].type"].UTF8String, "RegistrableDomain"); 253 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"targetMessage.arguments[1].value"].UTF8String, "webkit.org"); 254 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"targetMessage.arguments[2].type"].UTF8String, "uint64_t"); 255 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"targetMessage.arguments[2].value"].UTF8String, [webView stringByEvaluatingJavaScript:@"IPC.frameID.toString()"].UTF8String); 256 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"targetMessage.arguments[3].type"].UTF8String, "uint64_t"); 257 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"targetMessage.arguments[3].value"].intValue, [webView stringByEvaluatingJavaScript:@"IPC.pageID.toString()"].intValue); 258 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"typeof(targetMessage.syncRequestID)"].UTF8String, "undefined"); 259 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"targetMessage.destinationID"].intValue, 0); 260 } 211 261 #endif 262 263 TEST(IPCTestingAPI, CanInterceptFindString) 264 { 265 auto webView = createWebViewWithIPCTestingAPI(); 266 267 auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]); 268 [webView setUIDelegate:delegate.get()]; 269 270 [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><body><p>hello</p><script>messages = []; IPC.addIncomingMessageListener('UI', (message) => messages.push(message));</script>"]; 271 272 done = false; 273 auto findConfiguration = adoptNS([[WKFindConfiguration alloc] init]); 274 [webView findString:@"hello" withConfiguration:findConfiguration.get() completionHandler:^(WKFindResult *result) { 275 EXPECT_TRUE(result.matchFound); 276 EXPECT_TRUE([webView selectionRangeHasStartOffset:0 endOffset:5]); 277 done = true; 278 }]; 279 TestWebKitAPI::Util::run(&done); 280 281 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"messages = messages.filter((message) => message.name == IPC.messages.WebPage_FindString.name); messages.length"].UTF8String, "1"); 282 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"messages[0].description"].UTF8String, "WebPage_FindString"); 283 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"args = messages[0].arguments; args.length"].intValue, 3); 284 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"args[0].type"].UTF8String, "String"); 285 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"args[0].value"].UTF8String, "hello"); 286 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"args[1].type"].UTF8String, "uint16_t"); 287 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"args[1].value"].intValue, 0x11); 288 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"args[1].isOptionSet"].boolValue, YES); 289 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"args[2].type"].UTF8String, "uint32_t"); 290 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"args[2].value"].intValue, 1); 291 EXPECT_STREQ([webView stringByEvaluatingJavaScript:@"typeof(messages[0].syncRequestID)"].UTF8String, "undefined"); 292 EXPECT_EQ([webView stringByEvaluatingJavaScript:@"messages[0].destinationID"].intValue, 293 [webView stringByEvaluatingJavaScript:@"IPC.webPageProxyID.toString()"].intValue); 294 } 295 296 #endif
Note:
See TracChangeset
for help on using the changeset viewer.