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