⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 268503 in webkit


Ignore:
Timestamp:
Oct 14, 2020, 5:33:30 PM (6 years ago)
Author:
rniwa@webkit.org
Message:

Source/WebKit:
IPC testing JS API should expose a reply and describe the list of arguments for each message
https://bugs.webkit.org/show_bug.cgi?id=217565

Reviewed by Geoffrey Garen.

This patch makes IPC.sendMessage and IPC.sendSyncMessage decode the reply. IPC.sendSyncMessage now returns
a dictionary with two keys: "buffer" and "arguments", the first of which returns ArrayBuffer of the decoded
message reply and the second of which is an array of decoded arguments where there was an appropriate JS
binding code existed for the argument type. IPC.sendMessage now returns a Promise which can either resolve
with the same dictionary as IPC.sendSyncMessage or reject when the decoding fails.

In addition, this patch exposes a dictionary describing each IPC message argument's type and parameter name.

In order to add these two functionalities, this patch adds a new step in generate-message-receiver.py to
generate MessageArgumentDescriptions.cpp, which contains functions which know how to decode arguments of
any IPC message and create a JS dictionary describing it as well as functions that return descriptions of
arguments or reply arguments.

Finally, this patch adds encoders for a few types found to be very common after r268239 had been landed.

Tests: TestWebKitAPI.IPCTestingAPI.DecodesReplyArgumentsForPrompt

TestWebKitAPI.IPCTestingAPI.DecodesReplyArgumentsForAsyncMessage
TestWebKitAPI.IPCTestingAPI.DescribesArguments

  • CMakeLists.txt:
  • DerivedSources-output.xcfilelist:
  • DerivedSources.make:
  • Platform/IPC/Decoder.h:

(IPC::Decoder::buffer const):

  • Platform/IPC/JSIPCBinding.h: Added.

(jsValueForDecodedArgumentValue): Added. A template function to construct a JS value for a given C++ value.
(jsValueForDecodedNumericArgumentValue): Added. A helper for constructing a JS value for numeric values.
(jsValueForDecodedArgumentRect): Added. Ditto for IntRect and FloatRect.
(DecodedArgumentJSValueConverter): Added. A helper class to construct JS values for a tuple of values using
partial template specializations.
(DecodedArgumentJSValueConverter::convert): Added.
(jsValueForArgumentTuple): Added. A helper to construct a JS array for the decoded IPC arguments.
(jsValueForDecodedArguments): Added.

  • Platform/IPC/MessageArgumentDescriptions.h: Added.

(IPC::ArgumentDescription): Added.

  • Scripts/generate-message-receiver.py:

(main): Generate MessageArgumentDescriptions.cpp.

  • Scripts/webkit/messages.py:

(headers_for_type): Removed the special case for PaymentMethodUpdate now that it's in its own header. Also
added made webrtc::WebKitEncodedFrameInfo include LibWebRTCEnumTraits.h as it uses webrtc::VideoFrameType.
(collect_header_conditions_for_receiver): Extracted from generate_message_handler.
(generate_header_includes_from_conditions): Ditto.
(generate_message_handler):
(generate_js_value_conversion_function): Added.
(generate_js_argument_descriptions): Added.
(generate_message_argument_description_implementation): Added.

  • Shared/ApplePay/ApplePayPaymentSetupFeaturesWebKit.h: Fixed a bug that we were not forward declaring NSArray.
  • SourcesCocoa.txt: Added MessageArgumentDescriptions.cpp as a non-unified cpp file as its size is around 1MB.
  • WebKit.xcodeproj/project.pbxproj:
  • WebProcess/WebPage/IPCTestingAPI.cpp:

(WebKit::IPCTestingAPI::JSIPC::staticValues): Added the session ID and page ID as static variables.
(WebKit::IPCTestingAPI::encodePointType): Added.
(WebKit::IPCTestingAPI::encodeRectType): Fixed the bug was that this code wasn't checking for any exceptions.
(WebKit::IPCTestingAPI::encodeNumericType): Renamed from encodeIntegralType since this function is now used
to encode double and float, not just integral types.
(WebKit::IPCTestingAPI::encodeArgument): Added the support for IntPoint, FloatPoint, URL, RegistrableDomain,
double, and float all of which turned out to be in the top 20 most common types.
(WebKit::IPCTestingAPI::jsResultFromReplyDecoder): Added.
(WebKit::IPCTestingAPI::JSIPC::sendMessage): Added the code to return Promise when there is a reply and resolve
it with the JS object describing the decoded argument. We use messageReplyArgumentDescriptions to figure out
whether there is a reply or not.
(WebKit::IPCTestingAPI::JSIPC::sendSyncMessage): Decode the reply and return a JS object which describes it.
(WebKit::IPCTestingAPI::JSIPC::frameID): Renamed from frameIdentifier to be consistent.
(WebKit::IPCTestingAPI::JSIPC::pageID): Added.
(WebKit::IPCTestingAPI::JSIPC::sessionID): Added.
(WebKit::IPCTestingAPI::createJSArrayForArgumentDescriptions): Added.
(WebKit::IPCTestingAPI::JSIPC::messages): Added the code to generate descriptions for arguments.

Source/WTF:
Unreviewed build fix. Disable IPC testing API on non-Cocoa platforms.

  • wtf/PlatformEnable.h:

Tools:
IPC testing JS API should expose a reply and describe the list of arguments for each message
https://bugs.webkit.org/show_bug.cgi?id=217565

Reviewed by Geoffrey Garen.

Added tests for decoding replies for sync and async messages and one for argument descriptions.

  • TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm:

(-[IPCTestingAPIDelegate webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:]):
(-[IPCTestingAPIDelegate _webView:webContentProcessDidTerminateWithReason:]):
(IPCTestingAPI.DecodesReplyArgumentsForPrompt):
(IPCTestingAPI.DecodesReplyArgumentsForAsyncMessage):
(IPCTestingAPI.DescribesArguments):

Location:
trunk
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r268479 r268503  
     12020-10-14  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Unreviewed build fix. Disable IPC testing API on non-Cocoa platforms.
     4
     5        * wtf/PlatformEnable.h:
     6
    172020-10-14  Alex Christensen  <achristensen@webkit.org>
    28
  • trunk/Source/WTF/wtf/PlatformEnable.h

    r268453 r268503  
    314314#if !defined(ENABLE_IPC_TESTING_API)
    315315/* Enable IPC testing on all ASAN builds and debug builds. */
    316 #if ASAN_ENABLED || !defined(NDEBUG)
     316#if (ASAN_ENABLED || !defined(NDEBUG)) && PLATFORM(COCOA)
    317317#define ENABLE_IPC_TESTING_API 1
    318318#endif
  • trunk/Source/WebKit/CMakeLists.txt

    r268486 r268503  
    429429    add_custom_command(
    430430        OUTPUT
     431            ${WebKit_DERIVED_SOURCES_DIR}/MessageArgumentDescriptions.cpp
    431432            ${WebKit_DERIVED_SOURCES_DIR}/MessageNames.cpp
    432433            ${WebKit_DERIVED_SOURCES_DIR}/MessageNames.h
  • trunk/Source/WebKit/ChangeLog

    r268500 r268503  
     12020-10-14  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
    1762020-10-14  Chris Dumez  <cdumez@apple.com>
    277
  • trunk/Source/WebKit/DerivedSources-output.xcfilelist

    r268486 r268503  
    6969$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MediaPlayerPrivateRemoteMessages.h
    7070$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MediaPlayerPrivateRemoteMessagesReplies.h
     71$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MessageArgumentDescriptions.cpp
    7172$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MessageNames.cpp
    7273$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/MessageNames.h
  • trunk/Source/WebKit/DerivedSources.make

    r268486 r268503  
    258258MESSAGE_REPLIES_FILES := $(addsuffix MessagesReplies.h,$(notdir $(MESSAGE_RECEIVERS)))
    259259
    260 GENERATED_MESSAGES_FILES := $(MESSAGE_RECEIVER_FILES) $(MESSAGES_FILES) $(MESSAGE_REPLIES_FILES) MessageNames.h MessageNames.cpp
     260GENERATED_MESSAGES_FILES := $(MESSAGE_RECEIVER_FILES) $(MESSAGES_FILES) $(MESSAGE_REPLIES_FILES) MessageNames.h MessageNames.cpp MessageArgumentDescriptions.cpp
    261261GENERATED_MESSAGES_FILES_AS_PATTERNS := $(subst .,%,$(GENERATED_MESSAGES_FILES))
    262262
  • trunk/Source/WebKit/Platform/IPC/Decoder.h

    r268486 r268503  
    7373    static std::unique_ptr<Decoder> unwrapForTesting(Decoder&);
    7474
     75    const uint8_t* buffer() const { return m_buffer; }
    7576    size_t length() const { return m_bufferEnd - m_buffer; }
    7677
  • trunk/Source/WebKit/Scripts/generate-message-receiver.py

    r268486 r268503  
    3535    first_arg = True
    3636    second_arg = False
     37    receiver_header_files = []
    3738    for parameter in argv:
    3839        if first_arg:
     
    5455            implementation_output.write(webkit.messages.generate_message_handler(receiver))
    5556
    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:
    5760            header_output.write(webkit.messages.generate_messages_header(receiver))
    5861
     
    6669        message_names_implementation_output.write(webkit.messages.generate_message_names_implementation(receivers))
    6770
     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
    6874    return 0
    6975
  • trunk/Source/WebKit/Scripts/webkit/messages.py

    r268486 r268503  
    624624        'WebCore::PasteboardWebContent': ['<WebCore/Pasteboard.h>'],
    625625        'WebCore::PaymentAuthorizationResult': ['<WebCore/ApplePaySessionPaymentRequest.h>'],
    626         'WebCore::PaymentMethodUpdate': ['<WebCore/ApplePaySessionPaymentRequest.h>'],
    627626        'WebCore::PlatformTextTrackData': ['<WebCore/PlatformTextTrack.h>'],
    628627        'WebCore::PluginInfo': ['<WebCore/PluginData.h>'],
     
    688687        'struct WebKit::WebUserStyleSheetData': ['"WebUserContentControllerDataTypes.h"'],
    689688        'struct WebKit::WebScriptMessageHandlerData': ['"WebUserContentControllerDataTypes.h"'],
    690         'webrtc::WebKitEncodedFrameInfo': ['<webrtc/sdk/WebKit/WebKitEncoder.h>'],
     689        'webrtc::WebKitEncodedFrameInfo': ['<webrtc/sdk/WebKit/WebKitEncoder.h>', '<WebCore/LibWebRTCEnumTraits.h>'],
    691690        'webrtc::WebKitRTPFragmentationHeader': ['<webrtc/sdk/WebKit/WebKitEncoder.h>'],
    692691    }
     
    715714
    716715
    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 
     716def collect_header_conditions_for_receiver(receiver, header_conditions):
    724717    type_conditions = {}
    725718    for parameter in receiver.iterparameters():
     
    764757                    header_conditions[header].append(message.condition)
    765758
    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
     762def generate_header_includes_from_conditions(header_conditions):
     763    result = []
    776764    for header in sorted(header_conditions):
    777765        if header_conditions[header] and not None in header_conditions[header]:
     
    781769        else:
    782770            result += ['#include %s\n' % header]
     771    return result
     772
     773
     774def 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)
    783794    result.append('\n')
    784795
     
    10451056    result.append('} // namespace IPC\n')
    10461057    return ''.join(result)
     1058
     1059
     1060def 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
     1090def 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
     1140def 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

    r268486 r268503  
    2828#if ENABLE(APPLE_PAY)
    2929
     30OBJC_CLASS NSArray;
    3031OBJC_CLASS PKPaymentSetupFeature;
    3132
  • trunk/Source/WebKit/SourcesCocoa.txt

    r268486 r268503  
    659659LibWebRTCCodecsProxyMessageReceiver.cpp
    660660LibWebRTCCodecsMessageReceiver.cpp
     661MessageArgumentDescriptions.cpp @no-unify
    661662MessageNames.cpp
    662663RemoteAudioDestinationManagerMessageReceiver.cpp
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r268486 r268503  
    14241424                9B1229CE23FF25F2008CA751 /* RemoteAudioDestinationManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B1229CC23FF25F2008CA751 /* RemoteAudioDestinationManager.cpp */; };
    14251425                9B1229D223FF2BCC008CA751 /* RemoteAudioDestinationIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B1229D023FF2A5E008CA751 /* RemoteAudioDestinationIdentifier.h */; };
     1426                9B47908D25314D8300EC11AB /* MessageArgumentDescriptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B47908C25314D8300EC11AB /* MessageArgumentDescriptions.h */; };
     1427                9B47908F253151CC00EC11AB /* JSIPCBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B47908E253151CC00EC11AB /* JSIPCBinding.h */; };
     1428                9B4790912531563200EC11AB /* MessageArgumentDescriptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B4790902531563200EC11AB /* MessageArgumentDescriptions.cpp */; };
    14261429                9B5499AD2362A6F900DF8BA5 /* _WKTextManipulationConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5499AC2362A6F600DF8BA5 /* _WKTextManipulationConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14271430                9B5499B22362A7EC00DF8BA5 /* _WKTextManipulationExclusionRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5499B02362A7EC00DF8BA5 /* _WKTextManipulationExclusionRule.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    45264529                9B1229CF23FF2814008CA751 /* RemoteAudioDestinationManager.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = RemoteAudioDestinationManager.messages.in; sourceTree = "<group>"; };
    45274530                9B1229D023FF2A5E008CA751 /* RemoteAudioDestinationIdentifier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteAudioDestinationIdentifier.h; sourceTree = "<group>"; };
     4531                9B47908C25314D8300EC11AB /* MessageArgumentDescriptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MessageArgumentDescriptions.h; sourceTree = "<group>"; };
     4532                9B47908E253151CC00EC11AB /* JSIPCBinding.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSIPCBinding.h; sourceTree = "<group>"; };
     4533                9B4790902531563200EC11AB /* MessageArgumentDescriptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MessageArgumentDescriptions.cpp; path = MessageArgumentDescriptions.cpp; sourceTree = "<group>"; };
    45284534                9B5499AC2362A6F600DF8BA5 /* _WKTextManipulationConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKTextManipulationConfiguration.h; sourceTree = "<group>"; };
    45294535                9B5499AE2362A7A700DF8BA5 /* _WKTextManipulationConfiguration.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKTextManipulationConfiguration.mm; sourceTree = "<group>"; };
     
    64596465                                C0CE72AC1247E78D00BC0EC4 /* HandleMessage.h */,
    64606466                                1C9AF36124134D2300D3EC02 /* ImageDataReference.h */,
     6467                                9B47908E253151CC00EC11AB /* JSIPCBinding.h */,
     6468                                9B47908C25314D8300EC11AB /* MessageArgumentDescriptions.h */,
    64616469                                1AC4C82816B876A90069DCCD /* MessageFlags.h */,
    64626470                                1A3EED11161A53D600AEB4F5 /* MessageReceiver.h */,
     
    1008210090                                07E19EF923D401F00094FFB4 /* MediaPlayerPrivateRemoteMessages.h */,
    1008310091                                07E19EFA23D401F00094FFB4 /* MediaPlayerPrivateRemoteMessagesReplies.h */,
     10092                                9B4790902531563200EC11AB /* MessageArgumentDescriptions.cpp */,
    1008410093                                51DD9F2616367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp */,
    1008510094                                51DD9F2716367DA2001578E9 /* NetworkConnectionToWebProcessMessages.h */,
     
    1093510944                                C5BCE5DF1C50766A00CDE3FA /* InteractionInformationAtPosition.h in Headers */,
    1093610945                                2D4D2C811DF60BF3002EB10C /* InteractionInformationRequest.h in Headers */,
     10946                                9B47908F253151CC00EC11AB /* JSIPCBinding.h in Headers */,
    1093710947                                1AE49A4911FFA8CE0048B464 /* JSNPMethod.h in Headers */,
    1093810948                                1AE4987811FF7FAA0048B464 /* JSNPObject.h in Headers */,
     
    1097110981                                07E19EFD23D401F10094FFB4 /* MediaPlayerPrivateRemoteMessagesReplies.h in Headers */,
    1097210982                                51933DEF1965EB31008AC3EA /* MenuUtilities.h in Headers */,
     10983                                9B47908D25314D8300EC11AB /* MessageArgumentDescriptions.h in Headers */,
    1097310984                                1AC4C82916B876A90069DCCD /* MessageFlags.h in Headers */,
    1097410985                                1A3EED12161A53D600AEB4F5 /* MessageReceiver.h in Headers */,
     
    1284112852                                2D92A779212B6A6100F493FD /* Logging.cpp in Sources */,
    1284212853                                07E19EFB23D401F10094FFB4 /* MediaPlayerPrivateRemoteMessageReceiver.cpp in Sources */,
     12854                                9B4790912531563200EC11AB /* MessageArgumentDescriptions.cpp in Sources */,
    1284312855                                2D92A781212B6A7100F493FD /* MessageReceiverMap.cpp in Sources */,
    1284412856                                2D92A782212B6A7100F493FD /* MessageSender.cpp in Sources */,
  • trunk/Source/WebKit/WebProcess/WebPage/IPCTestingAPI.cpp

    r268486 r268503  
    3232#include "FrameInfoData.h"
    3333#include "GPUProcessConnection.h"
    34 #include "MessageNames.h"
     34#include "MessageArgumentDescriptions.h"
    3535#include "NetworkProcessConnection.h"
    3636#include "WebCoreArgumentCoders.h"
     
    8484    static JSValueRef visitedLinkStoreID(JSContextRef, JSObjectRef, JSStringRef, JSValueRef* exception);
    8585    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);
    8789    static JSValueRef retrieveID(JSContextRef, JSObjectRef thisObject, JSValueRef* exception, const WTF::Function<uint64_t(JSIPC&)>&);
    8890
     
    145147    static const JSStaticValue values[] = {
    146148        { "visitedLinkStoreID", visitedLinkStoreID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
     149        { "frameID", frameID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
     150        { "pageID", pageID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
     151        { "sessionID", sessionID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
    147152        { "webPageProxyID", webPageProxyID, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
    148         { "frameIdentifier", frameIdentifier, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
    149153        { "messages", messages, 0, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
    150154        { 0, 0, 0, 0 }
     
    238242}
    239243
    240 template<typename RectType> bool encodeRectType(IPC::Encoder& encoder, JSC::JSGlobalObject* globalObject, JSC::JSObject* jsObject)
     244template<typename PointType> bool encodePointType(IPC::Encoder& encoder, JSC::JSGlobalObject* globalObject, JSC::JSObject* jsObject, JSC::CatchScope& scope)
    241245{
    242246    auto& vm = globalObject->vm();
    243247    auto jsX = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "x"_s));
    244     if (!jsX.isNumber())
     248    if (scope.exception() || !jsX.isNumber())
    245249        return false;
    246250    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
     257template<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())
    248265        return false;
    249266    auto jsWidth = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "width"_s));
    250     if (!jsWidth.isNumber())
     267    if (scope.exception() || !jsWidth.isNumber())
    251268        return false;
    252269    auto jsHeight = jsObject->get(globalObject, JSC::Identifier::fromString(vm, "height"_s));
    253     if (!jsHeight.isNumber())
     270    if (scope.exception() || !jsHeight.isNumber())
    254271        return false;
    255272    encoder << RectType(jsX.asNumber(), jsY.asNumber(), jsWidth.asNumber(), jsHeight.asNumber());
     
    257274}
    258275
    259 template<typename IntegralType> bool encodeIntegralType(IPC::Encoder& encoder, JSC::JSValue jsValue)
     276template<typename IntegralType> bool encodeNumericType(IPC::Encoder& encoder, JSC::JSValue jsValue)
    260277{
    261278    if (jsValue.isBigInt()) {
     
    341358        return false;
    342359
     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
    343376    if (type == "IntRect") {
    344         if (!encodeRectType<WebCore::IntRect>(encoder, globalObject, jsObject)) {
     377        if (!encodeRectType<WebCore::IntRect>(encoder, globalObject, jsObject, scope)) {
    345378            *exception = createTypeError(context, "Failed to convert IntRect"_s);
    346379            return false;
     
    350383
    351384    if (type == "FloatRect") {
    352         if (!encodeRectType<WebCore::FloatRect>(encoder, globalObject, jsObject)) {
     385        if (!encodeRectType<WebCore::FloatRect>(encoder, globalObject, jsObject, scope)) {
    353386            *exception = createTypeError(context, "Failed to convert FloatRect"_s);
    354387            return false;
     
    383416    }
    384417
     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
    385442    if (type == "RGBA") {
    386443        if (!jsValue.isNumber()) {
     
    393450    }
    394451
    395     bool integralResult;
     452    bool numericResult;
    396453    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);
    398459    else if (type == "int8_t")
    399         integralResult = encodeIntegralType<int8_t>(encoder, jsValue);
     460        numericResult = encodeNumericType<int8_t>(encoder, jsValue);
    400461    else if (type == "int16_t")
    401         integralResult = encodeIntegralType<int16_t>(encoder, jsValue);
     462        numericResult = encodeNumericType<int16_t>(encoder, jsValue);
    402463    else if (type == "int32_t")
    403         integralResult = encodeIntegralType<int32_t>(encoder, jsValue);
     464        numericResult = encodeNumericType<int32_t>(encoder, jsValue);
    404465    else if (type == "int64_t")
    405         integralResult = encodeIntegralType<int64_t>(encoder, jsValue);
     466        numericResult = encodeNumericType<int64_t>(encoder, jsValue);
    406467    else if (type == "uint8_t")
    407         integralResult = encodeIntegralType<uint8_t>(encoder, jsValue);
     468        numericResult = encodeNumericType<uint8_t>(encoder, jsValue);
    408469    else if (type == "uint16_t")
    409         integralResult = encodeIntegralType<uint16_t>(encoder, jsValue);
     470        numericResult = encodeNumericType<uint16_t>(encoder, jsValue);
    410471    else if (type == "uint32_t")
    411         integralResult = encodeIntegralType<uint32_t>(encoder, jsValue);
     472        numericResult = encodeNumericType<uint32_t>(encoder, jsValue);
    412473    else if (type == "uint64_t")
    413         integralResult = encodeIntegralType<uint64_t>(encoder, jsValue);
     474        numericResult = encodeNumericType<uint64_t>(encoder, jsValue);
    414475    else {
    415476        *exception = createTypeError(context, "Bad type name"_s);
    416477        return false;
    417478    }
    418     if (!integralResult) {
    419         *exception = createTypeError(context, "Failed to encode an integer"_s);
     479    if (!numericResult) {
     480        *exception = createTypeError(context, "Failed to encode a number"_s);
    420481        return false;
    421482    }
    422483    return true;
     484}
     485
     486
     487static 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;
    423523}
    424524
     
    429529    auto jsIPC = makeRefPtr(toWrapped(context, thisObject));
    430530    if (!jsIPC) {
    431         *exception = toRef(JSC::createTypeError(toJS(context), "Wrong type"_s));
     531        *exception = createTypeError(context, "Wrong type"_s);
    432532        return JSValueMakeUndefined(context);
    433533    }
    434534
    435535    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);
    437537        return JSValueMakeUndefined(context);
    438538    }
     
    450550        return JSValueMakeUndefined(context);
    451551
    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;
     564ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN
     565        returnValue = JSObjectMakeDeferredPromise(context, &resolve, &reject, exception);
     566ALLOW_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    }
    453594
    454595    if (argumentCount > 3) {
     
    461602    connection->sendMessage(WTFMove(encoder), { });
    462603
    463     return JSValueMakeUndefined(context);
     604    return returnValue;
    464605}
    465606
     
    470611    auto jsIPC = makeRefPtr(toWrapped(context, thisObject));
    471612    if (!jsIPC) {
    472         *exception = toRef(JSC::createTypeError(toJS(context), "Wrong type"_s));
     613        *exception = createTypeError(context, "Wrong type"_s);
    473614        return JSValueMakeUndefined(context);
    474615    }
    475616
    476617    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);
    478619        return JSValueMakeUndefined(context);
    479620    }
     
    495636        auto jsValue = toJS(globalObject, arguments[3]);
    496637        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);
    498639            return JSValueMakeUndefined(context);
    499640        }
    500641        timeout = Seconds { jsValue.asNumber() };
    501642    }
    502    
     643
    503644    // FIXME: Support the options.
    504645
    505646    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);
    507649
    508650    if (argumentCount > 4) {
     
    511653    }
    512654
    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    }
    515665
    516666    return JSValueMakeUndefined(context);
     
    525675}
    526676
     677JSValueRef 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
     684JSValueRef 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
     691JSValueRef 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
    527698JSValueRef JSIPC::webPageProxyID(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef* exception)
    528699{
     
    532703}
    533704
    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 
    541705JSValueRef JSIPC::retrieveID(JSContextRef context, JSObjectRef thisObject, JSValueRef* exception, const WTF::Function<uint64_t(JSIPC&)>& callback)
    542706{
     
    556720}
    557721
     722static 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
    558757JSValueRef JSIPC::messages(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef* exception)
    559758{
     
    568767    }
    569768
     769    auto scope = DECLARE_CATCH_SCOPE(vm);
    570770    JSC::JSObject* messagesObject = constructEmptyObject(globalObject, globalObject->objectPrototype());
     771    RETURN_IF_EXCEPTION(scope, JSValueMakeUndefined(context));
     772
    571773    auto nameIdent = JSC::Identifier::fromString(vm, "name");
     774    auto replyArgumentsIdent = JSC::Identifier::fromString(vm, "replyArguments");
    572775    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);
    574777
    575778        JSC::JSObject* dictionary = constructEmptyObject(globalObject, globalObject->objectPrototype());
     779        RETURN_IF_EXCEPTION(scope, JSValueMakeUndefined(context));
     780
    576781        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));
    581798    }
    582799
  • trunk/Tools/ChangeLog

    r268498 r268503  
     12020-10-14  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
    1172020-10-14  Hector Lopez  <hector_i_lopez@apple.com>
    218
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IPCTestingAPI.mm

    r268497 r268503  
    3535
    3636static bool done = false;
     37static bool didCrash = false;
    3738static RetainPtr<NSString> alertMessage;
    38 
    39 @interface IPCTestingAPIDelegate : NSObject <WKUIDelegate>
     39static RetainPtr<NSString> promptDefault;
     40static RetainPtr<NSString> promptResult;
     41
     42@interface IPCTestingAPIDelegate : NSObject <WKUIDelegate, WKNavigationDelegate>
    4043@end
    4144   
     
    4952}
    5053
     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;
     65}
     66
    5167@end
    5268
     
    8298    done = false;
    8399    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>IPC.sendSyncMessage('UI', IPC.webPageProxyID, IPC.messages.WebPageProxy_RunJavaScriptAlert.name, 100,"
    84         "[{type: 'uint64_t', value: IPC.frameIdentifier}, {type: 'FrameInfoData'}, {'type': 'String', 'value': 'hi'}]);</script>"];
     100        "[{type: 'uint64_t', value: IPC.frameID}, {type: 'FrameInfoData'}, {'type': 'String', 'value': 'hi'}]);</script>"];
    85101    TestWebKitAPI::Util::run(&done);
    86102
     
    134150}
    135151
     152TEST(IPCTestingAPI, DecodesReplyArgumentsForPrompt)
     153{
     154    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     155    for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) {
     156        if ([feature.key isEqualToString:@"IPCTestingAPIEnabled"]) {
     157            [[configuration preferences] _setEnabled:YES forInternalDebugFeature:feature];
     158            break;
     159        }
     160    }
     161    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get()]);
     162
     163    auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]);
     164    [webView setUIDelegate:delegate.get()];
     165
     166    done = false;
     167    promptResult = @"foo";
     168    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>result = IPC.sendSyncMessage('UI', IPC.webPageProxyID, IPC.messages.WebPageProxy_RunJavaScriptPrompt.name, 100,"
     169        "[{type: 'uint64_t', value: IPC.frameID}, {type: 'FrameInfoData'}, {'type': 'String', 'value': 'hi'}, {'type': 'String', 'value': 'bar'}]);</script>"];
     170    TestWebKitAPI::Util::run(&done);
     171
     172    EXPECT_STREQ([promptDefault UTF8String], "bar");
     173    EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"JSON.stringify(result.arguments)"] UTF8String], "[{\"type\":\"String\",\"value\":\"foo\"}]");
     174}
     175
     176#if ENABLE(RESOURCE_LOAD_STATISTICS)
     177TEST(IPCTestingAPI, DecodesReplyArgumentsForAsyncMessage)
     178{
     179    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     180    for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) {
     181        if ([feature.key isEqualToString:@"IPCTestingAPIEnabled"]) {
     182            [[configuration preferences] _setEnabled:YES forInternalDebugFeature:feature];
     183            break;
     184        }
     185    }
     186    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get()]);
     187
     188    auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]);
     189    [webView setUIDelegate:delegate.get()];
     190
     191    done = false;
     192    promptResult = @"foo";
     193    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>IPC.sendMessage(\"Networking\", 0, IPC.messages.NetworkConnectionToWebProcess_HasStorageAccess.name,"
     194        "[{type: 'RegistrableDomain', value: 'https://ipctestingapi.com'}, {type: 'RegistrableDomain', value: 'https://webkit.org'}, {type: 'uint64_t', value: IPC.frameID},"
     195        "{type: 'uint64_t', value: IPC.pageID}]).then((result) => alert(JSON.stringify(result.arguments)));</script>"];
     196    TestWebKitAPI::Util::run(&done);
     197
     198    EXPECT_STREQ([alertMessage UTF8String], "[{\"type\":\"bool\",\"value\":false}]");
     199}
    136200#endif
     201
     202TEST(IPCTestingAPI, DescribesArguments)
     203{
     204    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     205    for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) {
     206        if ([feature.key isEqualToString:@"IPCTestingAPIEnabled"]) {
     207            [[configuration preferences] _setEnabled:YES forInternalDebugFeature:feature];
     208            break;
     209        }
     210    }
     211    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get()]);
     212
     213    auto delegate = adoptNS([[IPCTestingAPIDelegate alloc] init]);
     214    [webView setUIDelegate:delegate.get()];
     215
     216    done = false;
     217    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><script>window.args = IPC.messages.WebPageProxy_RunJavaScriptAlert.arguments; alert('ok')</script>"];
     218    TestWebKitAPI::Util::run(&done);
     219
     220    EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args.length"] UTF8String], "3");
     221    EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args[0].type"] UTF8String], "WebCore::FrameIdentifier");
     222    EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args[1].type"] UTF8String], "WebKit::FrameInfoData");
     223    EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args[2].name"] UTF8String], "message");
     224    EXPECT_STREQ([[webView stringByEvaluatingJavaScript:@"args[2].type"] UTF8String], "String");
     225}
     226
     227#endif
Note: See TracChangeset for help on using the changeset viewer.