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