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