bfab03ab4c03e5ab5fdc7c590aaaa0725bc6ff9e
[WebKit-https.git] / Source / WebKit / Scripts / webkit / messages.py
1 # Copyright (C) 2010-2018 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1.  Redistributions of source code must retain the above copyright
7 #     notice, this list of conditions and the following disclaimer.
8 # 2.  Redistributions in binary form must reproduce the above copyright
9 #     notice, this list of conditions and the following disclaimer in the
10 #     documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
13 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
16 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
20 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
21 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
23 import collections
24 import re
25 import sys
26
27 from webkit import parser
28
29 WANTS_CONNECTION_ATTRIBUTE = 'WantsConnection'
30 LEGACY_RECEIVER_ATTRIBUTE = 'LegacyReceiver'
31 DELAYED_ATTRIBUTE = 'Delayed'
32 ASYNC_ATTRIBUTE = 'Async'
33 LEGACY_SYNC_ATTRIBUTE = 'LegacySync'
34
35 _license_header = """/*
36  * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1.  Redistributions of source code must retain the above copyright
42  *     notice, this list of conditions and the following disclaimer.
43  * 2.  Redistributions in binary form must reproduce the above copyright
44  *     notice, this list of conditions and the following disclaimer in the
45  *     documentation and/or other materials provided with the distribution.
46  *
47  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
51  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
54  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
55  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
56  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57  */
58
59 """
60
61
62 def messages_header_filename(receiver):
63     return '%sMessages.h' % receiver.name
64
65
66 def surround_in_condition(string, condition):
67     if not condition:
68         return string
69     return '#if %s\n%s#endif\n' % (condition, string)
70
71
72 def function_parameter_type(type, kind):
73     # Don't use references for built-in types.
74     builtin_types = frozenset([
75         'bool',
76         'float',
77         'double',
78         'uint8_t',
79         'uint16_t',
80         'uint32_t',
81         'uint64_t',
82         'int8_t',
83         'int16_t',
84         'int32_t',
85         'int64_t',
86     ])
87
88     if type in builtin_types:
89         return type
90
91     if kind.startswith('enum:'):
92         return type
93
94     return 'const %s&' % type
95
96
97 def reply_parameter_type(type):
98     return '%s&' % type
99
100
101 def move_type(type):
102     return '%s&&' % type
103
104
105 def arguments_type(message):
106     return 'std::tuple<%s>' % ', '.join(function_parameter_type(parameter.type, parameter.kind) for parameter in message.parameters)
107
108
109 def reply_type(message):
110     return 'std::tuple<%s>' % (', '.join(reply_parameter_type(parameter.type) for parameter in message.reply_parameters))
111
112
113 def message_to_struct_declaration(message):
114     result = []
115     function_parameters = [(function_parameter_type(x.type, x.kind), x.name) for x in message.parameters]
116     result.append('class %s {\n' % message.name)
117     result.append('public:\n')
118     result.append('    typedef %s Arguments;\n' % arguments_type(message))
119     result.append('\n')
120     result.append('    static IPC::StringReference receiverName() { return messageReceiverName(); }\n')
121     result.append('    static IPC::StringReference name() { return IPC::StringReference("%s"); }\n' % message.name)
122     result.append('    static const bool isSync = %s;\n' % ('false', 'true')[message.reply_parameters != None and not message.has_attribute(ASYNC_ATTRIBUTE)])
123     result.append('\n')
124     if message.reply_parameters != None:
125         send_parameters = [(function_parameter_type(x.type, x.kind), x.name) for x in message.reply_parameters]
126         completion_handler_parameters = '%s' % ', '.join([' '.join(x) for x in send_parameters])
127         if message.has_attribute(ASYNC_ATTRIBUTE):
128             move_parameters = ', '.join([move_type(x.type) for x in message.reply_parameters])
129             result.append('    static void callReply(IPC::Decoder&, CompletionHandler<void(%s)>&&);\n' % move_parameters)
130             result.append('    static void cancelReply(CompletionHandler<void(%s)>&&);\n' % move_parameters)
131             result.append('    static IPC::StringReference asyncMessageReplyName() { return { "%sReply" }; }\n' % message.name)
132             result.append('    using AsyncReply')
133         elif message.has_attribute(DELAYED_ATTRIBUTE):
134             result.append('    using DelayedReply')
135         if message.has_attribute(DELAYED_ATTRIBUTE) or message.has_attribute(ASYNC_ATTRIBUTE):
136             result.append(' = CompletionHandler<void(%s)>;\n' % completion_handler_parameters)
137             result.append('    static void send(std::unique_ptr<IPC::Encoder>&&, IPC::Connection&')
138             if len(send_parameters):
139                 result.append(', %s' % completion_handler_parameters)
140             result.append(');\n')
141         result.append('    typedef %s Reply;\n' % reply_type(message))
142
143     if len(function_parameters):
144         result.append('    %s%s(%s)' % (len(function_parameters) == 1 and 'explicit ' or '', message.name, ', '.join([' '.join(x) for x in function_parameters])))
145         result.append('\n        : m_arguments(%s)\n' % ', '.join([x[1] for x in function_parameters]))
146         result.append('    {\n')
147         result.append('    }\n\n')
148     result.append('    const Arguments& arguments() const\n')
149     result.append('    {\n')
150     result.append('        return m_arguments;\n')
151     result.append('    }\n')
152     result.append('\n')
153     result.append('private:\n')
154     result.append('    Arguments m_arguments;\n')
155     result.append('};\n')
156     return surround_in_condition(''.join(result), message.condition)
157
158
159 def forward_declaration(namespace, kind_and_type):
160     kind, type = kind_and_type
161
162     qualified_name = '%s::%s' % (namespace, type)
163     if kind == 'struct':
164         return 'struct %s' % type
165     elif kind.startswith('enum:'):
166         return 'enum class %s : %s' % (type, kind[5:])
167     else:
168         return 'class %s' % type
169
170
171 def forward_declarations_for_namespace(namespace, kind_and_types):
172     result = []
173     result.append('namespace %s {\n' % namespace)
174     result += ['%s;\n' % forward_declaration(namespace, x) for x in kind_and_types]
175     result.append('}\n')
176     return ''.join(result)
177
178
179 def forward_declarations_and_headers(receiver):
180     types_by_namespace = collections.defaultdict(set)
181
182     headers = set([
183         '"ArgumentCoders.h"',
184         '<wtf/Forward.h>',
185     ])
186
187     non_template_wtf_types = frozenset([
188         'MachSendRight',
189         'String',
190     ])
191
192     headers.add('"Connection.h"')
193     headers.add('<wtf/ThreadSafeRefCounted.h>')
194
195     no_forward_declaration_types = frozenset([
196         'MachSendRight',
197         'String',
198         'WebCore::DocumentIdentifier',
199         'WebCore::FetchIdentifier',
200         'WebCore::PointerID',
201         'WebCore::ServiceWorkerIdentifier',
202         'WebCore::ServiceWorkerJobIdentifier',
203         'WebCore::ServiceWorkerOrClientData',
204         'WebCore::ServiceWorkerOrClientIdentifier',
205         'WebCore::ServiceWorkerRegistrationIdentifier',
206         'WebCore::SWServerConnectionIdentifier',
207         'WebKit::ActivityStateChangeID',
208         'WebKit::UserContentControllerIdentifier',
209     ])
210
211     for parameter in receiver.iterparameters():
212         kind = parameter.kind
213         type = parameter.type
214
215         if type.find('<') != -1 or type in no_forward_declaration_types:
216             # Don't forward declare class templates.
217             headers.update(headers_for_type(type))
218             continue
219
220         split = type.split('::')
221
222         # Handle WTF types even if the WTF:: prefix is not given
223         if split[0] in non_template_wtf_types:
224             split.insert(0, 'WTF')
225
226         if len(split) == 2:
227             namespace = split[0]
228             inner_type = split[1]
229             types_by_namespace[namespace].add((kind, inner_type))
230         elif len(split) > 2:
231             # We probably have a nested struct, which means we can't forward declare it.
232             # Include its header instead.
233             headers.update(headers_for_type(type))
234
235     forward_declarations = '\n'.join([forward_declarations_for_namespace(namespace, types) for (namespace, types) in sorted(types_by_namespace.items())])
236     headers = ['#include %s\n' % header for header in sorted(headers)]
237
238     return (forward_declarations, headers)
239
240
241 def generate_messages_header(file):
242     receiver = parser.parse(file)
243
244     result = []
245
246     result.append(_license_header)
247
248     result.append('#pragma once\n')
249     result.append('\n')
250
251     if receiver.condition:
252         result.append('#if %s\n\n' % receiver.condition)
253
254     forward_declarations, headers = forward_declarations_and_headers(receiver)
255
256     result += headers
257     result.append('\n')
258
259     result.append(forward_declarations)
260     result.append('\n')
261
262     result.append('namespace Messages {\nnamespace %s {\n' % receiver.name)
263     result.append('\n')
264     result.append('static inline IPC::StringReference messageReceiverName()\n')
265     result.append('{\n')
266     result.append('    return IPC::StringReference("%s");\n' % receiver.name)
267     result.append('}\n')
268     result.append('\n')
269     result.append('\n'.join([message_to_struct_declaration(x) for x in receiver.messages]))
270     result.append('\n')
271     result.append('} // namespace %s\n} // namespace Messages\n' % receiver.name)
272
273     if receiver.condition:
274         result.append('\n#endif // %s\n' % receiver.condition)
275
276     return ''.join(result)
277
278
279 def handler_function(receiver, message):
280     if message.name.find('URL') == 0:
281         return '%s::%s' % (receiver.name, 'url' + message.name[3:])
282     return '%s::%s' % (receiver.name, message.name[0].lower() + message.name[1:])
283
284
285 def async_message_statement(receiver, message):
286     dispatch_function_args = ['decoder', 'this', '&%s' % handler_function(receiver, message)]
287
288     dispatch_function = 'handleMessage'
289     if message.has_attribute(ASYNC_ATTRIBUTE):
290         dispatch_function += 'Async'
291         dispatch_function_args.insert(0, 'connection')
292
293     if message.has_attribute(WANTS_CONNECTION_ATTRIBUTE):
294         dispatch_function_args.insert(0, 'connection')
295
296     result = []
297     result.append('    if (decoder.messageName() == Messages::%s::%s::name()) {\n' % (receiver.name, message.name))
298     result.append('        IPC::%s<Messages::%s::%s>(%s);\n' % (dispatch_function, receiver.name, message.name, ', '.join(dispatch_function_args)))
299     result.append('        return;\n')
300     result.append('    }\n')
301     return surround_in_condition(''.join(result), message.condition)
302
303
304 def sync_message_statement(receiver, message):
305     dispatch_function = 'handleMessage'
306     if message.has_attribute(DELAYED_ATTRIBUTE):
307         dispatch_function += 'Delayed'
308         if message.has_attribute(WANTS_CONNECTION_ATTRIBUTE):
309             dispatch_function += 'WantsConnection'
310     if message.has_attribute(ASYNC_ATTRIBUTE):
311         dispatch_function += 'Async'
312     if message.has_attribute(LEGACY_SYNC_ATTRIBUTE):
313         dispatch_function += 'LegacySync'
314
315     wants_connection = message.has_attribute(DELAYED_ATTRIBUTE) or message.has_attribute(WANTS_CONNECTION_ATTRIBUTE)
316
317     result = []
318     result.append('    if (decoder.messageName() == Messages::%s::%s::name()) {\n' % (receiver.name, message.name))
319     result.append('        IPC::%s<Messages::%s::%s>(%sdecoder, %sreplyEncoder, this, &%s);\n' % (dispatch_function, receiver.name, message.name, 'connection, ' if wants_connection else '', '' if message.has_attribute(DELAYED_ATTRIBUTE) or message.has_attribute(ASYNC_ATTRIBUTE) else '*', handler_function(receiver, message)))
320     result.append('        return;\n')
321     result.append('    }\n')
322     return surround_in_condition(''.join(result), message.condition)
323
324
325 def class_template_headers(template_string):
326     template_string = template_string.strip()
327
328     class_template_types = {
329         'WebCore::RectEdges': {'headers': ['<WebCore/RectEdges.h>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
330         'HashMap': {'headers': ['<wtf/HashMap.h>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
331         'HashSet': {'headers': ['<wtf/HashSet.h>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
332         'Optional': {'headers': ['<wtf/Optional.h>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
333         'OptionSet': {'headers': ['<wtf/OptionSet.h>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
334         'Vector': {'headers': ['<wtf/Vector.h>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
335         'std::pair': {'headers': ['<utility>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
336     }
337
338     match = re.match('(?P<template_name>.+?)<(?P<parameter_string>.+)>', template_string)
339     if not match:
340         return {'header_infos': [], 'types': [template_string]}
341
342     template_name = match.groupdict()['template_name']
343     if template_name not in class_template_types:
344         sys.stderr.write("Error: no class template type is defined for '%s'\n" % (template_string))
345         sys.exit(1)
346
347     header_infos = [class_template_types[template_name]]
348     types = []
349
350     for parameter in parser.split_parameters_string(match.groupdict()['parameter_string']):
351         parameter_header_infos_and_types = class_template_headers(parameter)
352
353         header_infos += parameter_header_infos_and_types['header_infos']
354         types += parameter_header_infos_and_types['types']
355
356     return {'header_infos': header_infos, 'types': types}
357
358
359 def argument_coder_headers_for_type(type):
360     header_infos_and_types = class_template_headers(type)
361
362     special_cases = {
363         'String': '"ArgumentCoders.h"',
364         'WebKit::ScriptMessageHandlerHandle': '"WebScriptMessageHandler.h"',
365     }
366
367     headers = []
368     for header_info in header_infos_and_types['header_infos']:
369         headers += header_info['argument_coder_headers']
370
371     for type in header_infos_and_types['types']:
372         if type in special_cases:
373             headers.append(special_cases[type])
374             continue
375
376         split = type.split('::')
377         if len(split) < 2:
378             continue
379         if split[0] == 'WebCore':
380             headers.append('"WebCoreArgumentCoders.h"')
381
382     return headers
383
384
385 def headers_for_type(type):
386     header_infos_and_types = class_template_headers(type)
387
388     special_cases = {
389         'IPC::SharedBufferDataReference': ['"SharedBufferDataReference.h"', '"DataReference.h"'],
390         'MachSendRight': ['<wtf/MachSendRight.h>'],
391         'JSC::MessageLevel': ['<JavaScriptCore/ConsoleTypes.h>'],
392         'JSC::MessageSource': ['<JavaScriptCore/ConsoleTypes.h>'],
393         'Inspector::InspectorTargetType': ['<JavaScriptCore/InspectorTarget.h>'],
394         'Inspector::FrontendChannel::ConnectionType': ['<JavaScriptCore/InspectorFrontendChannel.h>'],
395         'MonotonicTime': ['<wtf/MonotonicTime.h>'],
396         'Seconds': ['<wtf/Seconds.h>'],
397         'WallTime': ['<wtf/WallTime.h>'],
398         'String': ['<wtf/text/WTFString.h>'],
399         'PAL::SessionID': ['<pal/SessionID.h>'],
400         'WebCore::AutoplayEventFlags': ['<WebCore/AutoplayEvent.h>'],
401         'WebCore::DOMPasteAccessResponse': ['<WebCore/DOMPasteAccess.h>'],
402         'WebCore::DragHandlingMethod': ['<WebCore/DragActions.h>'],
403         'WebCore::ExceptionDetails': ['<WebCore/JSDOMExceptionHandling.h>'],
404         'WebCore::FileChooserSettings': ['<WebCore/FileChooser.h>'],
405         'WebCore::ShareDataWithParsedURL': ['<WebCore/ShareData.h>'],
406         'WebCore::FontChanges': ['<WebCore/FontAttributeChanges.h>'],
407         'WebCore::FrameLoadType': ['<WebCore/FrameLoaderTypes.h>'],
408         'WebCore::GrammarDetail': ['<WebCore/TextCheckerClient.h>'],
409         'WebCore::HasInsecureContent': ['<WebCore/FrameLoaderTypes.h>'],
410         'WebCore::Highlight': ['<WebCore/InspectorOverlay.h>'],
411         'WebCore::IncludeSecureCookies': ['<WebCore/CookieJar.h>'],
412         'WebCore::IndexedDB::ObjectStoreOverwriteMode': ['<WebCore/IndexedDB.h>'],
413         'WebCore::InputMode': ['<WebCore/InputMode.h>'],
414         'WebCore::KeyframeValueList': ['<WebCore/GraphicsLayer.h>'],
415         'WebCore::KeypressCommand': ['<WebCore/KeyboardEvent.h>'],
416         'WebCore::LockBackForwardList': ['<WebCore/FrameLoaderTypes.h>'],
417         'WebCore::NetworkTransactionInformation': ['<WebCore/NetworkLoadInformation.h>'],
418         'WebCore::PasteboardCustomData': ['<WebCore/Pasteboard.h>'],
419         'WebCore::PasteboardImage': ['<WebCore/Pasteboard.h>'],
420         'WebCore::PasteboardURL': ['<WebCore/Pasteboard.h>'],
421         'WebCore::PasteboardWebContent': ['<WebCore/Pasteboard.h>'],
422         'WebCore::PaymentAuthorizationResult': ['<WebCore/ApplePaySessionPaymentRequest.h>'],
423         'WebCore::PaymentMethodUpdate': ['<WebCore/ApplePaySessionPaymentRequest.h>'],
424         'WebCore::PluginInfo': ['<WebCore/PluginData.h>'],
425         'WebCore::PolicyAction': ['<WebCore/FrameLoaderTypes.h>'],
426         'WebCore::PolicyCheckIdentifier': ['<WebCore/FrameLoaderTypes.h>'],
427         'WebCore::RecentSearch': ['<WebCore/SearchPopupMenu.h>'],
428         'WebCore::RouteSharingPolicy': ['<WebCore/AudioSession.h>'],
429         'WebCore::SWServerConnectionIdentifier': ['<WebCore/ServiceWorkerTypes.h>'],
430         'WebCore::ServiceWorkerJobIdentifier': ['<WebCore/ServiceWorkerTypes.h>'],
431         'WebCore::ServiceWorkerOrClientData': ['<WebCore/ServiceWorkerTypes.h>', '<WebCore/ServiceWorkerClientData.h>', '<WebCore/ServiceWorkerData.h>'],
432         'WebCore::ServiceWorkerOrClientIdentifier': ['<WebCore/ServiceWorkerTypes.h>', '<WebCore/ServiceWorkerClientIdentifier.h>'],
433         'WebCore::ServiceWorkerRegistrationIdentifier': ['<WebCore/ServiceWorkerTypes.h>'],
434         'WebCore::ServiceWorkerRegistrationState': ['<WebCore/ServiceWorkerTypes.h>'],
435         'WebCore::ServiceWorkerState': ['<WebCore/ServiceWorkerTypes.h>'],
436         'WebCore::ShippingContactUpdate': ['<WebCore/ApplePaySessionPaymentRequest.h>'],
437         'WebCore::ShippingMethodUpdate': ['<WebCore/ApplePaySessionPaymentRequest.h>'],
438         'WebCore::ShouldNotifyWhenResolved': ['<WebCore/ServiceWorkerTypes.h>'],
439         'WebCore::ShouldSample': ['<WebCore/DiagnosticLoggingClient.h>'],
440         'WebCore::SupportedPluginIdentifier': ['<WebCore/PluginData.h>'],
441         'WebCore::TextCheckingRequestData': ['<WebCore/TextChecking.h>'],
442         'WebCore::TextCheckingResult': ['<WebCore/TextCheckerClient.h>'],
443         'WebCore::TextCheckingType': ['<WebCore/TextChecking.h>'],
444         'WebCore::TextIndicatorData': ['<WebCore/TextIndicator.h>'],
445         'WebCore::ViewportAttributes': ['<WebCore/ViewportArguments.h>'],
446         'WebCore::SelectionRect': ['"EditorState.h"'],
447         'WebKit::ActivityStateChangeID': ['"DrawingAreaInfo.h"'],
448         'WebKit::BackForwardListItemState': ['"SessionState.h"'],
449         'WebKit::LayerHostingMode': ['"LayerTreeContext.h"'],
450         'WebKit::PageState': ['"SessionState.h"'],
451         'WebKit::WebGestureEvent': ['"WebEvent.h"'],
452         'WebKit::WebKeyboardEvent': ['"WebEvent.h"'],
453         'WebKit::WebMouseEvent': ['"WebEvent.h"'],
454         'WebKit::WebTouchEvent': ['"WebEvent.h"'],
455         'WebKit::WebWheelEvent': ['"WebEvent.h"'],
456         'struct WebKit::WebUserScriptData': ['"WebUserContentControllerDataTypes.h"'],
457         'struct WebKit::WebUserStyleSheetData': ['"WebUserContentControllerDataTypes.h"'],
458         'struct WebKit::WebScriptMessageHandlerData': ['"WebUserContentControllerDataTypes.h"'],
459     }
460
461     headers = []
462     for header_info in header_infos_and_types['header_infos']:
463         headers += header_info['headers']
464
465     for type in header_infos_and_types['types']:
466         if type in special_cases:
467             headers += special_cases[type]
468             continue
469
470         # We assume that we must include a header for a type iff it has a scope
471         # resolution operator (::).
472         split = type.split('::')
473         if len(split) < 2:
474             continue
475
476         if split[0] == 'WebKit' or split[0] == 'IPC':
477             headers.append('"%s.h"' % split[1])
478         else:
479             headers.append('<%s/%s.h>' % tuple(split[0:2]))
480
481     return headers
482
483
484 def generate_message_handler(file):
485     receiver = parser.parse(file)
486     header_conditions = {
487         '"%s"' % messages_header_filename(receiver): [None],
488         '"HandleMessage.h"': [None],
489         '"Decoder.h"': [None],
490     }
491
492     type_conditions = {}
493     for parameter in receiver.iterparameters():
494         if not parameter.type in type_conditions:
495             type_conditions[parameter.type] = []
496
497         if not parameter.condition in type_conditions[parameter.type]:
498             type_conditions[parameter.type].append(parameter.condition)
499
500     for parameter in receiver.iterparameters():
501         type = parameter.type
502         conditions = type_conditions[type]
503
504         argument_encoder_headers = argument_coder_headers_for_type(type)
505         if argument_encoder_headers:
506             for header in argument_encoder_headers:
507                 if header not in header_conditions:
508                     header_conditions[header] = []
509                 header_conditions[header].extend(conditions)
510
511         type_headers = headers_for_type(type)
512         for header in type_headers:
513             if header not in header_conditions:
514                 header_conditions[header] = []
515             header_conditions[header].extend(conditions)
516
517     for message in receiver.messages:
518         if message.reply_parameters is not None:
519             for reply_parameter in message.reply_parameters:
520                 type = reply_parameter.type
521                 argument_encoder_headers = argument_coder_headers_for_type(type)
522                 if argument_encoder_headers:
523                     for header in argument_encoder_headers:
524                         if header not in header_conditions:
525                             header_conditions[header] = []
526                         header_conditions[header].append(message.condition)
527
528                 type_headers = headers_for_type(type)
529                 for header in type_headers:
530                     if header not in header_conditions:
531                         header_conditions[header] = []
532                     header_conditions[header].append(message.condition)
533
534     result = []
535
536     result.append(_license_header)
537     result.append('#include "config.h"\n')
538     result.append('\n')
539
540     if receiver.condition:
541         result.append('#if %s\n\n' % receiver.condition)
542
543     result.append('#include "%s.h"\n\n' % receiver.name)
544     for header in sorted(header_conditions):
545         if header_conditions[header] and not None in header_conditions[header]:
546             result.append('#if %s\n' % ' || '.join(set(header_conditions[header])))
547             result += ['#include %s\n' % header]
548             result.append('#endif\n')
549         else:
550             result += ['#include %s\n' % header]
551     result.append('\n')
552
553     delayed_or_async_messages = []
554     for message in receiver.messages:
555         if message.reply_parameters != None and (message.has_attribute(DELAYED_ATTRIBUTE) or message.has_attribute(ASYNC_ATTRIBUTE)):
556             delayed_or_async_messages.append(message)
557
558     if delayed_or_async_messages:
559         result.append('namespace Messages {\n\nnamespace %s {\n\n' % receiver.name)
560
561         for message in delayed_or_async_messages:
562             send_parameters = [(function_parameter_type(x.type, x.kind), x.name) for x in message.reply_parameters]
563
564             if message.condition:
565                 result.append('#if %s\n\n' % message.condition)
566
567             if message.has_attribute(ASYNC_ATTRIBUTE):
568                 move_parameters = message.name, ', '.join([move_type(x.type) for x in message.reply_parameters])
569                 result.append('void %s::callReply(IPC::Decoder& decoder, CompletionHandler<void(%s)>&& completionHandler)\n{\n' % move_parameters)
570                 for x in message.reply_parameters:
571                     result.append('    Optional<%s> %s;\n' % (x.type, x.name))
572                     result.append('    decoder >> %s;\n' % x.name)
573                     result.append('    if (!%s) {\n        ASSERT_NOT_REACHED();\n        return;\n    }\n' % x.name)
574                 result.append('    completionHandler(')
575                 if len(message.reply_parameters):
576                     result.append('WTFMove(*%s)' % ('), WTFMove(*'.join(x.name for x in message.reply_parameters)))
577                 result.append(');\n}\n\n')
578                 result.append('void %s::cancelReply(CompletionHandler<void(%s)>&& completionHandler)\n{\n    completionHandler(' % move_parameters)
579                 result.append(', '.join(['{ }' for x in message.reply_parameters]))
580                 result.append(');\n}\n\n')
581
582             result.append('void %s::send(std::unique_ptr<IPC::Encoder>&& encoder, IPC::Connection& connection' % (message.name))
583             if len(send_parameters):
584                 result.append(', %s' % ', '.join([' '.join(x) for x in send_parameters]))
585             result.append(')\n{\n')
586             result += ['    *encoder << %s;\n' % x.name for x in message.reply_parameters]
587             result.append('    connection.sendSyncReply(WTFMove(encoder));\n')
588             result.append('}\n')
589             result.append('\n')
590
591             if message.condition:
592                 result.append('#endif\n\n')
593
594         result.append('} // namespace %s\n\n} // namespace Messages\n\n' % receiver.name)
595
596     result.append('namespace WebKit {\n\n')
597
598     async_messages = []
599     sync_messages = []
600     for message in receiver.messages:
601         if message.reply_parameters is not None and not message.has_attribute(ASYNC_ATTRIBUTE):
602             sync_messages.append(message)
603         else:
604             async_messages.append(message)
605
606     if async_messages:
607         result.append('void %s::didReceive%sMessage(IPC::Connection& connection, IPC::Decoder& decoder)\n' % (receiver.name, receiver.name if receiver.has_attribute(LEGACY_RECEIVER_ATTRIBUTE) else ''))
608         result.append('{\n')
609         result += [async_message_statement(receiver, message) for message in async_messages]
610         if (receiver.superclass):
611             result.append('    %s::didReceiveMessage(connection, decoder);\n' % (receiver.superclass))
612         else:
613             result.append('    UNUSED_PARAM(connection);\n')
614             result.append('    UNUSED_PARAM(decoder);\n')
615             result.append('    ASSERT_NOT_REACHED();\n')
616         result.append('}\n')
617
618     if sync_messages:
619         result.append('\n')
620         result.append('void %s::didReceiveSync%sMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)\n' % (receiver.name, receiver.name if receiver.has_attribute(LEGACY_RECEIVER_ATTRIBUTE) else ''))
621         result.append('{\n')
622         result += [sync_message_statement(receiver, message) for message in sync_messages]
623         result.append('    UNUSED_PARAM(connection);\n')
624         result.append('    UNUSED_PARAM(decoder);\n')
625         result.append('    UNUSED_PARAM(replyEncoder);\n')
626         result.append('    ASSERT_NOT_REACHED();\n')
627         result.append('}\n')
628
629     result.append('\n} // namespace WebKit\n\n')
630
631     if receiver.condition:
632         result.append('\n#endif // %s\n' % receiver.condition)
633
634     return ''.join(result)