Changeset 268431 in webkit
- Timestamp:
- Oct 13, 2020 4:20:54 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/CMakeLists.txt
r268342 r268431 429 429 add_custom_command( 430 430 OUTPUT 431 ${WebKit_DERIVED_SOURCES_DIR}/MessageArgumentDescriptions.cpp 431 432 ${WebKit_DERIVED_SOURCES_DIR}/MessageNames.cpp 432 433 ${WebKit_DERIVED_SOURCES_DIR}/MessageNames.h -
trunk/Source/WebKit/ChangeLog
r268428 r268431 1 2020-10-12 Ryosuke Niwa <rniwa@webkit.org> 2 3 IPC testing JS API should expose a reply and describe the list of arguments for each message 4 https://bugs.webkit.org/show_bug.cgi?id=217565 5 6 Reviewed by Geoffrey Garen. 7 8 This patch makes IPC.sendMessage and IPC.sendSyncMessage decode the reply. IPC.sendSyncMessage now returns 9 a dictionary with two keys: "buffer" and "arguments", the first of which returns ArrayBuffer of the decoded 10 message reply and the second of which is an array of decoded arguments where there was an appropriate JS 11 binding code existed for the argument type. IPC.sendMessage now returns a Promise which can either resolve 12 with the same dictionary as IPC.sendSyncMessage or reject when the decoding fails. 13 14 In addition, this patch exposes a dictionary describing each IPC message argument's type and parameter name. 15 16 In order to add these two functionalities, this patch adds a new step in generate-message-receiver.py to 17 generate MessageArgumentDescriptions.cpp, which contains functions which know how to decode arguments of 18 any IPC message and create a JS dictionary describing it as well as functions that return descriptions of 19 arguments or reply arguments. 20 21 Finally, this patch adds encoders for a few types found to be very common after r268239 had been landed. 22 23 Tests: TestWebKitAPI.IPCTestingAPI.DecodesReplyArgumentsForPrompt 24 TestWebKitAPI.IPCTestingAPI.DecodesReplyArgumentsForAsyncMessage 25 TestWebKitAPI.IPCTestingAPI.DescribesArguments 26 27 * CMakeLists.txt: 28 * DerivedSources-output.xcfilelist: 29 * DerivedSources.make: 30 * Platform/IPC/Decoder.h: 31 (IPC::Decoder::buffer const): 32 * Platform/IPC/JSIPCBinding.h: Added. 33 (jsValueForDecodedArgumentValue): Added. A template function to construct a JS value for a given C++ value. 34 (jsValueForDecodedNumericArgumentValue): Added. A helper for constructing a JS value for numeric values. 35 (jsValueForDecodedArgumentRect): Added. Ditto for IntRect and FloatRect. 36 (DecodedArgumentJSValueConverter): Added. A helper class to construct JS values for a tuple of values using 37 partial template specializations. 38 (DecodedArgumentJSValueConverter::convert): Added. 39 (jsValueForArgumentTuple): Added. A helper to construct a JS array for the decoded IPC arguments. 40 (jsValueForDecodedArguments): Added. 41 * Platform/IPC/MessageArgumentDescriptions.h: Added. 42 (IPC::ArgumentDescription): Added. 43 * Scripts/generate-message-receiver.py: 44 (main): Generate MessageArgumentDescriptions.cpp. 45 * Scripts/webkit/messages.py: 46 (headers_for_type): Removed the special case for PaymentMethodUpdate now that it's in its own header. Also 47 added made webrtc::WebKitEncodedFrameInfo include LibWebRTCEnumTraits.h as it uses webrtc::VideoFrameType. 48 (collect_header_conditions_for_receiver): Extracted from generate_message_handler. 49 (generate_header_includes_from_conditions): Ditto. 50 (generate_message_handler): 51 (generate_js_value_conversion_function): Added. 52 (generate_js_argument_descriptions): Added. 53 (generate_message_argument_description_implementation): Added. 54 * Shared/ApplePay/ApplePayPaymentSetupFeaturesWebKit.h: Fixed a bug that we were not forward declaring NSArray. 55 * SourcesCocoa.txt: Added MessageArgumentDescriptions.cpp as a non-unified cpp file as its size is around 1MB. 56 * WebKit.xcodeproj/project.pbxproj: 57 * WebProcess/WebPage/IPCTestingAPI.cpp: 58 (WebKit::IPCTestingAPI::JSIPC::staticValues): Added the session ID and page ID as static variables. 59 (WebKit::IPCTestingAPI::encodePointType): Added. 60 (WebKit::IPCTestingAPI::encodeRectType): Fixed the bug was that this code wasn't checking for any exceptions. 61 (WebKit::IPCTestingAPI::encodeNumericType): Renamed from encodeIntegralType since this function is now used 62 to encode double and float, not just integral types. 63 (WebKit::IPCTestingAPI::encodeArgument): Added the support for IntPoint, FloatPoint, URL, RegistrableDomain, 64 double, and float all of which turned out to be in the top 20 most common types. 65 (WebKit::IPCTestingAPI::jsResultFromReplyDecoder): Added. 66 (WebKit::IPCTestingAPI::JSIPC::sendMessage): Added the code to return Promise when there is a reply and resolve 67 it with the JS object describing the decoded argument. We use messageReplyArgumentDescriptions to figure out 68 whether there is a reply or not. 69 (WebKit::IPCTestingAPI::JSIPC::sendSyncMessage): Decode the reply and return a JS object which describes it. 70 (WebKit::IPCTestingAPI::JSIPC::frameID): Renamed from frameIdentifier to be consistent. 71 (WebKit::IPCTestingAPI::JSIPC::pageID): Added. 72 (WebKit::IPCTestingAPI::JSIPC::sessionID): Added. 73 (WebKit::IPCTestingAPI::createJSArrayForArgumentDescriptions): Added. 74 (WebKit::IPCTestingAPI::JSIPC::messages): Added the code to generate descriptions for arguments. 75 1 76 2020-10-13 Ellie Epskamp-Hunt <eepskamphunt@apple.com> 2 77 -
trunk/Source/WebKit/DerivedSources-output.xcfilelist
r268342 r268431 69 69 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MediaPlayerPrivateRemoteMessages.h 70 70 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MediaPlayerPrivateRemoteMessagesReplies.h 71 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MessageArgumentDescriptions.cpp 71 72 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MessageNames.cpp 72 73 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MessageNames.h -
trunk/Source/WebKit/DerivedSources.make
r268342 r268431 258 258 MESSAGE_REPLIES_FILES := $(addsuffix MessagesReplies.h,$(notdir $(MESSAGE_RECEIVERS))) 259 259 260 GENERATED_MESSAGES_FILES := $(MESSAGE_RECEIVER_FILES) $(MESSAGES_FILES) $(MESSAGE_REPLIES_FILES) MessageNames.h MessageNames.cpp 260 GENERATED_MESSAGES_FILES := $(MESSAGE_RECEIVER_FILES) $(MESSAGES_FILES) $(MESSAGE_REPLIES_FILES) MessageNames.h MessageNames.cpp MessageArgumentDescriptions.cpp 261 261 GENERATED_MESSAGES_FILES_AS_PATTERNS := $(subst .,%,$(GENERATED_MESSAGES_FILES)) 262 262 -
trunk/Source/WebKit/Platform/IPC/Decoder.h
r263208 r268431 73 73 static std::unique_ptr<Decoder> unwrapForTesting(Decoder&); 74 74 75 const uint8_t* buffer() const { return m_buffer; } 75 76 size_t length() const { return m_bufferEnd - m_buffer; } 76 77 -
trunk/Source/WebKit/Scripts/generate-message-receiver.py
r261461 r268431 35 35 first_arg = True 36 36 second_arg = False 37 receiver_header_files = [] 37 38 for parameter in argv: 38 39 if first_arg: … … 54 55 implementation_output.write(webkit.messages.generate_message_handler(receiver)) 55 56 56 with open('%sMessages.h' % receiver_name, "w+") as header_output: 57 receiver_message_header = '%sMessages.h' % receiver_name 58 receiver_header_files.append(receiver_message_header) 59 with open(receiver_message_header, "w+") as header_output: 57 60 header_output.write(webkit.messages.generate_messages_header(receiver)) 58 61 … … 66 69 message_names_implementation_output.write(webkit.messages.generate_message_names_implementation(receivers)) 67 70 71 with open('MessageArgumentDescriptions.cpp', "w+") as message_descriptions_implementation_output: 72 message_descriptions_implementation_output.write(webkit.messages.generate_message_argument_description_implementation(receivers, receiver_header_files)) 73 68 74 return 0 69 75 -
trunk/Source/WebKit/Scripts/webkit/messages.py
r268372 r268431 624 624 'WebCore::PasteboardWebContent': ['<WebCore/Pasteboard.h>'], 625 625 'WebCore::PaymentAuthorizationResult': ['<WebCore/ApplePaySessionPaymentRequest.h>'], 626 'WebCore::PaymentMethodUpdate': ['<WebCore/ApplePaySessionPaymentRequest.h>'],627 626 'WebCore::PlatformTextTrackData': ['<WebCore/PlatformTextTrack.h>'], 628 627 'WebCore::PluginInfo': ['<WebCore/PluginData.h>'], … … 688 687 'struct WebKit::WebUserStyleSheetData': ['"WebUserContentControllerDataTypes.h"'], 689 688 'struct WebKit::WebScriptMessageHandlerData': ['"WebUserContentControllerDataTypes.h"'], 690 'webrtc::WebKitEncodedFrameInfo': ['<webrtc/sdk/WebKit/WebKitEncoder.h>' ],689 'webrtc::WebKitEncodedFrameInfo': ['<webrtc/sdk/WebKit/WebKitEncoder.h>', '<WebCore/LibWebRTCEnumTraits.h>'], 691 690 'webrtc::WebKitRTPFragmentationHeader': ['<webrtc/sdk/WebKit/WebKitEncoder.h>'], 692 691 } … … 715 714 716 715 717 def generate_message_handler(receiver): 718 header_conditions = { 719 '"%s"' % messages_header_filename(receiver): [None], 720 '"HandleMessage.h"': [None], 721 '"Decoder.h"': [None], 722 } 723 716 def collect_header_conditions_for_receiver(receiver, header_conditions): 724 717 type_conditions = {} 725 718 for parameter in receiver.iterparameters(): … … 764 757 header_conditions[header].append(message.condition) 765 758 766 result = [] 767 768 result.append(_license_header) 769 result.append('#include "config.h"\n') 770 result.append('\n') 771 772 if receiver.condition: 773 result.append('#if %s\n\n' % receiver.condition) 774 775 result.append('#include "%s.h"\n\n' % receiver.name) 759 return header_conditions 760 761 762 def generate_header_includes_from_conditions(header_conditions): 763 result = [] 776 764 for header in sorted(header_conditions): 777 765 if header_conditions[header] and not None in header_conditions[header]: … … 781 769 else: 782 770 result += ['#include %s\n' % header] 771 return result 772 773 774 def generate_message_handler(receiver): 775 header_conditions = { 776 '"%s"' % messages_header_filename(receiver): [None], 777 '"HandleMessage.h"': [None], 778 '"Decoder.h"': [None], 779 } 780 781 collect_header_conditions_for_receiver(receiver, header_conditions) 782 783 result = [] 784 785 result.append(_license_header) 786 result.append('#include "config.h"\n') 787 result.append('\n') 788 789 if receiver.condition: 790 result.append('#if %s\n\n' % receiver.condition) 791 792 result.append('#include "%s.h"\n\n' % receiver.name) 793 result += generate_header_includes_from_conditions(header_conditions) 783 794 result.append('\n') 784 795 … … 1045 1056 result.append('} // namespace IPC\n') 1046 1057 return ''.join(result) 1058 1059 1060 def generate_js_value_conversion_function(result, receivers, function_name, argument_type, predicate=lambda message: True): 1061 result.append('Optional<JSC::JSValue> %s(JSC::JSGlobalObject* globalObject, MessageName name, Decoder& decoder)\n' % function_name) 1062 result.append('{\n') 1063 result.append(' switch (name) {\n') 1064 for receiver in receivers: 1065 if receiver.condition: 1066 result.append('#if %s\n' % receiver.condition) 1067 prevision_message_condition = None 1068 for message in receiver.messages: 1069 if not predicate(message): 1070 continue 1071 if prevision_message_condition != message.condition: 1072 if prevision_message_condition: 1073 result.append('#endif\n') 1074 if message.condition: 1075 result.append('#if %s\n' % message.condition) 1076 prevision_message_condition = message.condition 1077 result.append(' case MessageName::%s_%s:\n' % (receiver.name, message.name)) 1078 result.append(' return jsValueForDecodedArguments<Messages::%s::%s::%s>(globalObject, decoder);\n' % (receiver.name, message.name, argument_type)) 1079 if prevision_message_condition: 1080 result.append('#endif\n') 1081 if receiver.condition: 1082 result.append('#endif\n') 1083 result.append(' default:\n') 1084 result.append(' break;\n') 1085 result.append(' }\n') 1086 result.append(' return WTF::nullopt;\n') 1087 result.append('}\n') 1088 1089 1090 def generate_js_argument_descriptions(receivers, function_name, arguments_from_message): 1091 result = [] 1092 result.append('Optional<Vector<ArgumentDescription>> %s(MessageName name)\n' % function_name) 1093 result.append('{\n') 1094 result.append(' switch (name) {\n') 1095 for receiver in receivers: 1096 if receiver.condition: 1097 result.append('#if %s\n' % receiver.condition) 1098 prevision_message_condition = None 1099 for message in receiver.messages: 1100 argument_list = arguments_from_message(message) 1101 if argument_list is None: 1102 continue 1103 if prevision_message_condition != message.condition: 1104 if prevision_message_condition: 1105 result.append('#endif\n') 1106 if message.condition: 1107 result.append('#if %s\n' % message.condition) 1108 prevision_message_condition = message.condition 1109 result.append(' case MessageName::%s_%s:\n' % (receiver.name, message.name)) 1110 1111 if not len(argument_list): 1112 result.append(' return Vector<ArgumentDescription> { };\n') 1113 continue 1114 1115 result.append(' return Vector<ArgumentDescription> {\n') 1116 for argument in argument_list: 1117 argument_type = argument.type 1118 enum_type = None 1119 is_optional = False 1120 if argument.kind.startswith('enum:'): 1121 enum_type = '"%s"' % argument_type 1122 argument_type = argument.kind[5:] 1123 if argument_type.startswith('Optional<') and argument_type.endswith('>'): 1124 argument_type = argument_type[9:-1] 1125 is_optional = True 1126 result.append(' {"%s", "%s", %s, %s},\n' % (argument.name, argument_type, enum_type or 'nullptr', 'true' if is_optional else 'false')) 1127 result.append(' };\n') 1128 if prevision_message_condition: 1129 result.append('#endif\n') 1130 if receiver.condition: 1131 result.append('#endif\n') 1132 result.append(' default:\n') 1133 result.append(' break;\n') 1134 result.append(' }\n') 1135 result.append(' return WTF::nullopt;\n') 1136 result.append('}\n') 1137 return result 1138 1139 1140 def generate_message_argument_description_implementation(receivers, receiver_headers): 1141 header_conditions = { 1142 '"JSIPCBinding.h"': [None] 1143 } 1144 for receiver in receivers: 1145 header_conditions['"%s"' % messages_header_filename(receiver)] = [None] 1146 collect_header_conditions_for_receiver(receiver, header_conditions) 1147 1148 result = [] 1149 result.append(_license_header) 1150 result.append('#include "config.h"\n') 1151 result.append('#include "MessageArgumentDescriptions.h"\n') 1152 result.append('\n') 1153 result.append('#if ENABLE(IPC_TESTING_API)\n') 1154 result.append('\n') 1155 result += generate_header_includes_from_conditions(header_conditions) 1156 result.append('\n') 1157 1158 for header in receiver_headers: 1159 result.append('#include "%s"\n' % (header)) 1160 1161 result.append('\n') 1162 result.append('namespace IPC {\n') 1163 result.append('\n') 1164 1165 generate_js_value_conversion_function(result, receivers, 'jsValueForArguments', 'Arguments') 1166 1167 result.append('\n') 1168 1169 generate_js_value_conversion_function(result, receivers, 'jsValueForReplyArguments', 'ReplyArguments', lambda message: message.reply_parameters is not None and (message.has_attribute(SYNCHRONOUS_ATTRIBUTE) or message.has_attribute(ASYNC_ATTRIBUTE))) 1170 1171 result.append('\n') 1172 1173 result += generate_js_argument_descriptions(receivers, 'messageArgumentDescriptions', lambda message: message.parameters) 1174 1175 result.append('\n') 1176 1177 result += generate_js_argument_descriptions(receivers, 'messageReplyArgumentDescriptions', lambda message: message.reply_parameters if message.has_attribute(SYNCHRONOUS_ATTRIBUTE) or message.has_attribute(ASYNC_ATTRIBUTE) else None) 1178 1179 result.append('\n') 1180 1181 result.append('} // namespace WebKit\n') 1182 result.append('\n') 1183 result.append('#endif\n') 1184 return ''.join(result) -
trunk/Source/WebKit/Shared/ApplePay/ApplePayPaymentSetupFeaturesWebKit.h
r262714 r268431 28 28 #if ENABLE(APPLE_PAY) 29 29 30 OBJC_CLASS NSArray; 30 31 OBJC_CLASS PKPaymentSetupFeature; 31 32 -
trunk/Source/WebKit/SourcesCocoa.txt
r268384 r268431 660 660 LibWebRTCCodecsProxyMessageReceiver.cpp 661 661 LibWebRTCCodecsMessageReceiver.cpp 662 MessageArgumentDescriptions.cpp @no-unify 662 663 MessageNames.cpp 663 664 RemoteAudioDestinationManagerMessageReceiver.cpp -
trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj
r268384 r268431 1425 1425 9B1229CE23FF25F2008CA751 /* RemoteAudioDestinationManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B1229CC23FF25F2008CA751 /* RemoteAudioDestinationManager.cpp */; }; 1426 1426 9B1229D223FF2BCC008CA751 /* RemoteAudioDestinationIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B1229D023FF2A5E008CA751 /* RemoteAudioDestinationIdentifier.h */; }; 1427 9B47908D25314D8300EC11AB /* MessageArgumentDescriptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B47908C25314D8300EC11AB /* MessageArgumentDescriptions.h */; }; 1428 9B47908F253151CC00EC11AB /* JSIPCBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B47908E253151CC00EC11AB /* JSIPCBinding.h */; }; 1429 9B4790912531563200EC11AB /* MessageArgumentDescriptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B4790902531563200EC11AB /* MessageArgumentDescriptions.cpp */; }; 1427 1430 9B5499AD2362A6F900DF8BA5 /* _WKTextManipulationConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5499AC2362A6F600DF8BA5 /* _WKTextManipulationConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1428 1431 9B5499B22362A7EC00DF8BA5 /* _WKTextManipulationExclusionRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5499B02362A7EC00DF8BA5 /* _WKTextManipulationExclusionRule.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 4530 4533 9B1229CF23FF2814008CA751 /* RemoteAudioDestinationManager.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = RemoteAudioDestinationManager.messages.in; sourceTree = "<group>"; }; 4531 4534 9B1229D023FF2A5E008CA751 /* RemoteAudioDestinationIdentifier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteAudioDestinationIdentifier.h; sourceTree = "<group>"; }; 4535 9B47908C25314D8300EC11AB /* MessageArgumentDescriptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MessageArgumentDescriptions.h; sourceTree = "<group>"; }; 4536 9B47908E253151CC00EC11AB /* JSIPCBinding.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSIPCBinding.h; sourceTree = "<group>"; }; 4537 9B4790902531563200EC11AB /* MessageArgumentDescriptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MessageArgumentDescriptions.cpp; path = MessageArgumentDescriptions.cpp; sourceTree = "<group>"; }; 4532 4538 9B5499AC2362A6F600DF8BA5 /* _WKTextManipulationConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKTextManipulationConfiguration.h; sourceTree = "<group>"; }; 4533 4539 9B5499AE2362A7A700DF8BA5 /* _WKTextManipulationConfiguration.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKTextManipulationConfiguration.mm; sourceTree = "<group>"; }; … … 6464 6470 C0CE72AC1247E78D00BC0EC4 /* HandleMessage.h */, 6465 6471 1C9AF36124134D2300D3EC02 /* ImageDataReference.h */, 6472 9B47908E253151CC00EC11AB /* JSIPCBinding.h */, 6473 9B47908C25314D8300EC11AB /* MessageArgumentDescriptions.h */, 6466 6474 1AC4C82816B876A90069DCCD /* MessageFlags.h */, 6467 6475 1A3EED11161A53D600AEB4F5 /* MessageReceiver.h */, … … 10089 10097 07E19EF923D401F00094FFB4 /* MediaPlayerPrivateRemoteMessages.h */, 10090 10098 07E19EFA23D401F00094FFB4 /* MediaPlayerPrivateRemoteMessagesReplies.h */, 10099 9B4790902531563200EC11AB /* MessageArgumentDescriptions.cpp */, 10091 10100 51DD9F2616367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp */, 10092 10101 51DD9F2716367DA2001578E9 /* NetworkConnectionToWebProcessMessages.h */, … … 10942 10951 C5BCE5DF1C50766A00CDE3FA /* InteractionInformationAtPosition.h in Headers */, 10943 10952 2D4D2C811DF60BF3002EB10C /* InteractionInformationRequest.h in Headers */, 10953 9B47908F253151CC00EC11AB /* JSIPCBinding.h in Headers */, 10944 10954 1AE49A4911FFA8CE0048B464 /* JSNPMethod.h in Headers */, 10945 10955 1AE4987811FF7FAA0048B464 /* JSNPObject.h in Headers */, … … 10978 10988 07E19EFD23D401F10094FFB4 /* MediaPlayerPrivateRemoteMessagesReplies.h in Headers */, 10979 10989 51933DEF1965EB31008AC3EA /* MenuUtilities.h in Headers */, 10990 9B47908D25314D8300EC11AB /* MessageArgumentDescriptions.h in Headers */, 10980 10991 1AC4C82916B876A90069DCCD /* MessageFlags.h in Headers */, 10981 10992 1A3EED12161A53D600AEB4F5 /* MessageReceiver.h in Headers */, … … 12849 12860 2D92A779212B6A6100F493FD /* Logging.cpp in Sources */, 12850 12861 07E19EFB23D401F10094FFB4 /* MediaPlayerPrivateRemoteMessageReceiver.cpp in Sources */, 12862 9B4790912531563200EC11AB /* MessageArgumentDescriptions.cpp in Sources */, 12851 12863 2D92A781212B6A7100F493FD /* MessageReceiverMap.cpp in Sources */, 12852 12864 2D92A782212B6A7100F493FD /* MessageSender.cpp in Sources */, -
trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp
r268239 r268431 32 32 #include "FrameInfoData.h" 33 33 #include "GPUProcessConnection.h" 34 #include "Message Names.h"34 #include "MessageArgumentDescriptions.h" 35 35 #include "NetworkProcessConnection.h" 36 36 #include "WebCoreArgumentCoders.h" … … 84 84 static JSValueRef visitedLinkStoreID(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception); 85 85 static JSValueRef webPageProxyID(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception); 86 static JSValueRef frameIdentifier(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception); 86 static JSValueRef sessionID(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception); 87 static JSValueRef pageID(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception); 88 static JSValueRef frameID(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception); 87 89 static JSValueRef retrieveID(JSContextRef, JSObjectRef thisObject, JSValueRef* exception, const WTF::Function<uint64_t(JSIPC&)>&); 88 90 … … 145 147 static const JSStaticValue values[] = { 146 148 { "visitedLinkStoreID", visitedLinkStoreID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 149 { "frameID", frameID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 150 { "pageID", pageID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 151 { "sessionID", sessionID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 147 152 { "webPageProxyID", webPageProxyID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 148 { "frameIdentifier", frameIdentifier, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },149 153 { "messages", messages, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 150 154 { 0, 0, 0, 0 } … … 238 242 } 239 243 240 template<typename RectType> bool encodeRectType(IPC::Encoder& encoder, JSC::JSGlobalObject* globalObject, JSC::JSObject* jsObject)244 template<typename PointType> bool encodePointType(IPC::Encoder& encoder, JSC::JSGlobalObject* globalObject, JSC::JSObject* jsObject, JSC::CatchScope& scope) 241 245 { 242 246 auto& vm = globalObject->vm(); 243 247 auto jsX = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "x"_s)); 244 if ( !jsX.isNumber())248 if (scope.exception() || !jsX.isNumber()) 245 249 return false; 246 250 auto jsY = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "y"_s)); 247 if (!jsY.isNumber()) 251 if (scope.exception() || !jsY.isNumber()) 252 return false; 253 encoder << PointType(jsX.asNumber(), jsY.asNumber()); 254 return true; 255 } 256 257 template<typename RectType> bool encodeRectType(IPC::Encoder& encoder, JSC::JSGlobalObject* globalObject, JSC::JSObject* jsObject, JSC::CatchScope& scope) 258 { 259 auto& vm = globalObject->vm(); 260 auto jsX = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "x"_s)); 261 if (scope.exception() || !jsX.isNumber()) 262 return false; 263 auto jsY = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "y"_s)); 264 if (scope.exception() || !jsY.isNumber()) 248 265 return false; 249 266 auto jsWidth = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "width"_s)); 250 if ( !jsWidth.isNumber())267 if (scope.exception() || !jsWidth.isNumber()) 251 268 return false; 252 269 auto jsHeight = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "height"_s)); 253 if ( !jsHeight.isNumber())270 if (scope.exception() || !jsHeight.isNumber()) 254 271 return false; 255 272 encoder << RectType(jsX.asNumber(), jsY.asNumber(), jsWidth.asNumber(), jsHeight.asNumber()); … … 257 274 } 258 275 259 template<typename IntegralType> bool encode IntegralType(IPC::Encoder& encoder, JSC::JSValue jsValue)276 template<typename IntegralType> bool encodeNumericType(IPC::Encoder& encoder, JSC::JSValue jsValue) 260 277 { 261 278 if (jsValue.isBigInt()) { … … 341 358 return false; 342 359 360 if (type == "IntPoint") { 361 if (!encodePointType<WebCore::IntPoint>(encoder, globalObject, jsObject, scope)) { 362 *exception = createTypeError(context, "Failed to convert IntPoint"_s); 363 return false; 364 } 365 return true; 366 } 367 368 if (type == "FloatPoint") { 369 if (!encodePointType<WebCore::IntPoint>(encoder, globalObject, jsObject, scope)) { 370 *exception = createTypeError(context, "Failed to convert FloatPoint"_s); 371 return false; 372 } 373 return true; 374 } 375 343 376 if (type == "IntRect") { 344 if (!encodeRectType<WebCore::IntRect>(encoder, globalObject, jsObject )) {377 if (!encodeRectType<WebCore::IntRect>(encoder, globalObject, jsObject, scope)) { 345 378 *exception = createTypeError(context, "Failed to convert IntRect"_s); 346 379 return false; … … 350 383 351 384 if (type == "FloatRect") { 352 if (!encodeRectType<WebCore::FloatRect>(encoder, globalObject, jsObject )) {385 if (!encodeRectType<WebCore::FloatRect>(encoder, globalObject, jsObject, scope)) { 353 386 *exception = createTypeError(context, "Failed to convert FloatRect"_s); 354 387 return false; … … 383 416 } 384 417 418 if (type == "URL") { 419 if (jsValue.isUndefinedOrNull()) { 420 encoder << URL { }; 421 return true; 422 } 423 auto string = jsValue.toWTFString(globalObject); 424 if (scope.exception()) 425 return false; 426 encoder << URL { URL { }, string }; 427 return true; 428 } 429 430 if (type == "RegistrableDomain") { 431 if (jsValue.isUndefinedOrNull()) { 432 encoder << RegistrableDomain { }; 433 return true; 434 } 435 auto string = jsValue.toWTFString(globalObject); 436 if (scope.exception()) 437 return false; 438 encoder << RegistrableDomain { URL { URL { }, string } }; 439 return true; 440 } 441 385 442 if (type == "RGBA") { 386 443 if (!jsValue.isNumber()) { … … 393 450 } 394 451 395 bool integralResult;452 bool numericResult; 396 453 if (type == "bool") 397 integralResult = encodeIntegralType<bool>(encoder, jsValue); 454 numericResult = encodeNumericType<bool>(encoder, jsValue); 455 else if (type == "double") 456 numericResult = encodeNumericType<double>(encoder, jsValue); 457 else if (type == "float") 458 numericResult = encodeNumericType<float>(encoder, jsValue); 398 459 else if (type == "int8_t") 399 integralResult = encodeIntegralType<int8_t>(encoder, jsValue);460 numericResult = encodeNumericType<int8_t>(encoder, jsValue); 400 461 else if (type == "int16_t") 401 integralResult = encodeIntegralType<int16_t>(encoder, jsValue);462 numericResult = encodeNumericType<int16_t>(encoder, jsValue); 402 463 else if (type == "int32_t") 403 integralResult = encodeIntegralType<int32_t>(encoder, jsValue);464 numericResult = encodeNumericType<int32_t>(encoder, jsValue); 404 465 else if (type == "int64_t") 405 integralResult = encodeIntegralType<int64_t>(encoder, jsValue);466 numericResult = encodeNumericType<int64_t>(encoder, jsValue); 406 467 else if (type == "uint8_t") 407 integralResult = encodeIntegralType<uint8_t>(encoder, jsValue);468 numericResult = encodeNumericType<uint8_t>(encoder, jsValue); 408 469 else if (type == "uint16_t") 409 integralResult = encodeIntegralType<uint16_t>(encoder, jsValue);470 numericResult = encodeNumericType<uint16_t>(encoder, jsValue); 410 471 else if (type == "uint32_t") 411 integralResult = encodeIntegralType<uint32_t>(encoder, jsValue);472 numericResult = encodeNumericType<uint32_t>(encoder, jsValue); 412 473 else if (type == "uint64_t") 413 integralResult = encodeIntegralType<uint64_t>(encoder, jsValue);474 numericResult = encodeNumericType<uint64_t>(encoder, jsValue); 414 475 else { 415 476 *exception = createTypeError(context, "Bad type name"_s); 416 477 return false; 417 478 } 418 if (! integralResult) {419 *exception = createTypeError(context, "Failed to encode a n integer"_s);479 if (!numericResult) { 480 *exception = createTypeError(context, "Failed to encode a number"_s); 420 481 return false; 421 482 } 422 483 return true; 484 } 485 486 487 static JSC::JSObject* jsResultFromReplyDecoder(JSC::JSGlobalObject* globalObject, IPC::MessageName messageName, IPC::Decoder& decoder) 488 { 489 auto& vm = globalObject->vm(); 490 auto scope = DECLARE_THROW_SCOPE(vm); 491 492 auto arrayBuffer = JSC::ArrayBuffer::create(decoder.buffer(), decoder.length()); 493 JSC::JSArrayBuffer* jsArrayBuffer = nullptr; 494 if (auto* structure = globalObject->arrayBufferStructure(arrayBuffer->sharingMode())) 495 jsArrayBuffer = JSC::JSArrayBuffer::create(vm, structure, WTFMove(arrayBuffer)); 496 if (!jsArrayBuffer) { 497 throwException(globalObject, scope, JSC::createTypeError(globalObject, "Failed to create the array buffer for the reply"_s)); 498 return nullptr; 499 } 500 501 auto jsReplyArguments = jsValueForReplyArguments(globalObject, messageName, decoder); 502 if (!jsReplyArguments) { 503 throwException(globalObject, scope, JSC::createTypeError(globalObject, "Failed to decode the reply"_s)); 504 return nullptr; 505 } 506 507 if (jsReplyArguments->isEmpty()) { 508 throwException(globalObject, scope, JSC::createTypeError(globalObject, "Failed to convert the reply to an JS array"_s)); 509 return nullptr; 510 } 511 512 auto catchScope = DECLARE_CATCH_SCOPE(vm); 513 JSC::JSObject* jsResult = constructEmptyObject(globalObject, globalObject->objectPrototype()); 514 RETURN_IF_EXCEPTION(catchScope, nullptr); 515 516 jsResult->putDirect(vm, vm.propertyNames->arguments, *jsReplyArguments); 517 RETURN_IF_EXCEPTION(catchScope, nullptr); 518 519 jsResult->putDirect(vm, JSC::Identifier::fromString(vm, "buffer"), jsArrayBuffer); 520 RETURN_IF_EXCEPTION(catchScope, nullptr); 521 522 return jsResult; 423 523 } 424 524 … … 429 529 auto jsIPC = makeRefPtr(toWrapped(context, thisObject)); 430 530 if (!jsIPC) { 431 *exception = toRef(JSC::createTypeError(toJS(context), "Wrong type"_s));531 *exception = createTypeError(context, "Wrong type"_s); 432 532 return JSValueMakeUndefined(context); 433 533 } 434 534 435 535 if (argumentCount < 3) { 436 *exception = toRef(JSC::createTypeError(toJS(context), "Must specify the target process, desination ID, and message ID as the first three arguments"_s));536 *exception = createTypeError(context, "Must specify the target process, desination ID, and message ID as the first three arguments"_s); 437 537 return JSValueMakeUndefined(context); 438 538 } … … 450 550 return JSValueMakeUndefined(context); 451 551 452 auto encoder = makeUnique<IPC::Encoder>(static_cast<IPC::MessageName>(static_cast<uint64_t>(*messageID)), *destinationID); 552 auto messageName = static_cast<IPC::MessageName>(*messageID); 553 auto encoder = makeUnique<IPC::Encoder>(messageName, *destinationID); 554 555 JSValueRef returnValue = JSValueMakeUndefined(context); 556 557 bool hasReply = !!messageReplyArgumentDescriptions(messageName); 558 if (hasReply) { 559 uint64_t listenerID = IPC::nextAsyncReplyHandlerID(); 560 encoder->encode(listenerID); 561 562 JSObjectRef resolve; 563 JSObjectRef reject; 564 ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN 565 returnValue = JSObjectMakeDeferredPromise(context, &resolve, &reject, exception); 566 ALLOW_NEW_API_WITHOUT_GUARDS_END 567 if (!returnValue) 568 return JSValueMakeUndefined(context); 569 570 JSGlobalContextRetain(JSContextGetGlobalContext(context)); 571 JSValueProtect(context, resolve); 572 JSValueProtect(context, reject); 573 IPC::addAsyncReplyHandler(*connection, listenerID, [messageName, context, resolve, reject](IPC::Decoder* replyDecoder) { 574 auto* globalObject = toJS(context); 575 auto& vm = globalObject->vm(); 576 JSC::JSLockHolder lock(vm); 577 578 auto scope = DECLARE_CATCH_SCOPE(vm); 579 auto* jsResult = jsResultFromReplyDecoder(globalObject, messageName, *replyDecoder); 580 if (auto* exception = scope.exception()) { 581 scope.clearException(); 582 JSValueRef arguments[] = { toRef(globalObject, exception) }; 583 JSObjectCallAsFunction(context, reject, reject, 1, arguments, nullptr); 584 } else { 585 JSValueRef arguments[] = { toRef(globalObject, jsResult) }; 586 JSObjectCallAsFunction(context, resolve, resolve, 1, arguments, nullptr); 587 } 588 589 JSValueUnprotect(context, reject); 590 JSValueUnprotect(context, resolve); 591 JSGlobalContextRelease(JSContextGetGlobalContext(context)); 592 }); 593 } 453 594 454 595 if (argumentCount > 3) { … … 461 602 connection->sendMessage(WTFMove(encoder), { }); 462 603 463 return JSValueMakeUndefined(context);604 return returnValue; 464 605 } 465 606 … … 470 611 auto jsIPC = makeRefPtr(toWrapped(context, thisObject)); 471 612 if (!jsIPC) { 472 *exception = toRef(JSC::createTypeError(toJS(context), "Wrong type"_s));613 *exception = createTypeError(context, "Wrong type"_s); 473 614 return JSValueMakeUndefined(context); 474 615 } 475 616 476 617 if (argumentCount < 4) { 477 *exception = toRef(JSC::createTypeError(toJS(context), "Must specify the target process, desination ID, message ID, and timeout as the first four arguments"_s));618 *exception = createTypeError(context, "Must specify the target process, desination ID, and message ID as the first three arguments"_s); 478 619 return JSValueMakeUndefined(context); 479 620 } … … 495 636 auto jsValue = toJS(globalObject, arguments[3]); 496 637 if (!jsValue.isNumber()) { 497 *exception = toRef(JSC::createTypeError(globalObject, "timeout must be a number"_s));638 *exception = createTypeError(context, "Timeout must be a number"_s); 498 639 return JSValueMakeUndefined(context); 499 640 } 500 641 timeout = Seconds { jsValue.asNumber() }; 501 642 } 502 643 503 644 // FIXME: Support the options. 504 645 505 646 uint64_t syncRequestID = 0; 506 auto encoder = connection->createSyncMessageEncoder(static_cast<IPC::MessageName>(static_cast<uint64_t>(*messageID)), *destinationID, syncRequestID); 647 auto messageName = static_cast<IPC::MessageName>(*messageID); 648 auto encoder = connection->createSyncMessageEncoder(messageName, *destinationID, syncRequestID); 507 649 508 650 if (argumentCount > 4) { … … 511 653 } 512 654 513 auto replyDecoder = connection->sendSyncMessage(syncRequestID, WTFMove(encoder), timeout, { }); 514 // FIXME: Decode the reply. 655 if (auto replyDecoder = connection->sendSyncMessage(syncRequestID, WTFMove(encoder), timeout, { })) { 656 auto scope = DECLARE_CATCH_SCOPE(globalObject->vm()); 657 auto* jsResult = jsResultFromReplyDecoder(globalObject, messageName, *replyDecoder); 658 if (scope.exception()) { 659 *exception = toRef(globalObject, scope.exception()); 660 scope.clearException(); 661 return JSValueMakeUndefined(context); 662 } 663 return toRef(globalObject, jsResult); 664 } 515 665 516 666 return JSValueMakeUndefined(context); … … 525 675 } 526 676 677 JSValueRef JSIPC::frameID(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef* exception) 678 { 679 return retrieveID(context, thisObject, exception, [](JSIPC& wrapped) { 680 return wrapped.m_webFrame->frameID().toUInt64(); 681 }); 682 } 683 684 JSValueRef JSIPC::pageID(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef* exception) 685 { 686 return retrieveID(context, thisObject, exception, [](JSIPC& wrapped) { 687 return wrapped.m_webPage->identifier().toUInt64(); 688 }); 689 } 690 691 JSValueRef JSIPC::sessionID(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef* exception) 692 { 693 return retrieveID(context, thisObject, exception, [](JSIPC& wrapped) { 694 return wrapped.m_webPage->sessionID().toUInt64(); 695 }); 696 } 697 527 698 JSValueRef JSIPC::webPageProxyID(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef* exception) 528 699 { … … 532 703 } 533 704 534 JSValueRef JSIPC::frameIdentifier(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef* exception)535 {536 return retrieveID(context, thisObject, exception, [](JSIPC& wrapped) {537 return wrapped.m_webFrame->frameID().toUInt64();538 });539 }540 541 705 JSValueRef JSIPC::retrieveID(JSContextRef context, JSObjectRef thisObject, JSValueRef* exception, const WTF::Function<uint64_t(JSIPC&)>& callback) 542 706 { … … 556 720 } 557 721 722 static JSC::JSValue createJSArrayForArgumentDescriptions(JSC::JSGlobalObject* globalObject, Optional<Vector<IPC::ArgumentDescription>>&& argumentDescriptions) 723 { 724 if (!argumentDescriptions) 725 return JSC::jsNull(); 726 727 auto& vm = globalObject->vm(); 728 auto scope = DECLARE_CATCH_SCOPE(vm); 729 JSC::JSObject* argumentsArray = JSC::constructEmptyArray(globalObject, nullptr); 730 RETURN_IF_EXCEPTION(scope, JSC::jsTDZValue()); 731 732 for (unsigned argumentIndex = 0; argumentIndex < argumentDescriptions->size(); ++argumentIndex) { 733 auto& description = argumentDescriptions->at(argumentIndex); 734 JSC::JSObject* jsDescriptions = constructEmptyObject(globalObject, globalObject->objectPrototype()); 735 RETURN_IF_EXCEPTION(scope, JSC::jsTDZValue()); 736 737 argumentsArray->putDirectIndex(globalObject, argumentIndex, jsDescriptions); 738 RETURN_IF_EXCEPTION(scope, JSC::jsTDZValue()); 739 740 jsDescriptions->putDirect(vm, JSC::Identifier::fromString(vm, "name"), JSC::jsString(vm, String(description.name))); 741 RETURN_IF_EXCEPTION(scope, JSC::jsTDZValue()); 742 743 jsDescriptions->putDirect(vm, JSC::Identifier::fromString(vm, "type"), JSC::jsString(vm, String(description.type))); 744 RETURN_IF_EXCEPTION(scope, JSC::jsTDZValue()); 745 746 jsDescriptions->putDirect(vm, JSC::Identifier::fromString(vm, "optional"), JSC::jsBoolean(description.isOptional)); 747 RETURN_IF_EXCEPTION(scope, JSC::jsTDZValue()); 748 749 if (description.enumName) { 750 jsDescriptions->putDirect(vm, JSC::Identifier::fromString(vm, "enum"), JSC::jsString(vm, String(description.enumName))); 751 RETURN_IF_EXCEPTION(scope, JSC::jsTDZValue()); 752 } 753 } 754 return argumentsArray; 755 } 756 558 757 JSValueRef JSIPC::messages(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef* exception) 559 758 { … … 568 767 } 569 768 769 auto scope = DECLARE_CATCH_SCOPE(vm); 570 770 JSC::JSObject* messagesObject = constructEmptyObject(globalObject, globalObject->objectPrototype()); 771 RETURN_IF_EXCEPTION(scope, JSValueMakeUndefined(context)); 772 571 773 auto nameIdent = JSC::Identifier::fromString(vm, "name"); 774 auto replyArgumentsIdent = JSC::Identifier::fromString(vm, "replyArguments"); 572 775 for (unsigned i = 0; i < static_cast<unsigned>(IPC::MessageName::Last); ++i) { 573 auto * messageName = description(static_cast<IPC::MessageName>(i));776 auto name = static_cast<IPC::MessageName>(i); 574 777 575 778 JSC::JSObject* dictionary = constructEmptyObject(globalObject, globalObject->objectPrototype()); 779 RETURN_IF_EXCEPTION(scope, JSValueMakeUndefined(context)); 780 576 781 dictionary->putDirect(vm, nameIdent, JSC::JSValue(i)); 577 578 // FIXME: Add argument names. 579 580 messagesObject->putDirect(vm, JSC::Identifier::fromString(vm, messageName), dictionary); 782 RETURN_IF_EXCEPTION(scope, JSValueMakeUndefined(context)); 783 784 auto argumentDescriptions = createJSArrayForArgumentDescriptions(globalObject, IPC::messageArgumentDescriptions(name)); 785 if (argumentDescriptions.isEmpty()) 786 return JSValueMakeUndefined(context); 787 dictionary->putDirect(vm, vm.propertyNames->arguments, argumentDescriptions); 788 RETURN_IF_EXCEPTION(scope, JSValueMakeUndefined(context)); 789 790 auto replyArgumentDescriptions = createJSArrayForArgumentDescriptions(globalObject, IPC::messageReplyArgumentDescriptions(name)); 791 if (replyArgumentDescriptions.isEmpty()) 792 return JSValueMakeUndefined(context); 793 dictionary->putDirect(vm, replyArgumentsIdent, replyArgumentDescriptions); 794 RETURN_IF_EXCEPTION(scope, JSValueMakeUndefined(context)); 795 796 messagesObject->putDirect(vm, JSC::Identifier::fromString(vm, description(name)), dictionary); 797 RETURN_IF_EXCEPTION(scope, JSValueMakeUndefined(context)); 581 798 } 582 799 -
trunk/Tools/ChangeLog
r268429 r268431 1 2020-10-12 Ryosuke Niwa <rniwa@webkit.org> 2 3 IPC testing JS API should expose a reply and describe the list of arguments for each message 4 https://bugs.webkit.org/show_bug.cgi?id=217565 5 6 Reviewed by Geoffrey Garen. 7 8 Added tests for decoding replies for sync and async messages and one for argument descriptions. 9 10 * TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm: 11 (-[IPCTestingAPIDelegate webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:]): 12 (-[IPCTestingAPIDelegate _webView:webContentProcessDidTerminateWithReason:]): 13 (IPCTestingAPI.DecodesReplyArgumentsForPrompt): 14 (IPCTestingAPI.DecodesReplyArgumentsForAsyncMessage): 15 (IPCTestingAPI.DescribesArguments): 16 1 17 2020-10-13 Aakash Jain <aakash_jain@apple.com> 2 18 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm
r268239 r268431 35 35 36 36 static bool done = false; 37 static bool didCrash = false; 37 38 static RetainPtr<NSString> alertMessage; 39 static RetainPtr<NSString> promptDefault; 40 static RetainPtr<NSString> promptResult; 38 41 39 @interface IPCTestingAPIDelegate : NSObject <WKUIDelegate >42 @interface IPCTestingAPIDelegate : NSObject <WKUIDelegate, WKNavigationDelegate> 40 43 @end 41 44 … … 47 50 done = true; 48 51 completionHandler(); 52 } 53 54 - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler 55 { 56 promptDefault = defaultText; 57 done = true; 58 completionHandler(promptResult.get()); 59 } 60 61 - (void)_webView:(WKWebView *)webView webContentProcessDidTerminateWithReason:(_WKProcessTerminationReason)reason 62 { 63 didCrash = false; 64 done = true; 49 65 } 50 66 … … 88 104 } 89 105 106 TEST(IPCTestingAPI, DecodesReplyArgumentsForPrompt) 107 { 108 RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 109 for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) { 110 if ([feature.key isEqualToString:@"IPCTestingAPIEnabled"]) { 111 [[configuration preferences] _setEnabled:YES forInternalDebugFeature:feature]; 112 break; 113 } 114 } 115 RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get()]); 116 117 auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]); 118 [webView setUIDelegate:delegate.get()]; 119 120 done = false; 121 promptResult = @"foo"; 122 [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>result = IPC.sendSyncMessage('UI', IPC.webPageProxyID, IPC.messages.WebPageProxy_RunJavaScriptPrompt.name, 100," 123 "[{type: 'uint64_t', value: IPC.frameIdentifier}, {type: 'FrameInfoData'}, {'type': 'String', 'value': 'hi'}, {'type': 'String', 'value': 'bar'}]);</script>"]; 124 TestWebKitAPI::Util::run(&done); 125 126 EXPECT_STREQ([promptDefault UTF8String], "bar"); 127 EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"JSON.stringify(result.arguments)"] UTF8String], "[{\"type\":\"String\",\"value\":\"foo\"}]"); 128 } 129 130 #if ENABLE(RESOURCE_LOAD_STATISTICS) 131 TEST(IPCTestingAPI, DecodesReplyArgumentsForAsyncMessage) 132 { 133 RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 134 for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) { 135 if ([feature.key isEqualToString:@"IPCTestingAPIEnabled"]) { 136 [[configuration preferences] _setEnabled:YES forInternalDebugFeature:feature]; 137 break; 138 } 139 } 140 RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get()]); 141 142 auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]); 143 [webView setUIDelegate:delegate.get()]; 144 145 done = false; 146 promptResult = @"foo"; 147 [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>IPC.sendMessage(\"Networking\", 0, IPC.messages.NetworkConnectionToWebProcess_HasStorageAccess.name," 148 "[{type: 'RegistrableDomain', value: 'https://ipctestingapi.com'}, {type: 'RegistrableDomain', value: 'https://webkit.org'}, {type: 'uint64_t', value: IPC.frameIdentifier}," 149 "{type: 'uint64_t', value: IPC.pageIdentifier}]).then((result) => alert(JSON.stringify(result.arguments)));</script>"]; 150 TestWebKitAPI::Util::run(&done); 151 152 EXPECT_STREQ([alertMessage UTF8String], "[{\"type\":\"bool\",\"value\":false}]"); 153 } 90 154 #endif 155 156 TEST(IPCTestingAPI, DescribesArguments) 157 { 158 RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 159 for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) { 160 if ([feature.key isEqualToString:@"IPCTestingAPIEnabled"]) { 161 [[configuration preferences] _setEnabled:YES forInternalDebugFeature:feature]; 162 break; 163 } 164 } 165 RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get()]); 166 167 auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]); 168 [webView setUIDelegate:delegate.get()]; 169 170 done = false; 171 [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>window.args = IPC.messages.WebPageProxy_RunJavaScriptAlert.arguments; alert('ok')</script>"]; 172 TestWebKitAPI::Util::run(&done); 173 174 EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args.length"] UTF8String], "3"); 175 EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args[0].type"] UTF8String], "WebCore::FrameIdentifier"); 176 EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args[1].type"] UTF8String], "WebKit::FrameInfoData"); 177 EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args[2].name"] UTF8String], "message"); 178 EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args[2].type"] UTF8String], "String"); 179 } 180 181 #endif
Note: See TracChangeset
for help on using the changeset viewer.