summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/Scripts/webkit2
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/Scripts/webkit2')
-rw-r--r--Source/WebKit2/Scripts/webkit2/__init__.py23
-rw-r--r--Source/WebKit2/Scripts/webkit2/messages.py519
-rw-r--r--Source/WebKit2/Scripts/webkit2/messages_unittest.py592
3 files changed, 1134 insertions, 0 deletions
diff --git a/Source/WebKit2/Scripts/webkit2/__init__.py b/Source/WebKit2/Scripts/webkit2/__init__.py
new file mode 100644
index 0000000..27e3fc3
--- /dev/null
+++ b/Source/WebKit2/Scripts/webkit2/__init__.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2010 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Required for Python to search this directory for module files
diff --git a/Source/WebKit2/Scripts/webkit2/messages.py b/Source/WebKit2/Scripts/webkit2/messages.py
new file mode 100644
index 0000000..8fc0eaa
--- /dev/null
+++ b/Source/WebKit2/Scripts/webkit2/messages.py
@@ -0,0 +1,519 @@
+# Copyright (C) 2010 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import collections
+import itertools
+import re
+
+
+_license_header = """/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+"""
+
+class MessageReceiver(object):
+ def __init__(self, name, messages, condition):
+ self.name = name
+ self.messages = messages
+ self.condition = condition
+
+ def iterparameters(self):
+ return itertools.chain((parameter for message in self.messages for parameter in message.parameters),
+ (reply_parameter for message in self.messages if message.reply_parameters for reply_parameter in message.reply_parameters))
+
+ @classmethod
+ def parse(cls, file):
+ destination = None
+ messages = []
+ condition = None
+ master_condition = None
+ for line in file:
+ match = re.search(r'messages -> ([A-Za-z_0-9]+) {', line)
+ if match:
+ if condition:
+ master_condition = condition
+ condition = None
+ destination = match.group(1)
+ continue
+ if line.startswith('#'):
+ if line.startswith('#if '):
+ condition = line.rstrip()[4:]
+ elif line.startswith('#endif'):
+ condition = None
+ continue
+ match = re.search(r'([A-Za-z_0-9]+)\((.*?)\)(?:(?:\s+->\s+)\((.*?)\)(?:\s+(delayed))?)?', line)
+ if match:
+ name, parameters_string, reply_parameters_string, delayed_string = match.groups()
+ if parameters_string:
+ parameters = parse_parameter_string(parameters_string)
+ else:
+ parameters = []
+
+ delayed = delayed_string == 'delayed'
+
+ if reply_parameters_string:
+ reply_parameters = parse_parameter_string(reply_parameters_string)
+ elif reply_parameters_string == '':
+ reply_parameters = []
+ else:
+ reply_parameters = None
+
+ messages.append(Message(name, parameters, reply_parameters, delayed, condition))
+ return MessageReceiver(destination, messages, master_condition)
+
+
+class Message(object):
+ def __init__(self, name, parameters, reply_parameters, delayed, condition):
+ self.name = name
+ self.parameters = parameters
+ self.reply_parameters = reply_parameters
+ if self.reply_parameters is not None:
+ self.delayed = delayed
+ self.condition = condition
+ if len(self.parameters) != 0:
+ self.is_variadic = parameter_type_is_variadic(self.parameters[-1].type)
+ else:
+ self.is_variadic = False
+
+ def id(self):
+ return '%sID' % self.name
+
+
+class Parameter(object):
+ def __init__(self, type, name):
+ self.type = type
+ self.name = name
+
+
+def parse_parameter_string(parameter_string):
+ return [Parameter(*type_and_name.rsplit(' ', 1)) for type_and_name in parameter_string.split(', ')]
+
+
+def messages_header_filename(receiver):
+ return '%sMessages.h' % receiver.name
+
+
+def surround_in_condition(string, condition):
+ if not condition:
+ return string
+ return '#if %s\n%s#endif\n' % (condition, string)
+
+
+def messages_to_kind_enum(messages):
+ result = []
+ result.append('enum Kind {\n')
+ result += [surround_in_condition(' %s,\n' % message.id(), message.condition) for message in messages]
+ result.append('};\n')
+ return ''.join(result)
+
+
+def parameter_type_is_variadic(type):
+ variadic_types = frozenset([
+ 'WebKit::InjectedBundleUserMessageEncoder',
+ 'WebKit::WebContextUserMessageEncoder',
+ ])
+
+ return type in variadic_types
+
+def function_parameter_type(type):
+ # Don't use references for built-in types.
+ builtin_types = frozenset([
+ 'bool',
+ 'float',
+ 'double',
+ 'uint8_t',
+ 'uint16_t',
+ 'uint32_t',
+ 'uint64_t',
+ 'int8_t',
+ 'int16_t',
+ 'int32_t',
+ 'int64_t',
+ ])
+
+ if type in builtin_types:
+ return type
+
+ return 'const %s&' % type
+
+
+def reply_parameter_type(type):
+ return '%s&' % type
+
+
+def arguments_type(parameters, parameter_type_function):
+ arguments_type = 'CoreIPC::Arguments%d' % len(parameters)
+ if len(parameters):
+ arguments_type = '%s<%s>' % (arguments_type, ', '.join(parameter_type_function(parameter.type) for parameter in parameters))
+ return arguments_type
+
+
+def base_class(message):
+ return arguments_type(message.parameters, function_parameter_type)
+
+
+def reply_type(message):
+ return arguments_type(message.reply_parameters, reply_parameter_type)
+
+
+def decode_type(message):
+ if message.is_variadic:
+ return arguments_type(message.parameters[:-1], reply_parameter_type)
+ return base_class(message)
+
+
+def delayed_reply_type(message):
+ return arguments_type(message.reply_parameters, function_parameter_type)
+
+
+def message_to_struct_declaration(message):
+ result = []
+ function_parameters = [(function_parameter_type(x.type), x.name) for x in message.parameters]
+ result.append('struct %s : %s' % (message.name, base_class(message)))
+ result.append(' {\n')
+ result.append(' static const Kind messageID = %s;\n' % message.id())
+ if message.reply_parameters != None:
+ if message.delayed:
+ send_parameters = [(function_parameter_type(x.type), x.name) for x in message.reply_parameters]
+ result.append(' struct DelayedReply {\n')
+ result.append(' DelayedReply(PassRefPtr<CoreIPC::Connection> connection, PassOwnPtr<CoreIPC::ArgumentDecoder> arguments)\n')
+ result.append(' : m_connection(connection)\n')
+ result.append(' , m_arguments(arguments)\n')
+ result.append(' {\n')
+ result.append(' }\n')
+ result.append('\n')
+ result.append(' bool send(%s)\n' % ', '.join([' '.join(x) for x in send_parameters]))
+ result.append(' {\n')
+ result.append(' ASSERT(m_arguments);\n')
+ result += [' m_arguments->encode(%s);\n' % x.name for x in message.reply_parameters]
+ result.append(' bool result = m_connection->sendSyncReply(m_arguments.release());\n')
+ result.append(' m_connection = nullptr;\n')
+ result.append(' return result;\n')
+ result.append(' }\n')
+ result.append('\n')
+ result.append(' private:\n')
+ result.append(' RefPtr<CoreIPC::Connection> m_connection;\n')
+ result.append(' OwnPtr<CoreIPC::ArgumentDecoder> m_arguments;\n')
+ result.append(' };\n\n')
+ else:
+ result.append(' typedef %s Reply;\n' % reply_type(message))
+
+ result.append(' typedef %s DecodeType;\n' % decode_type(message))
+ if len(function_parameters):
+ result.append(' %s%s(%s)' % (len(function_parameters) == 1 and 'explicit ' or '', message.name, ', '.join([' '.join(x) for x in function_parameters])))
+ result.append('\n : %s(%s)\n' % (base_class(message), ', '.join([x[1] for x in function_parameters])))
+ result.append(' {\n')
+ result.append(' }\n')
+ result.append('};\n')
+ return surround_in_condition(''.join(result), message.condition)
+
+
+def struct_or_class(namespace, type):
+ structs = frozenset([
+ 'WebCore::CompositionUnderline',
+ 'WebCore::KeypressCommand',
+ 'WebCore::PluginInfo',
+ 'WebCore::PrintInfo',
+ 'WebCore::ViewportArguments',
+ 'WebCore::WindowFeatures',
+ 'WebKit::DrawingAreaInfo',
+ 'WebKit::PlatformPopupMenuData',
+ 'WebKit::PluginProcessCreationParameters',
+ 'WebKit::WebNavigationDataStore',
+ 'WebKit::WebOpenPanelParameters::Data',
+ 'WebKit::WebPageCreationParameters',
+ 'WebKit::WebPreferencesStore',
+ 'WebKit::WebProcessCreationParameters',
+ ])
+
+ qualified_name = '%s::%s' % (namespace, type)
+ if qualified_name in structs:
+ return 'struct %s' % type
+
+ return 'class %s' % type
+
+def forward_declarations_for_namespace(namespace, types):
+ result = []
+ result.append('namespace %s {\n' % namespace)
+ result += [' %s;\n' % struct_or_class(namespace, x) for x in types]
+ result.append('}\n')
+ return ''.join(result)
+
+
+def forward_declarations_and_headers(receiver):
+ types_by_namespace = collections.defaultdict(set)
+
+ headers = set([
+ '"Arguments.h"',
+ '"MessageID.h"',
+ ])
+
+ for parameter in receiver.iterparameters():
+ type = parameter.type
+
+ if type.find('<') != -1:
+ # Don't forward declare class templates.
+ headers.update(headers_for_type(type))
+ continue
+
+ split = type.split('::')
+
+ if len(split) == 2:
+ namespace = split[0]
+ inner_type = split[1]
+ types_by_namespace[namespace].add(inner_type)
+ elif len(split) > 2:
+ # We probably have a nested struct, which means we can't forward declare it.
+ # Include its header instead.
+ headers.update(headers_for_type(type))
+
+ forward_declarations = '\n'.join([forward_declarations_for_namespace(namespace, types) for (namespace, types) in sorted(types_by_namespace.iteritems())])
+ headers = ['#include %s\n' % header for header in sorted(headers)]
+
+ return (forward_declarations, headers)
+
+def generate_messages_header(file):
+ receiver = MessageReceiver.parse(file)
+ header_guard = messages_header_filename(receiver).replace('.', '_')
+
+ result = []
+
+ result.append(_license_header)
+ result.append('\n')
+
+ result.append('#ifndef %s\n' % header_guard)
+ result.append('#define %s\n\n' % header_guard)
+
+ if receiver.condition:
+ result.append('#if %s\n\n' % receiver.condition)
+
+ forward_declarations, headers = forward_declarations_and_headers(receiver)
+
+ result += headers
+ result.append('\n')
+
+ result.append(forward_declarations)
+ result.append('\n')
+
+ result.append('namespace Messages {\n\nnamespace %s {\n\n' % receiver.name)
+ result.append(messages_to_kind_enum(receiver.messages))
+ result.append('\n')
+ result.append('\n'.join([message_to_struct_declaration(x) for x in receiver.messages]))
+ result.append('\n} // namespace %s\n\n} // namespace Messages\n' % receiver.name)
+
+ result.append('\nnamespace CoreIPC {\n\n')
+ result.append('template<> struct MessageKindTraits<Messages::%s::Kind> {\n' % receiver.name)
+ result.append(' static const MessageClass messageClass = MessageClass%s;\n' % receiver.name)
+ result.append('};\n')
+ result.append('\n} // namespace CoreIPC\n')
+
+ if receiver.condition:
+ result.append('\n#endif // %s\n' % receiver.condition)
+
+ result.append('\n#endif // %s\n' % header_guard)
+
+ return ''.join(result)
+
+
+def handler_function(receiver, message):
+ return '%s::%s' % (receiver.name, message.name[0].lower() + message.name[1:])
+
+
+def async_case_statement(receiver, message):
+ dispatch_function = 'handleMessage'
+ if message.is_variadic:
+ dispatch_function += 'Variadic'
+
+ result = []
+ result.append(' case Messages::%s::%s:\n' % (receiver.name, message.id()))
+ result.append(' CoreIPC::%s<Messages::%s::%s>(arguments, this, &%s);\n' % (dispatch_function, receiver.name, message.name, handler_function(receiver, message)))
+ result.append(' return;\n')
+ return surround_in_condition(''.join(result), message.condition)
+
+
+def sync_case_statement(receiver, message):
+ result = []
+ result.append(' case Messages::%s::%s:\n' % (receiver.name, message.id()))
+ result.append(' CoreIPC::handleMessage<Messages::%s::%s>(arguments, reply, this, &%s);\n' % (receiver.name, message.name, handler_function(receiver, message)))
+ # FIXME: Handle delayed replies
+ result.append(' return CoreIPC::AutomaticReply;\n')
+ return surround_in_condition(''.join(result), message.condition)
+
+
+def argument_coder_headers_for_type(type):
+ # Check for Vector.
+ match = re.search(r'Vector<(.+)>', type)
+ if match:
+ element_type = match.groups()[0].strip()
+ return ['"ArgumentCoders.h"'] + argument_coder_headers_for_type(element_type)
+
+ special_cases = {
+ 'WTF::String': '"ArgumentCoders.h"',
+ 'WebKit::InjectedBundleUserMessageEncoder': '"InjectedBundleUserMessageCoders.h"',
+ 'WebKit::WebContextUserMessageEncoder': '"WebContextUserMessageCoders.h"',
+ }
+
+ if type in special_cases:
+ return [special_cases[type]]
+
+ split = type.split('::')
+ if len(split) < 2:
+ return []
+ if split[0] == 'WebCore':
+ return ['"WebCoreArgumentCoders.h"']
+
+ return []
+
+
+def headers_for_type(type):
+ # Check for Vector.
+ match = re.search(r'Vector<(.+)>', type)
+ if match:
+ element_type = match.groups()[0].strip()
+ return ['<wtf/Vector.h>'] + headers_for_type(element_type)
+
+ special_cases = {
+ 'WTF::String': '<wtf/text/WTFString.h>',
+ 'WebCore::CompositionUnderline': '<WebCore/Editor.h>',
+ 'WebCore::KeypressCommand': '<WebCore/KeyboardEvent.h>',
+ 'WebCore::PluginInfo': '<WebCore/PluginData.h>',
+ 'WebCore::TextCheckingResult': '<WebCore/EditorClient.h>',
+ 'WebKit::WebKeyboardEvent': '"WebEvent.h"',
+ 'WebKit::WebMouseEvent': '"WebEvent.h"',
+ 'WebKit::WebTouchEvent': '"WebEvent.h"',
+ 'WebKit::WebWheelEvent': '"WebEvent.h"',
+ }
+ if type in special_cases:
+ return [special_cases[type]]
+
+ # We assume that we must include a header for a type iff it has a scope
+ # resolution operator (::).
+ split = type.split('::')
+ if len(split) < 2:
+ return []
+ if split[0] == 'WebKit' or split[0] == 'CoreIPC':
+ return ['"%s.h"' % split[1]]
+ return ['<%s/%s.h>' % tuple(split)]
+
+
+def generate_message_handler(file):
+ receiver = MessageReceiver.parse(file)
+ headers = set([
+ '"%s"' % messages_header_filename(receiver),
+ '"HandleMessage.h"',
+ '"ArgumentDecoder.h"',
+ ])
+
+ for parameter in receiver.iterparameters():
+ type = parameter.type
+ argument_encoder_headers = argument_coder_headers_for_type(parameter.type)
+ if argument_encoder_headers:
+ headers.update(argument_encoder_headers)
+ continue
+
+ type_headers = headers_for_type(type)
+ headers.update(type_headers)
+
+ for message in receiver.messages:
+ if message.reply_parameters is not None:
+ for reply_parameter in message.reply_parameters:
+ type = reply_parameter.type
+ argument_encoder_headers = argument_coder_headers_for_type(type)
+ if argument_encoder_headers:
+ headers.update(argument_encoder_headers)
+ continue
+
+ type_headers = headers_for_type(type)
+ headers.update(type_headers)
+
+ result = []
+
+ result.append(_license_header)
+ result.append('\n')
+
+ if receiver.condition:
+ result.append('#if %s\n\n' % receiver.condition)
+
+ result.append('#include "%s.h"\n\n' % receiver.name)
+ result += ['#include %s\n' % header for header in sorted(headers)]
+ result.append('\n')
+
+ result.append('namespace WebKit {\n\n')
+
+ async_messages = []
+ sync_messages = []
+ for message in receiver.messages:
+ if message.reply_parameters is not None:
+ sync_messages.append(message)
+ else:
+ async_messages.append(message)
+
+ if async_messages:
+ result.append('void %s::didReceive%sMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)\n' % (receiver.name, receiver.name))
+ result.append('{\n')
+ result.append(' switch (messageID.get<Messages::%s::Kind>()) {\n' % receiver.name)
+ result += [async_case_statement(receiver, message) for message in async_messages]
+ result.append(' default:\n')
+ result.append(' break;\n')
+ result.append(' }\n\n')
+ result.append(' ASSERT_NOT_REACHED();\n')
+ result.append('}\n')
+
+ if sync_messages:
+ result.append('\n')
+ result.append('CoreIPC::SyncReplyMode %s::didReceiveSync%sMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)\n' % (receiver.name, receiver.name))
+ result.append('{\n')
+ result.append(' switch (messageID.get<Messages::%s::Kind>()) {\n' % receiver.name)
+ result += [sync_case_statement(receiver, message) for message in sync_messages]
+ result.append(' default:\n')
+ result.append(' break;\n')
+ result.append(' }\n\n')
+ result.append(' ASSERT_NOT_REACHED();\n')
+ result.append(' return CoreIPC::AutomaticReply;\n')
+ result.append('}\n')
+
+ result.append('\n} // namespace WebKit\n')
+
+ if receiver.condition:
+ result.append('\n#endif // %s\n' % receiver.condition)
+
+ return ''.join(result)
diff --git a/Source/WebKit2/Scripts/webkit2/messages_unittest.py b/Source/WebKit2/Scripts/webkit2/messages_unittest.py
new file mode 100644
index 0000000..25123c0
--- /dev/null
+++ b/Source/WebKit2/Scripts/webkit2/messages_unittest.py
@@ -0,0 +1,592 @@
+# Copyright (C) 2010 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import unittest
+from StringIO import StringIO
+
+import messages
+
+_messages_file_contents = """# Copyright (C) 2010 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#if ENABLE(WEBKIT2)
+
+messages -> WebPage {
+ LoadURL(WTF::String url)
+#if ENABLE(TOUCH_EVENTS)
+ TouchEvent(WebKit::WebTouchEvent event)
+#endif
+ DidReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction)
+ Close()
+
+ PreferencesDidChange(WebKit::WebPreferencesStore store)
+ SendDoubleAndFloat(double d, float f)
+ SendInts(Vector<uint64_t> ints, Vector<Vector<uint64_t> > intVectors)
+
+ CreatePlugin(uint64_t pluginInstanceID, WebKit::Plugin::Parameters parameters) -> (bool result)
+ RunJavaScriptAlert(uint64_t frameID, WTF::String message) -> ()
+ GetPlugins(bool refresh) -> (Vector<WebCore::PluginInfo> plugins)
+ GetPluginProcessConnection(WTF::String pluginPath) -> (CoreIPC::Connection::Handle connectionHandle) delayed
+
+ DidCreateWebProcessConnection(CoreIPC::MachPort connectionIdentifier)
+
+#if PLATFORM(MAC)
+ # Keyboard support
+ InterpretKeyEvent(uint32_t type) -> (Vector<WebCore::KeypressCommand> commandName)
+#endif
+}
+
+#endif
+"""
+
+_expected_results = {
+ 'name': 'WebPage',
+ 'condition': 'ENABLE(WEBKIT2)',
+ 'messages': (
+ {
+ 'name': 'LoadURL',
+ 'parameters': (
+ ('WTF::String', 'url'),
+ ),
+ 'condition': None,
+ },
+ {
+ 'name': 'TouchEvent',
+ 'parameters': (
+ ('WebKit::WebTouchEvent', 'event'),
+ ),
+ 'condition': 'ENABLE(TOUCH_EVENTS)',
+ },
+ {
+ 'name': 'DidReceivePolicyDecision',
+ 'parameters': (
+ ('uint64_t', 'frameID'),
+ ('uint64_t', 'listenerID'),
+ ('uint32_t', 'policyAction'),
+ ),
+ 'condition': None,
+ },
+ {
+ 'name': 'Close',
+ 'parameters': (),
+ 'condition': None,
+ },
+ {
+ 'name': 'PreferencesDidChange',
+ 'parameters': (
+ ('WebKit::WebPreferencesStore', 'store'),
+ ),
+ 'condition': None,
+ },
+ {
+ 'name': 'SendDoubleAndFloat',
+ 'parameters': (
+ ('double', 'd'),
+ ('float', 'f'),
+ ),
+ 'condition': None,
+ },
+ {
+ 'name': 'SendInts',
+ 'parameters': (
+ ('Vector<uint64_t>', 'ints'),
+ ('Vector<Vector<uint64_t> >', 'intVectors')
+ ),
+ 'condition': None,
+ },
+ {
+ 'name': 'CreatePlugin',
+ 'parameters': (
+ ('uint64_t', 'pluginInstanceID'),
+ ('WebKit::Plugin::Parameters', 'parameters')
+ ),
+ 'reply_parameters': (
+ ('bool', 'result'),
+ ),
+ 'condition': None,
+ },
+ {
+ 'name': 'RunJavaScriptAlert',
+ 'parameters': (
+ ('uint64_t', 'frameID'),
+ ('WTF::String', 'message')
+ ),
+ 'reply_parameters': (),
+ 'condition': None,
+ },
+ {
+ 'name': 'GetPlugins',
+ 'parameters': (
+ ('bool', 'refresh'),
+ ),
+ 'reply_parameters': (
+ ('Vector<WebCore::PluginInfo>', 'plugins'),
+ ),
+ 'condition': None,
+ },
+ {
+ 'name': 'GetPluginProcessConnection',
+ 'parameters': (
+ ('WTF::String', 'pluginPath'),
+ ),
+ 'reply_parameters': (
+ ('CoreIPC::Connection::Handle', 'connectionHandle'),
+ ),
+ 'condition': None,
+ },
+ {
+ 'name': 'DidCreateWebProcessConnection',
+ 'parameters': (
+ ('CoreIPC::MachPort', 'connectionIdentifier'),
+ ),
+ 'condition': None,
+ },
+ {
+ 'name': 'InterpretKeyEvent',
+ 'parameters': (
+ ('uint32_t', 'type'),
+ ),
+ 'reply_parameters': (
+ ('Vector<WebCore::KeypressCommand>', 'commandName'),
+ ),
+ 'condition': 'PLATFORM(MAC)',
+ },
+ ),
+}
+
+
+class MessagesTest(unittest.TestCase):
+ def setUp(self):
+ self.receiver = messages.MessageReceiver.parse(StringIO(_messages_file_contents))
+
+
+class ParsingTest(MessagesTest):
+ def check_message(self, message, expected_message):
+ self.assertEquals(message.name, expected_message['name'])
+ self.assertEquals(len(message.parameters), len(expected_message['parameters']))
+ for index, parameter in enumerate(message.parameters):
+ self.assertEquals(parameter.type, expected_message['parameters'][index][0])
+ self.assertEquals(parameter.name, expected_message['parameters'][index][1])
+ if message.reply_parameters != None:
+ for index, parameter in enumerate(message.reply_parameters):
+ self.assertEquals(parameter.type, expected_message['reply_parameters'][index][0])
+ self.assertEquals(parameter.name, expected_message['reply_parameters'][index][1])
+ else:
+ self.assertFalse('reply_parameters' in expected_message)
+ self.assertEquals(message.condition, expected_message['condition'])
+
+ def test_receiver(self):
+ """Receiver should be parsed as expected"""
+ self.assertEquals(self.receiver.name, _expected_results['name'])
+ self.assertEquals(self.receiver.condition, _expected_results['condition'])
+ self.assertEquals(len(self.receiver.messages), len(_expected_results['messages']))
+ for index, message in enumerate(self.receiver.messages):
+ self.check_message(message, _expected_results['messages'][index])
+
+_expected_header = """/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebPageMessages_h
+#define WebPageMessages_h
+
+#if ENABLE(WEBKIT2)
+
+#include "Arguments.h"
+#include "Connection.h"
+#include "MessageID.h"
+#include "Plugin.h"
+#include <WebCore/KeyboardEvent.h>
+#include <WebCore/PluginData.h>
+#include <wtf/Vector.h>
+
+namespace CoreIPC {
+ class MachPort;
+}
+
+namespace WTF {
+ class String;
+}
+
+namespace WebKit {
+ struct WebPreferencesStore;
+ class WebTouchEvent;
+}
+
+namespace Messages {
+
+namespace WebPage {
+
+enum Kind {
+ LoadURLID,
+#if ENABLE(TOUCH_EVENTS)
+ TouchEventID,
+#endif
+ DidReceivePolicyDecisionID,
+ CloseID,
+ PreferencesDidChangeID,
+ SendDoubleAndFloatID,
+ SendIntsID,
+ CreatePluginID,
+ RunJavaScriptAlertID,
+ GetPluginsID,
+ GetPluginProcessConnectionID,
+ DidCreateWebProcessConnectionID,
+#if PLATFORM(MAC)
+ InterpretKeyEventID,
+#endif
+};
+
+struct LoadURL : CoreIPC::Arguments1<const WTF::String&> {
+ static const Kind messageID = LoadURLID;
+ typedef CoreIPC::Arguments1<const WTF::String&> DecodeType;
+ explicit LoadURL(const WTF::String& url)
+ : CoreIPC::Arguments1<const WTF::String&>(url)
+ {
+ }
+};
+
+#if ENABLE(TOUCH_EVENTS)
+struct TouchEvent : CoreIPC::Arguments1<const WebKit::WebTouchEvent&> {
+ static const Kind messageID = TouchEventID;
+ typedef CoreIPC::Arguments1<const WebKit::WebTouchEvent&> DecodeType;
+ explicit TouchEvent(const WebKit::WebTouchEvent& event)
+ : CoreIPC::Arguments1<const WebKit::WebTouchEvent&>(event)
+ {
+ }
+};
+#endif
+
+struct DidReceivePolicyDecision : CoreIPC::Arguments3<uint64_t, uint64_t, uint32_t> {
+ static const Kind messageID = DidReceivePolicyDecisionID;
+ typedef CoreIPC::Arguments3<uint64_t, uint64_t, uint32_t> DecodeType;
+ DidReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction)
+ : CoreIPC::Arguments3<uint64_t, uint64_t, uint32_t>(frameID, listenerID, policyAction)
+ {
+ }
+};
+
+struct Close : CoreIPC::Arguments0 {
+ static const Kind messageID = CloseID;
+ typedef CoreIPC::Arguments0 DecodeType;
+};
+
+struct PreferencesDidChange : CoreIPC::Arguments1<const WebKit::WebPreferencesStore&> {
+ static const Kind messageID = PreferencesDidChangeID;
+ typedef CoreIPC::Arguments1<const WebKit::WebPreferencesStore&> DecodeType;
+ explicit PreferencesDidChange(const WebKit::WebPreferencesStore& store)
+ : CoreIPC::Arguments1<const WebKit::WebPreferencesStore&>(store)
+ {
+ }
+};
+
+struct SendDoubleAndFloat : CoreIPC::Arguments2<double, float> {
+ static const Kind messageID = SendDoubleAndFloatID;
+ typedef CoreIPC::Arguments2<double, float> DecodeType;
+ SendDoubleAndFloat(double d, float f)
+ : CoreIPC::Arguments2<double, float>(d, f)
+ {
+ }
+};
+
+struct SendInts : CoreIPC::Arguments2<const Vector<uint64_t>&, const Vector<Vector<uint64_t> >&> {
+ static const Kind messageID = SendIntsID;
+ typedef CoreIPC::Arguments2<const Vector<uint64_t>&, const Vector<Vector<uint64_t> >&> DecodeType;
+ SendInts(const Vector<uint64_t>& ints, const Vector<Vector<uint64_t> >& intVectors)
+ : CoreIPC::Arguments2<const Vector<uint64_t>&, const Vector<Vector<uint64_t> >&>(ints, intVectors)
+ {
+ }
+};
+
+struct CreatePlugin : CoreIPC::Arguments2<uint64_t, const WebKit::Plugin::Parameters&> {
+ static const Kind messageID = CreatePluginID;
+ typedef CoreIPC::Arguments1<bool&> Reply;
+ typedef CoreIPC::Arguments2<uint64_t, const WebKit::Plugin::Parameters&> DecodeType;
+ CreatePlugin(uint64_t pluginInstanceID, const WebKit::Plugin::Parameters& parameters)
+ : CoreIPC::Arguments2<uint64_t, const WebKit::Plugin::Parameters&>(pluginInstanceID, parameters)
+ {
+ }
+};
+
+struct RunJavaScriptAlert : CoreIPC::Arguments2<uint64_t, const WTF::String&> {
+ static const Kind messageID = RunJavaScriptAlertID;
+ typedef CoreIPC::Arguments0 Reply;
+ typedef CoreIPC::Arguments2<uint64_t, const WTF::String&> DecodeType;
+ RunJavaScriptAlert(uint64_t frameID, const WTF::String& message)
+ : CoreIPC::Arguments2<uint64_t, const WTF::String&>(frameID, message)
+ {
+ }
+};
+
+struct GetPlugins : CoreIPC::Arguments1<bool> {
+ static const Kind messageID = GetPluginsID;
+ typedef CoreIPC::Arguments1<Vector<WebCore::PluginInfo>&> Reply;
+ typedef CoreIPC::Arguments1<bool> DecodeType;
+ explicit GetPlugins(bool refresh)
+ : CoreIPC::Arguments1<bool>(refresh)
+ {
+ }
+};
+
+struct GetPluginProcessConnection : CoreIPC::Arguments1<const WTF::String&> {
+ static const Kind messageID = GetPluginProcessConnectionID;
+ struct DelayedReply {
+ DelayedReply(PassRefPtr<CoreIPC::Connection> connection, PassOwnPtr<CoreIPC::ArgumentDecoder> arguments)
+ : m_connection(connection)
+ , m_arguments(arguments)
+ {
+ }
+
+ bool send(const CoreIPC::Connection::Handle& connectionHandle)
+ {
+ ASSERT(m_arguments);
+ m_arguments->encode(connectionHandle);
+ bool result = m_connection->sendSyncReply(m_arguments.release());
+ m_connection = nullptr;
+ return result;
+ }
+
+ private:
+ RefPtr<CoreIPC::Connection> m_connection;
+ OwnPtr<CoreIPC::ArgumentDecoder> m_arguments;
+ };
+
+ typedef CoreIPC::Arguments1<const WTF::String&> DecodeType;
+ explicit GetPluginProcessConnection(const WTF::String& pluginPath)
+ : CoreIPC::Arguments1<const WTF::String&>(pluginPath)
+ {
+ }
+};
+
+struct DidCreateWebProcessConnection : CoreIPC::Arguments1<const CoreIPC::MachPort&> {
+ static const Kind messageID = DidCreateWebProcessConnectionID;
+ typedef CoreIPC::Arguments1<const CoreIPC::MachPort&> DecodeType;
+ explicit DidCreateWebProcessConnection(const CoreIPC::MachPort& connectionIdentifier)
+ : CoreIPC::Arguments1<const CoreIPC::MachPort&>(connectionIdentifier)
+ {
+ }
+};
+
+#if PLATFORM(MAC)
+struct InterpretKeyEvent : CoreIPC::Arguments1<uint32_t> {
+ static const Kind messageID = InterpretKeyEventID;
+ typedef CoreIPC::Arguments1<Vector<WebCore::KeypressCommand>&> Reply;
+ typedef CoreIPC::Arguments1<uint32_t> DecodeType;
+ explicit InterpretKeyEvent(uint32_t type)
+ : CoreIPC::Arguments1<uint32_t>(type)
+ {
+ }
+};
+#endif
+
+} // namespace WebPage
+
+} // namespace Messages
+
+namespace CoreIPC {
+
+template<> struct MessageKindTraits<Messages::WebPage::Kind> {
+ static const MessageClass messageClass = MessageClassWebPage;
+};
+
+} // namespace CoreIPC
+
+#endif // ENABLE(WEBKIT2)
+
+#endif // WebPageMessages_h
+"""
+
+_expected_receiver_implementation = """/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if ENABLE(WEBKIT2)
+
+#include "WebPage.h"
+
+#include "ArgumentCoders.h"
+#include "ArgumentDecoder.h"
+#include "Connection.h"
+#include "HandleMessage.h"
+#include "MachPort.h"
+#include "Plugin.h"
+#include "WebCoreArgumentCoders.h"
+#include "WebEvent.h"
+#include "WebPageMessages.h"
+#include "WebPreferencesStore.h"
+
+namespace WebKit {
+
+void WebPage::didReceiveWebPageMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
+{
+ switch (messageID.get<Messages::WebPage::Kind>()) {
+ case Messages::WebPage::LoadURLID:
+ CoreIPC::handleMessage<Messages::WebPage::LoadURL>(arguments, this, &WebPage::loadURL);
+ return;
+#if ENABLE(TOUCH_EVENTS)
+ case Messages::WebPage::TouchEventID:
+ CoreIPC::handleMessage<Messages::WebPage::TouchEvent>(arguments, this, &WebPage::touchEvent);
+ return;
+#endif
+ case Messages::WebPage::DidReceivePolicyDecisionID:
+ CoreIPC::handleMessage<Messages::WebPage::DidReceivePolicyDecision>(arguments, this, &WebPage::didReceivePolicyDecision);
+ return;
+ case Messages::WebPage::CloseID:
+ CoreIPC::handleMessage<Messages::WebPage::Close>(arguments, this, &WebPage::close);
+ return;
+ case Messages::WebPage::PreferencesDidChangeID:
+ CoreIPC::handleMessage<Messages::WebPage::PreferencesDidChange>(arguments, this, &WebPage::preferencesDidChange);
+ return;
+ case Messages::WebPage::SendDoubleAndFloatID:
+ CoreIPC::handleMessage<Messages::WebPage::SendDoubleAndFloat>(arguments, this, &WebPage::sendDoubleAndFloat);
+ return;
+ case Messages::WebPage::SendIntsID:
+ CoreIPC::handleMessage<Messages::WebPage::SendInts>(arguments, this, &WebPage::sendInts);
+ return;
+ case Messages::WebPage::DidCreateWebProcessConnectionID:
+ CoreIPC::handleMessage<Messages::WebPage::DidCreateWebProcessConnection>(arguments, this, &WebPage::didCreateWebProcessConnection);
+ return;
+ default:
+ break;
+ }
+
+ ASSERT_NOT_REACHED();
+}
+
+CoreIPC::SyncReplyMode WebPage::didReceiveSyncWebPageMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)
+{
+ switch (messageID.get<Messages::WebPage::Kind>()) {
+ case Messages::WebPage::CreatePluginID:
+ CoreIPC::handleMessage<Messages::WebPage::CreatePlugin>(arguments, reply, this, &WebPage::createPlugin);
+ return CoreIPC::AutomaticReply;
+ case Messages::WebPage::RunJavaScriptAlertID:
+ CoreIPC::handleMessage<Messages::WebPage::RunJavaScriptAlert>(arguments, reply, this, &WebPage::runJavaScriptAlert);
+ return CoreIPC::AutomaticReply;
+ case Messages::WebPage::GetPluginsID:
+ CoreIPC::handleMessage<Messages::WebPage::GetPlugins>(arguments, reply, this, &WebPage::getPlugins);
+ return CoreIPC::AutomaticReply;
+ case Messages::WebPage::GetPluginProcessConnectionID:
+ CoreIPC::handleMessage<Messages::WebPage::GetPluginProcessConnection>(arguments, reply, this, &WebPage::getPluginProcessConnection);
+ return CoreIPC::AutomaticReply;
+#if PLATFORM(MAC)
+ case Messages::WebPage::InterpretKeyEventID:
+ CoreIPC::handleMessage<Messages::WebPage::InterpretKeyEvent>(arguments, reply, this, &WebPage::interpretKeyEvent);
+ return CoreIPC::AutomaticReply;
+#endif
+ default:
+ break;
+ }
+
+ ASSERT_NOT_REACHED();
+ return CoreIPC::AutomaticReply;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(WEBKIT2)
+"""
+
+
+class GeneratedFileContentsTest(unittest.TestCase):
+ def assertGeneratedFileContentsEqual(self, first, second):
+ first_list = first.split('\n')
+ second_list = second.split('\n')
+
+ for index, first_line in enumerate(first_list):
+ self.assertEquals(first_line, second_list[index])
+
+ self.assertEquals(len(first_list), len(second_list))
+
+
+class HeaderTest(GeneratedFileContentsTest):
+ def test_header(self):
+ file_contents = messages.generate_messages_header(StringIO(_messages_file_contents))
+ self.assertGeneratedFileContentsEqual(file_contents, _expected_header)
+
+
+class ReceiverImplementationTest(GeneratedFileContentsTest):
+ def test_receiver_implementation(self):
+ file_contents = messages.generate_message_handler(StringIO(_messages_file_contents))
+ self.assertGeneratedFileContentsEqual(file_contents, _expected_receiver_implementation)
+
+
+if __name__ == '__main__':
+ unittest.main()