summaryrefslogtreecommitdiffstats
path: root/chromium/mojo/public
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/mojo/public
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/mojo/public')
-rw-r--r--chromium/mojo/public/DEPS6
-rw-r--r--chromium/mojo/public/README.md43
-rw-r--r--chromium/mojo/public/bindings/mojom_bindings_generator.gypi82
-rw-r--r--chromium/mojo/public/c/DEPS16
-rw-r--r--chromium/mojo/public/c/README.md45
-rw-r--r--chromium/mojo/public/c/environment/async_waiter.h30
-rw-r--r--chromium/mojo/public/c/environment/logger.h54
-rw-r--r--chromium/mojo/public/c/gles2/DEPS3
-rw-r--r--chromium/mojo/public/c/gles2/gles2.h51
-rw-r--r--chromium/mojo/public/c/gles2/gles2_call_visitor_autogen.h544
-rw-r--r--chromium/mojo/public/c/gles2/gles2_export.h26
-rw-r--r--chromium/mojo/public/c/gles2/gles2_types.h26
-rw-r--r--chromium/mojo/public/c/system/buffer.h187
-rw-r--r--chromium/mojo/public/c/system/core.h20
-rw-r--r--chromium/mojo/public/c/system/data_pipe.h367
-rw-r--r--chromium/mojo/public/c/system/functions.h87
-rw-r--r--chromium/mojo/public/c/system/macros.h72
-rw-r--r--chromium/mojo/public/c/system/message_pipe.h178
-rw-r--r--chromium/mojo/public/c/system/system_export.h33
-rw-r--r--chromium/mojo/public/c/system/types.h176
-rw-r--r--chromium/mojo/public/c/test_support/test_support.h48
-rw-r--r--chromium/mojo/public/c/test_support/test_support_export.h26
-rw-r--r--chromium/mojo/public/cpp/DEPS18
-rw-r--r--chromium/mojo/public/cpp/README.md71
-rw-r--r--chromium/mojo/public/cpp/application/DEPS14
-rw-r--r--chromium/mojo/public/cpp/application/application.h121
-rw-r--r--chromium/mojo/public/cpp/application/connect.h24
-rw-r--r--chromium/mojo/public/cpp/application/lib/application.cc34
-rw-r--r--chromium/mojo/public/cpp/application/lib/mojo_main_chromium.cc23
-rw-r--r--chromium/mojo/public/cpp/application/lib/mojo_main_standalone.cc22
-rw-r--r--chromium/mojo/public/cpp/application/lib/service_connector.cc18
-rw-r--r--chromium/mojo/public/cpp/application/lib/service_connector.h133
-rw-r--r--chromium/mojo/public/cpp/application/lib/service_registry.cc78
-rw-r--r--chromium/mojo/public/cpp/application/lib/service_registry.h55
-rw-r--r--chromium/mojo/public/cpp/bindings/BUILD.gn53
-rw-r--r--chromium/mojo/public/cpp/bindings/DEPS3
-rw-r--r--chromium/mojo/public/cpp/bindings/array.h143
-rw-r--r--chromium/mojo/public/cpp/bindings/callback.h462
-rw-r--r--chromium/mojo/public/cpp/bindings/callback.h.pump80
-rw-r--r--chromium/mojo/public/cpp/bindings/error_handler.h19
-rw-r--r--chromium/mojo/public/cpp/bindings/interface_impl.h109
-rw-r--r--chromium/mojo/public/cpp/bindings/interface_ptr.h124
-rw-r--r--chromium/mojo/public/cpp/bindings/interface_request.h76
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/DEPS5
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/TODO6
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/array_internal.cc70
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/array_internal.h384
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/array_serialization.h179
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/bindings_internal.h86
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/bindings_serialization.cc118
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/bindings_serialization.h83
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/bounds_checker.cc77
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/bounds_checker.h64
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/buffer.h24
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/callback_internal.h26
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/connector.cc157
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/connector.h100
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/filter_chain.cc49
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/filter_chain.h66
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc53
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h67
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/interface_impl_internal.h94
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/interface_ptr_internal.h84
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message.cc81
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_builder.cc52
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_builder.h63
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_filter.cc23
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_header_validator.cc81
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_header_validator.h24
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_internal.h44
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_queue.cc50
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_queue.h47
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/no_interface.cc20
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/router.cc140
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/router.h91
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/shared_data.h84
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/shared_ptr.h63
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/string_serialization.cc38
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/string_serialization.h20
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/sync_dispatcher.cc27
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/template_util.h89
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/validation_errors.cc64
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/validation_errors.h66
-rw-r--r--chromium/mojo/public/cpp/bindings/message.h123
-rw-r--r--chromium/mojo/public/cpp/bindings/message_filter.h39
-rw-r--r--chromium/mojo/public/cpp/bindings/no_interface.h56
-rw-r--r--chromium/mojo/public/cpp/bindings/string.h154
-rw-r--r--chromium/mojo/public/cpp/bindings/struct_ptr.h154
-rw-r--r--chromium/mojo/public/cpp/bindings/sync_dispatcher.h47
-rw-r--r--chromium/mojo/public/cpp/bindings/type_converter.h82
-rw-r--r--chromium/mojo/public/cpp/environment/environment.h41
-rw-r--r--chromium/mojo/public/cpp/environment/lib/DEPS4
-rw-r--r--chromium/mojo/public/cpp/environment/lib/default_async_waiter.cc94
-rw-r--r--chromium/mojo/public/cpp/environment/lib/default_async_waiter.h18
-rw-r--r--chromium/mojo/public/cpp/environment/lib/default_logger.cc71
-rw-r--r--chromium/mojo/public/cpp/environment/lib/default_logger.h18
-rw-r--r--chromium/mojo/public/cpp/environment/lib/environment.cc60
-rw-r--r--chromium/mojo/public/cpp/environment/lib/logging.cc45
-rw-r--r--chromium/mojo/public/cpp/environment/logging.h87
-rw-r--r--chromium/mojo/public/cpp/gles2/DEPS4
-rw-r--r--chromium/mojo/public/cpp/gles2/gles2.h24
-rw-r--r--chromium/mojo/public/cpp/system/core.h555
-rw-r--r--chromium/mojo/public/cpp/system/macros.h53
-rw-r--r--chromium/mojo/public/cpp/test_support/DEPS3
-rw-r--r--chromium/mojo/public/cpp/test_support/lib/test_support.cc26
-rw-r--r--chromium/mojo/public/cpp/test_support/lib/test_utils.cc91
-rw-r--r--chromium/mojo/public/cpp/test_support/test_support.h34
-rw-r--r--chromium/mojo/public/cpp/test_support/test_utils.h39
-rw-r--r--chromium/mojo/public/cpp/utility/lib/mutex.cc52
-rw-r--r--chromium/mojo/public/cpp/utility/lib/run_loop.cc221
-rw-r--r--chromium/mojo/public/cpp/utility/lib/thread.cc69
-rw-r--r--chromium/mojo/public/cpp/utility/lib/thread_local.h61
-rw-r--r--chromium/mojo/public/cpp/utility/lib/thread_local_posix.cc39
-rw-r--r--chromium/mojo/public/cpp/utility/lib/thread_local_win.cc39
-rw-r--r--chromium/mojo/public/cpp/utility/mutex.h70
-rw-r--r--chromium/mojo/public/cpp/utility/run_loop.h108
-rw-r--r--chromium/mojo/public/cpp/utility/run_loop_handler.h25
-rw-r--r--chromium/mojo/public/cpp/utility/thread.h62
-rw-r--r--chromium/mojo/public/gles2/gles2_interface.h23
-rw-r--r--chromium/mojo/public/gles2/gles2_private.cc92
-rw-r--r--chromium/mojo/public/gles2/gles2_private.h46
-rw-r--r--chromium/mojo/public/interfaces/interface_provider/BUILD.gn11
-rw-r--r--chromium/mojo/public/interfaces/interface_provider/interface_provider.mojom12
-rw-r--r--chromium/mojo/public/interfaces/service_provider/BUILD.gn11
-rw-r--r--chromium/mojo/public/interfaces/service_provider/service_provider.mojom19
-rw-r--r--chromium/mojo/public/interfaces/shell/BUILD.gn11
-rw-r--r--chromium/mojo/public/js/bindings/BUILD.gn10
-rw-r--r--chromium/mojo/public/js/bindings/codec.js739
-rw-r--r--chromium/mojo/public/js/bindings/connection.js30
-rw-r--r--chromium/mojo/public/js/bindings/connector.js109
-rw-r--r--chromium/mojo/public/js/bindings/constants.cc15
-rw-r--r--chromium/mojo/public/js/bindings/constants.h19
-rw-r--r--chromium/mojo/public/js/bindings/core.js215
-rw-r--r--chromium/mojo/public/js/bindings/router.js93
-rw-r--r--chromium/mojo/public/js/bindings/support.js30
-rw-r--r--chromium/mojo/public/js/bindings/unicode.js51
-rw-r--r--chromium/mojo/public/platform/native/system_thunks.cc170
-rw-r--r--chromium/mojo/public/platform/native/system_thunks.h137
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl9
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl49
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl315
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl23
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl14
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl6
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl6
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl14
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl49
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl86
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl108
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl33
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl22
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl28
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl91
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl5
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl51
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl31
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl15
-rw-r--r--chromium/mojo/public/tools/bindings/generators/java_templates/constant_definition.tmpl5
-rw-r--r--chromium/mojo/public/tools/bindings/generators/java_templates/constants.java.tmpl12
-rw-r--r--chromium/mojo/public/tools/bindings/generators/java_templates/enum.java.tmpl4
-rw-r--r--chromium/mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl21
-rw-r--r--chromium/mojo/public/tools/bindings/generators/java_templates/header.java.tmpl11
-rw-r--r--chromium/mojo/public/tools/bindings/generators/java_templates/java_macros.tmpl3
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl14
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl122
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl52
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl72
-rw-r--r--chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py286
-rw-r--r--chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py187
-rw-r--r--chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py186
-rwxr-xr-xchromium/mojo/public/tools/bindings/generators/run_cpp_generator.py28
-rw-r--r--chromium/mojo/public/tools/bindings/mojom.gni90
-rw-r--r--chromium/mojo/public/tools/bindings/mojom_bindings_generator.gypi99
-rwxr-xr-xchromium/mojo/public/tools/bindings/mojom_bindings_generator.py179
-rw-r--r--chromium/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py23
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/__init__.py0
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/error.py27
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py0
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/data.py348
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py86
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/generator.py90
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py217
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py34
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/pack.py150
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py176
-rwxr-xr-xchromium/mojo/public/tools/bindings/pylib/mojom/generate/run_tests.py35
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py54
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py193
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py0
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/parse/ast.py25
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py277
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py323
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/parse/translate.py144
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom_tests/__init__.py0
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/__init__.py0
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py187
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/parser_unittest.py493
-rwxr-xr-xchromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/run_parser.py39
-rwxr-xr-xchromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/run_translate.py37
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/__init__.py0
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/find_files.py32
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/run_bindings_generator.py47
202 files changed, 16551 insertions, 82 deletions
diff --git a/chromium/mojo/public/DEPS b/chromium/mojo/public/DEPS
new file mode 100644
index 00000000000..0c679b9fd0f
--- /dev/null
+++ b/chromium/mojo/public/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "-base",
+ "-build",
+ "-mojo",
+ "+mojo/public",
+]
diff --git a/chromium/mojo/public/README.md b/chromium/mojo/public/README.md
new file mode 100644
index 00000000000..a31a8a8245e
--- /dev/null
+++ b/chromium/mojo/public/README.md
@@ -0,0 +1,43 @@
+Mojo Public API
+===============
+
+The Mojo Public API is a binary stable API to the Mojo system.
+
+It consists of support for a number of programming languages (with a directory
+for each support language), some "build" tools and build-time requirements, and
+interface definitions for Mojo services (specified using an IDL).
+
+Note that there are various subdirectories named tests/. These contain tests of
+the code in the enclosing directory, and are not meant for use by Mojo
+applications.
+
+C/CPP/JS
+--------
+
+The c/, cpp/, js/ subdirectories define the API for C, C++, and JavaScript,
+respectively.
+
+The basic principle for these directories is that they consist of the source
+files that one needs at build/deployment/run time (as appropriate for the
+language), organized in a natural way for the particular language.
+
+Interfaces
+----------
+
+The interfaces/ subdirectory contains Mojo IDL (a.k.a. .mojom) descriptions of
+standard Mojo services.
+
+Platform
+--------
+
+The platform/ subdirectory contains any build-time requirements (e.g., static
+libraries) that may be needed to produce a Mojo application for certain
+platforms, such as a native shared library or as a NaCl binary.
+
+Tools
+-----
+
+The tools/ subdirectory contains tools that are useful/necessary at
+build/deployment time. These tools may be needed (as a practical necessity) to
+use the API in any given language, e.g., to generate bindings from Mojo IDL
+files.
diff --git a/chromium/mojo/public/bindings/mojom_bindings_generator.gypi b/chromium/mojo/public/bindings/mojom_bindings_generator.gypi
deleted file mode 100644
index 45efe768d1b..00000000000
--- a/chromium/mojo/public/bindings/mojom_bindings_generator.gypi
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
- 'variables': {
- 'output_dir': '<(SHARED_INTERMEDIATE_DIR)/mojom',
- },
- 'rules': [
- {
- 'rule_name': 'Generate C++ source files from mojom files',
- 'extension': 'mojom',
- 'variables': {
- 'mojom_bindings_generator':
- '<(DEPTH)/mojo/public/bindings/mojom_bindings_generator.py',
- },
- 'inputs': [
- '<(mojom_bindings_generator)',
- '<(DEPTH)/mojo/public/bindings/parse/mojo_parser.py',
- '<(DEPTH)/mojo/public/bindings/parse/mojo_translate.py',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/interface_declaration',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/interface_definition',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/interface_proxy_declaration',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/interface_stub_case',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/interface_stub_declaration',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/interface_stub_definition',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/module.cc-template',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/module.h-template',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/module_internal.h-template',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/params_definition',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/params_serialization',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/proxy_implementation',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_builder_definition',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_declaration',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_destructor',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_definition',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_serialization',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_serialization_definition',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/struct_serialization_traits',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/template_declaration',
- '<(DEPTH)/mojo/public/bindings/generators/cpp_templates/wrapper_class_declaration',
- '<(DEPTH)/mojo/public/bindings/generators/js_templates/module.js.tmpl',
- '<(DEPTH)/mojo/public/bindings/generators/mojom.py',
- '<(DEPTH)/mojo/public/bindings/generators/mojom_cpp_generator.py',
- '<(DEPTH)/mojo/public/bindings/generators/mojom_data.py',
- '<(DEPTH)/mojo/public/bindings/generators/mojom_generator.py',
- '<(DEPTH)/mojo/public/bindings/generators/mojom_js_generator.py',
- '<(DEPTH)/mojo/public/bindings/generators/mojom_pack.py',
- '<(DEPTH)/mojo/public/bindings/generators/template_expander.py',
- ],
- 'outputs': [
- '<(output_dir)/<(RULE_INPUT_ROOT).cc',
- '<(output_dir)/<(RULE_INPUT_ROOT).h',
- '<(output_dir)/<(RULE_INPUT_ROOT).js',
- '<(output_dir)/<(RULE_INPUT_ROOT)_internal.h',
- ],
- 'action': [
- 'python', '<@(mojom_bindings_generator)',
- '<(RULE_INPUT_PATH)',
- '-i', 'mojom',
- '-o', '<(output_dir)',
- ],
- 'message': 'Generating C++ from mojom <(RULE_INPUT_PATH)',
- 'process_outputs_as_sources': 1,
- }
- ],
- 'dependencies': [
- 'mojo_bindings',
- 'mojo_system',
- ],
- 'include_dirs': [
- '<(DEPTH)',
- '<(SHARED_INTERMEDIATE_DIR)',
- ],
- 'direct_dependent_settings': {
- 'include_dirs': [
- '<(DEPTH)',
- '<(SHARED_INTERMEDIATE_DIR)',
- ],
- },
- 'hard_dependency': 1,
-}
diff --git a/chromium/mojo/public/c/DEPS b/chromium/mojo/public/c/DEPS
new file mode 100644
index 00000000000..52727706c38
--- /dev/null
+++ b/chromium/mojo/public/c/DEPS
@@ -0,0 +1,16 @@
+include_rules = [
+ # Require explicit dependencies in each directory.
+ "-mojo/public",
+ # But everyone can depend on the C system headers.
+ "+mojo/public/c/system",
+]
+
+specific_include_rules = {
+ r".*_(unit|perf)test\.cc": [
+ "+testing",
+ # Our test harness is C++, so allow the use of C++:
+ "+mojo/public/cpp/system",
+ "+mojo/public/cpp/test_support",
+ "+mojo/public/cpp/utility",
+ ],
+}
diff --git a/chromium/mojo/public/c/README.md b/chromium/mojo/public/c/README.md
new file mode 100644
index 00000000000..8e11545deb0
--- /dev/null
+++ b/chromium/mojo/public/c/README.md
@@ -0,0 +1,45 @@
+Mojo Public C API
+=================
+
+This directory contains C language bindings for the Mojo Public API.
+
+Environment
+-----------
+
+The environment/ subdirectory defines some common things that, while not part of
+the system API, may be required for GLES2 (for example). These are things that a
+Mojo application may be required to provide to the GLES2 (for example) library
+in order to use it. (However, the Mojo application may implement these things as
+it sees fit.)
+
+GLES2
+-----
+
+The gles2/ subdirectory defines the GLES2 C API that's available to Mojo
+applications. To use GLES2, Mojo applications must link against a dynamic
+library (the exact mechanism being platform-dependent) and use the header files
+in this directory as well as the standard Khronos GLES2 header files.
+
+The reason for this, rather than providing GLES2 using the standard Mojo IPC
+mechanism, is performance: The protocol (and transport mechanisms) used to
+communicate with the Mojo GLES2 service is not stable nor "public" (mainly for
+performance reasons), and using the dynamic library shields the application from
+changes to the underlying system.
+
+System
+------
+
+The system/ subdirectory provides definitions of the basic low-level API used by
+all Mojo applications (whether directly or indirectly). These consist primarily
+of the IPC primitives used to communicate with Mojo services.
+
+Though the message protocol is stable, the implementation of the transport is
+not, and access to the IPC mechanisms must be via the primitives defined in this
+directory.
+
+Test Support
+------------
+
+This directory contains a C API for running tests. This API is only available
+under special, specific test conditions. It is not meant for general use by Mojo
+applications.
diff --git a/chromium/mojo/public/c/environment/async_waiter.h b/chromium/mojo/public/c/environment/async_waiter.h
new file mode 100644
index 00000000000..1eb06317d70
--- /dev/null
+++ b/chromium/mojo/public/c/environment/async_waiter.h
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_ENVIRONMENT_ASYNC_WAITER_H_
+#define MOJO_PUBLIC_C_ENVIRONMENT_ASYNC_WAITER_H_
+
+#include "mojo/public/c/system/types.h"
+
+typedef uintptr_t MojoAsyncWaitID;
+
+typedef void (*MojoAsyncWaitCallback)(void* closure, MojoResult result);
+
+struct MojoAsyncWaiter {
+ // Asynchronously call MojoWait on a background thread, and pass the result
+ // of MojoWait to the given MojoAsyncWaitCallback on the current thread.
+ // Returns a non-zero MojoAsyncWaitID that can be used with CancelWait to
+ // stop waiting. This identifier becomes invalid once the callback runs.
+ MojoAsyncWaitID (*AsyncWait)(MojoHandle handle,
+ MojoHandleSignals signals,
+ MojoDeadline deadline,
+ MojoAsyncWaitCallback callback,
+ void* closure);
+
+ // Cancel an existing call to AsyncWait with the given MojoAsyncWaitID. The
+ // corresponding MojoAsyncWaitCallback will not be called in this case.
+ void (*CancelWait)(MojoAsyncWaitID wait_id);
+};
+
+#endif // MOJO_PUBLIC_C_ENVIRONMENT_ASYNC_WAITER_H_
diff --git a/chromium/mojo/public/c/environment/logger.h b/chromium/mojo/public/c/environment/logger.h
new file mode 100644
index 00000000000..5e9067fb509
--- /dev/null
+++ b/chromium/mojo/public/c/environment/logger.h
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_ENVIRONMENT_LOGGER_H_
+#define MOJO_PUBLIC_C_ENVIRONMENT_LOGGER_H_
+
+#include <stdint.h>
+
+// |MojoLogLevel|: Used to specify the type of log message. Values are ordered
+// by severity (i.e., higher numerical values are more severe).
+
+typedef int32_t MojoLogLevel;
+
+#ifdef __cplusplus
+const MojoLogLevel MOJO_LOG_LEVEL_VERBOSE = -1;
+const MojoLogLevel MOJO_LOG_LEVEL_INFO = 0;
+const MojoLogLevel MOJO_LOG_LEVEL_WARNING = 1;
+const MojoLogLevel MOJO_LOG_LEVEL_ERROR = 2;
+const MojoLogLevel MOJO_LOG_LEVEL_FATAL = 3;
+#else
+#define MOJO_LOG_LEVEL_VERBOSE ((MojoLogLevel) -1)
+#define MOJO_LOG_LEVEL_INFO ((MojoLogLevel) 0)
+#define MOJO_LOG_LEVEL_WARNING ((MojoLogLevel) 1)
+#define MOJO_LOG_LEVEL_ERROR ((MojoLogLevel) 2)
+#define MOJO_LOG_LEVEL_FATAL ((MojoLogLevel) 3)
+#endif
+
+// Structure with basic logging functions (on top of which more friendly logging
+// macros may be built). The functions are thread-safe, except for
+// |SetMinimumLogLevel()| (see below).
+struct MojoLogger {
+ // Logs |message| at level |log_level| if |log_level| is at least the current
+ // minimum log level. If |log_level| is |MOJO_LOG_LEVEL_FATAL| (or greater),
+ // aborts the application/process.
+ void (*LogMessage)(MojoLogLevel log_level, const char* message);
+
+ // Gets the minimum log level (see above), which will always be at most
+ // |MOJO_LOG_LEVEL_FATAL|. (Though |LogMessage()| will automatically avoid
+ // logging messages below the minimum log level, this may be used to avoid
+ // extra work.)
+ MojoLogLevel (*GetMinimumLogLevel)(void);
+
+ // Sets the minimum log level (see above) to the lesser of |minimum_log_level|
+ // and |MOJO_LOG_LEVEL_FATAL|.
+ //
+ // Warning: This function may not be thread-safe, and should not be called
+ // concurrently with other |MojoLogger| functions. (In some environments --
+ // such as Chromium -- that share a logger across applications, this may mean
+ // that it is almost never safe to call this.)
+ void (*SetMinimumLogLevel)(MojoLogLevel minimum_log_level);
+};
+
+#endif // MOJO_PUBLIC_C_ENVIRONMENT_LOGGER_H_
diff --git a/chromium/mojo/public/c/gles2/DEPS b/chromium/mojo/public/c/gles2/DEPS
new file mode 100644
index 00000000000..38874579404
--- /dev/null
+++ b/chromium/mojo/public/c/gles2/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+mojo/public/c/environment",
+]
diff --git a/chromium/mojo/public/c/gles2/gles2.h b/chromium/mojo/public/c/gles2/gles2.h
new file mode 100644
index 00000000000..44880afc1ed
--- /dev/null
+++ b/chromium/mojo/public/c/gles2/gles2.h
@@ -0,0 +1,51 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_GLES2_GLES2_H_
+#define MOJO_PUBLIC_C_GLES2_GLES2_H_
+
+// Note: This header should be compilable as C.
+
+#include <stdint.h>
+#include <GLES2/gl2.h>
+
+#include "mojo/public/c/environment/async_waiter.h"
+#include "mojo/public/c/gles2/gles2_export.h"
+#include "mojo/public/c/gles2/gles2_types.h"
+#include "mojo/public/c/system/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MOJO_GLES2_EXPORT void MojoGLES2Initialize(const MojoAsyncWaiter* async_waiter);
+MOJO_GLES2_EXPORT void MojoGLES2Terminate(void);
+MOJO_GLES2_EXPORT MojoGLES2Context MojoGLES2CreateContext(
+ MojoHandle handle,
+ MojoGLES2ContextLost lost_callback,
+ MojoGLES2DrawAnimationFrame animation_callback,
+ void* closure);
+MOJO_GLES2_EXPORT void MojoGLES2DestroyContext(MojoGLES2Context context);
+MOJO_GLES2_EXPORT void MojoGLES2MakeCurrent(MojoGLES2Context context);
+MOJO_GLES2_EXPORT void MojoGLES2SwapBuffers(void);
+// TODO(piman): this doesn't belong here.
+MOJO_GLES2_EXPORT void MojoGLES2RequestAnimationFrames(
+ MojoGLES2Context context);
+MOJO_GLES2_EXPORT void MojoGLES2CancelAnimationFrames(MojoGLES2Context context);
+
+// TODO(piman): We shouldn't have to leak those 2 interfaces, especially in a
+// type-unsafe way.
+MOJO_GLES2_EXPORT void* MojoGLES2GetGLES2Interface(MojoGLES2Context context);
+MOJO_GLES2_EXPORT void* MojoGLES2GetContextSupport(MojoGLES2Context context);
+
+#define VISIT_GL_CALL(Function, ReturnType, PARAMETERS, ARGUMENTS) \
+ MOJO_GLES2_EXPORT ReturnType GL_APIENTRY gl##Function PARAMETERS;
+#include "mojo/public/c/gles2/gles2_call_visitor_autogen.h"
+#undef VISIT_GL_CALL
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // MOJO_PUBLIC_C_GLES2_GLES2_H_
diff --git a/chromium/mojo/public/c/gles2/gles2_call_visitor_autogen.h b/chromium/mojo/public/c/gles2/gles2_call_visitor_autogen.h
new file mode 100644
index 00000000000..72494c5416c
--- /dev/null
+++ b/chromium/mojo/public/c/gles2/gles2_call_visitor_autogen.h
@@ -0,0 +1,544 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is auto-generated from
+// gpu/command_buffer/build_gles2_cmd_buffer.py
+// It's formatted by clang-format using chromium coding style:
+// clang-format -i -style=chromium filename
+// DO NOT EDIT!
+
+VISIT_GL_CALL(ActiveTexture, void, (GLenum texture), (texture))
+VISIT_GL_CALL(AttachShader,
+ void,
+ (GLuint program, GLuint shader),
+ (program, shader))
+VISIT_GL_CALL(BindAttribLocation,
+ void,
+ (GLuint program, GLuint index, const char* name),
+ (program, index, name))
+VISIT_GL_CALL(BindBuffer,
+ void,
+ (GLenum target, GLuint buffer),
+ (target, buffer))
+VISIT_GL_CALL(BindFramebuffer,
+ void,
+ (GLenum target, GLuint framebuffer),
+ (target, framebuffer))
+VISIT_GL_CALL(BindRenderbuffer,
+ void,
+ (GLenum target, GLuint renderbuffer),
+ (target, renderbuffer))
+VISIT_GL_CALL(BindTexture,
+ void,
+ (GLenum target, GLuint texture),
+ (target, texture))
+VISIT_GL_CALL(BlendColor,
+ void,
+ (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha),
+ (red, green, blue, alpha))
+VISIT_GL_CALL(BlendEquation, void, (GLenum mode), (mode))
+VISIT_GL_CALL(BlendEquationSeparate,
+ void,
+ (GLenum modeRGB, GLenum modeAlpha),
+ (modeRGB, modeAlpha))
+VISIT_GL_CALL(BlendFunc,
+ void,
+ (GLenum sfactor, GLenum dfactor),
+ (sfactor, dfactor))
+VISIT_GL_CALL(BlendFuncSeparate,
+ void,
+ (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha),
+ (srcRGB, dstRGB, srcAlpha, dstAlpha))
+VISIT_GL_CALL(BufferData,
+ void,
+ (GLenum target, GLsizeiptr size, const void* data, GLenum usage),
+ (target, size, data, usage))
+VISIT_GL_CALL(
+ BufferSubData,
+ void,
+ (GLenum target, GLintptr offset, GLsizeiptr size, const void* data),
+ (target, offset, size, data))
+VISIT_GL_CALL(CheckFramebufferStatus, GLenum, (GLenum target), (target))
+VISIT_GL_CALL(Clear, void, (GLbitfield mask), (mask))
+VISIT_GL_CALL(ClearColor,
+ void,
+ (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha),
+ (red, green, blue, alpha))
+VISIT_GL_CALL(ClearDepthf, void, (GLclampf depth), (depth))
+VISIT_GL_CALL(ClearStencil, void, (GLint s), (s))
+VISIT_GL_CALL(ColorMask,
+ void,
+ (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha),
+ (red, green, blue, alpha))
+VISIT_GL_CALL(CompileShader, void, (GLuint shader), (shader))
+VISIT_GL_CALL(
+ CompressedTexImage2D,
+ void,
+ (GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void* data),
+ (target, level, internalformat, width, height, border, imageSize, data))
+VISIT_GL_CALL(
+ CompressedTexSubImage2D,
+ void,
+ (GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void* data),
+ (target, level, xoffset, yoffset, width, height, format, imageSize, data))
+VISIT_GL_CALL(CopyTexImage2D,
+ void,
+ (GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border),
+ (target, level, internalformat, x, y, width, height, border))
+VISIT_GL_CALL(CopyTexSubImage2D,
+ void,
+ (GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height),
+ (target, level, xoffset, yoffset, x, y, width, height))
+VISIT_GL_CALL(CreateProgram, GLuint, (), ())
+VISIT_GL_CALL(CreateShader, GLuint, (GLenum type), (type))
+VISIT_GL_CALL(CullFace, void, (GLenum mode), (mode))
+VISIT_GL_CALL(DeleteBuffers,
+ void,
+ (GLsizei n, const GLuint* buffers),
+ (n, buffers))
+VISIT_GL_CALL(DeleteFramebuffers,
+ void,
+ (GLsizei n, const GLuint* framebuffers),
+ (n, framebuffers))
+VISIT_GL_CALL(DeleteProgram, void, (GLuint program), (program))
+VISIT_GL_CALL(DeleteRenderbuffers,
+ void,
+ (GLsizei n, const GLuint* renderbuffers),
+ (n, renderbuffers))
+VISIT_GL_CALL(DeleteShader, void, (GLuint shader), (shader))
+VISIT_GL_CALL(DeleteTextures,
+ void,
+ (GLsizei n, const GLuint* textures),
+ (n, textures))
+VISIT_GL_CALL(DepthFunc, void, (GLenum func), (func))
+VISIT_GL_CALL(DepthMask, void, (GLboolean flag), (flag))
+VISIT_GL_CALL(DepthRangef, void, (GLclampf zNear, GLclampf zFar), (zNear, zFar))
+VISIT_GL_CALL(DetachShader,
+ void,
+ (GLuint program, GLuint shader),
+ (program, shader))
+VISIT_GL_CALL(Disable, void, (GLenum cap), (cap))
+VISIT_GL_CALL(DisableVertexAttribArray, void, (GLuint index), (index))
+VISIT_GL_CALL(DrawArrays,
+ void,
+ (GLenum mode, GLint first, GLsizei count),
+ (mode, first, count))
+VISIT_GL_CALL(DrawElements,
+ void,
+ (GLenum mode, GLsizei count, GLenum type, const void* indices),
+ (mode, count, type, indices))
+VISIT_GL_CALL(Enable, void, (GLenum cap), (cap))
+VISIT_GL_CALL(EnableVertexAttribArray, void, (GLuint index), (index))
+VISIT_GL_CALL(Finish, void, (), ())
+VISIT_GL_CALL(Flush, void, (), ())
+VISIT_GL_CALL(FramebufferRenderbuffer,
+ void,
+ (GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer),
+ (target, attachment, renderbuffertarget, renderbuffer))
+VISIT_GL_CALL(FramebufferTexture2D,
+ void,
+ (GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level),
+ (target, attachment, textarget, texture, level))
+VISIT_GL_CALL(FrontFace, void, (GLenum mode), (mode))
+VISIT_GL_CALL(GenBuffers, void, (GLsizei n, GLuint * buffers), (n, buffers))
+VISIT_GL_CALL(GenerateMipmap, void, (GLenum target), (target))
+VISIT_GL_CALL(GenFramebuffers,
+ void,
+ (GLsizei n, GLuint * framebuffers),
+ (n, framebuffers))
+VISIT_GL_CALL(GenRenderbuffers,
+ void,
+ (GLsizei n, GLuint * renderbuffers),
+ (n, renderbuffers))
+VISIT_GL_CALL(GenTextures, void, (GLsizei n, GLuint * textures), (n, textures))
+VISIT_GL_CALL(GetActiveAttrib,
+ void,
+ (GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei * length,
+ GLint * size,
+ GLenum * type,
+ char* name),
+ (program, index, bufsize, length, size, type, name))
+VISIT_GL_CALL(GetActiveUniform,
+ void,
+ (GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei * length,
+ GLint * size,
+ GLenum * type,
+ char* name),
+ (program, index, bufsize, length, size, type, name))
+VISIT_GL_CALL(
+ GetAttachedShaders,
+ void,
+ (GLuint program, GLsizei maxcount, GLsizei * count, GLuint * shaders),
+ (program, maxcount, count, shaders))
+VISIT_GL_CALL(GetAttribLocation,
+ GLint,
+ (GLuint program, const char* name),
+ (program, name))
+VISIT_GL_CALL(GetBooleanv,
+ void,
+ (GLenum pname, GLboolean * params),
+ (pname, params))
+VISIT_GL_CALL(GetBufferParameteriv,
+ void,
+ (GLenum target, GLenum pname, GLint * params),
+ (target, pname, params))
+VISIT_GL_CALL(GetError, GLenum, (), ())
+VISIT_GL_CALL(GetFloatv,
+ void,
+ (GLenum pname, GLfloat * params),
+ (pname, params))
+VISIT_GL_CALL(GetFramebufferAttachmentParameteriv,
+ void,
+ (GLenum target, GLenum attachment, GLenum pname, GLint * params),
+ (target, attachment, pname, params))
+VISIT_GL_CALL(GetIntegerv,
+ void,
+ (GLenum pname, GLint * params),
+ (pname, params))
+VISIT_GL_CALL(GetProgramiv,
+ void,
+ (GLuint program, GLenum pname, GLint * params),
+ (program, pname, params))
+VISIT_GL_CALL(
+ GetProgramInfoLog,
+ void,
+ (GLuint program, GLsizei bufsize, GLsizei * length, char* infolog),
+ (program, bufsize, length, infolog))
+VISIT_GL_CALL(GetRenderbufferParameteriv,
+ void,
+ (GLenum target, GLenum pname, GLint * params),
+ (target, pname, params))
+VISIT_GL_CALL(GetShaderiv,
+ void,
+ (GLuint shader, GLenum pname, GLint * params),
+ (shader, pname, params))
+VISIT_GL_CALL(GetShaderInfoLog,
+ void,
+ (GLuint shader, GLsizei bufsize, GLsizei * length, char* infolog),
+ (shader, bufsize, length, infolog))
+VISIT_GL_CALL(
+ GetShaderPrecisionFormat,
+ void,
+ (GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision),
+ (shadertype, precisiontype, range, precision))
+VISIT_GL_CALL(GetShaderSource,
+ void,
+ (GLuint shader, GLsizei bufsize, GLsizei * length, char* source),
+ (shader, bufsize, length, source))
+VISIT_GL_CALL(GetString, const GLubyte*, (GLenum name), (name))
+VISIT_GL_CALL(GetTexParameterfv,
+ void,
+ (GLenum target, GLenum pname, GLfloat * params),
+ (target, pname, params))
+VISIT_GL_CALL(GetTexParameteriv,
+ void,
+ (GLenum target, GLenum pname, GLint * params),
+ (target, pname, params))
+VISIT_GL_CALL(GetUniformfv,
+ void,
+ (GLuint program, GLint location, GLfloat * params),
+ (program, location, params))
+VISIT_GL_CALL(GetUniformiv,
+ void,
+ (GLuint program, GLint location, GLint * params),
+ (program, location, params))
+VISIT_GL_CALL(GetUniformLocation,
+ GLint,
+ (GLuint program, const char* name),
+ (program, name))
+VISIT_GL_CALL(GetVertexAttribfv,
+ void,
+ (GLuint index, GLenum pname, GLfloat * params),
+ (index, pname, params))
+VISIT_GL_CALL(GetVertexAttribiv,
+ void,
+ (GLuint index, GLenum pname, GLint * params),
+ (index, pname, params))
+VISIT_GL_CALL(GetVertexAttribPointerv,
+ void,
+ (GLuint index, GLenum pname, void** pointer),
+ (index, pname, pointer))
+VISIT_GL_CALL(Hint, void, (GLenum target, GLenum mode), (target, mode))
+VISIT_GL_CALL(IsBuffer, GLboolean, (GLuint buffer), (buffer))
+VISIT_GL_CALL(IsEnabled, GLboolean, (GLenum cap), (cap))
+VISIT_GL_CALL(IsFramebuffer, GLboolean, (GLuint framebuffer), (framebuffer))
+VISIT_GL_CALL(IsProgram, GLboolean, (GLuint program), (program))
+VISIT_GL_CALL(IsRenderbuffer, GLboolean, (GLuint renderbuffer), (renderbuffer))
+VISIT_GL_CALL(IsShader, GLboolean, (GLuint shader), (shader))
+VISIT_GL_CALL(IsTexture, GLboolean, (GLuint texture), (texture))
+VISIT_GL_CALL(LineWidth, void, (GLfloat width), (width))
+VISIT_GL_CALL(LinkProgram, void, (GLuint program), (program))
+VISIT_GL_CALL(PixelStorei, void, (GLenum pname, GLint param), (pname, param))
+VISIT_GL_CALL(PolygonOffset,
+ void,
+ (GLfloat factor, GLfloat units),
+ (factor, units))
+VISIT_GL_CALL(ReadPixels,
+ void,
+ (GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ void* pixels),
+ (x, y, width, height, format, type, pixels))
+VISIT_GL_CALL(ReleaseShaderCompiler, void, (), ())
+VISIT_GL_CALL(
+ RenderbufferStorage,
+ void,
+ (GLenum target, GLenum internalformat, GLsizei width, GLsizei height),
+ (target, internalformat, width, height))
+VISIT_GL_CALL(SampleCoverage,
+ void,
+ (GLclampf value, GLboolean invert),
+ (value, invert))
+VISIT_GL_CALL(Scissor,
+ void,
+ (GLint x, GLint y, GLsizei width, GLsizei height),
+ (x, y, width, height))
+VISIT_GL_CALL(ShaderBinary,
+ void,
+ (GLsizei n,
+ const GLuint* shaders,
+ GLenum binaryformat,
+ const void* binary,
+ GLsizei length),
+ (n, shaders, binaryformat, binary, length))
+VISIT_GL_CALL(ShaderSource,
+ void,
+ (GLuint shader,
+ GLsizei count,
+ const GLchar* const* str,
+ const GLint* length),
+ (shader, count, str, length))
+VISIT_GL_CALL(StencilFunc,
+ void,
+ (GLenum func, GLint ref, GLuint mask),
+ (func, ref, mask))
+VISIT_GL_CALL(StencilFuncSeparate,
+ void,
+ (GLenum face, GLenum func, GLint ref, GLuint mask),
+ (face, func, ref, mask))
+VISIT_GL_CALL(StencilMask, void, (GLuint mask), (mask))
+VISIT_GL_CALL(StencilMaskSeparate,
+ void,
+ (GLenum face, GLuint mask),
+ (face, mask))
+VISIT_GL_CALL(StencilOp,
+ void,
+ (GLenum fail, GLenum zfail, GLenum zpass),
+ (fail, zfail, zpass))
+VISIT_GL_CALL(StencilOpSeparate,
+ void,
+ (GLenum face, GLenum fail, GLenum zfail, GLenum zpass),
+ (face, fail, zfail, zpass))
+VISIT_GL_CALL(TexImage2D,
+ void,
+ (GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void* pixels),
+ (target,
+ level,
+ internalformat,
+ width,
+ height,
+ border,
+ format,
+ type,
+ pixels))
+VISIT_GL_CALL(TexParameterf,
+ void,
+ (GLenum target, GLenum pname, GLfloat param),
+ (target, pname, param))
+VISIT_GL_CALL(TexParameterfv,
+ void,
+ (GLenum target, GLenum pname, const GLfloat* params),
+ (target, pname, params))
+VISIT_GL_CALL(TexParameteri,
+ void,
+ (GLenum target, GLenum pname, GLint param),
+ (target, pname, param))
+VISIT_GL_CALL(TexParameteriv,
+ void,
+ (GLenum target, GLenum pname, const GLint* params),
+ (target, pname, params))
+VISIT_GL_CALL(
+ TexSubImage2D,
+ void,
+ (GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void* pixels),
+ (target, level, xoffset, yoffset, width, height, format, type, pixels))
+VISIT_GL_CALL(Uniform1f, void, (GLint location, GLfloat x), (location, x))
+VISIT_GL_CALL(Uniform1fv,
+ void,
+ (GLint location, GLsizei count, const GLfloat* v),
+ (location, count, v))
+VISIT_GL_CALL(Uniform1i, void, (GLint location, GLint x), (location, x))
+VISIT_GL_CALL(Uniform1iv,
+ void,
+ (GLint location, GLsizei count, const GLint* v),
+ (location, count, v))
+VISIT_GL_CALL(Uniform2f,
+ void,
+ (GLint location, GLfloat x, GLfloat y),
+ (location, x, y))
+VISIT_GL_CALL(Uniform2fv,
+ void,
+ (GLint location, GLsizei count, const GLfloat* v),
+ (location, count, v))
+VISIT_GL_CALL(Uniform2i,
+ void,
+ (GLint location, GLint x, GLint y),
+ (location, x, y))
+VISIT_GL_CALL(Uniform2iv,
+ void,
+ (GLint location, GLsizei count, const GLint* v),
+ (location, count, v))
+VISIT_GL_CALL(Uniform3f,
+ void,
+ (GLint location, GLfloat x, GLfloat y, GLfloat z),
+ (location, x, y, z))
+VISIT_GL_CALL(Uniform3fv,
+ void,
+ (GLint location, GLsizei count, const GLfloat* v),
+ (location, count, v))
+VISIT_GL_CALL(Uniform3i,
+ void,
+ (GLint location, GLint x, GLint y, GLint z),
+ (location, x, y, z))
+VISIT_GL_CALL(Uniform3iv,
+ void,
+ (GLint location, GLsizei count, const GLint* v),
+ (location, count, v))
+VISIT_GL_CALL(Uniform4f,
+ void,
+ (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w),
+ (location, x, y, z, w))
+VISIT_GL_CALL(Uniform4fv,
+ void,
+ (GLint location, GLsizei count, const GLfloat* v),
+ (location, count, v))
+VISIT_GL_CALL(Uniform4i,
+ void,
+ (GLint location, GLint x, GLint y, GLint z, GLint w),
+ (location, x, y, z, w))
+VISIT_GL_CALL(Uniform4iv,
+ void,
+ (GLint location, GLsizei count, const GLint* v),
+ (location, count, v))
+VISIT_GL_CALL(
+ UniformMatrix2fv,
+ void,
+ (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value),
+ (location, count, transpose, value))
+VISIT_GL_CALL(
+ UniformMatrix3fv,
+ void,
+ (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value),
+ (location, count, transpose, value))
+VISIT_GL_CALL(
+ UniformMatrix4fv,
+ void,
+ (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value),
+ (location, count, transpose, value))
+VISIT_GL_CALL(UseProgram, void, (GLuint program), (program))
+VISIT_GL_CALL(ValidateProgram, void, (GLuint program), (program))
+VISIT_GL_CALL(VertexAttrib1f, void, (GLuint indx, GLfloat x), (indx, x))
+VISIT_GL_CALL(VertexAttrib1fv,
+ void,
+ (GLuint indx, const GLfloat* values),
+ (indx, values))
+VISIT_GL_CALL(VertexAttrib2f,
+ void,
+ (GLuint indx, GLfloat x, GLfloat y),
+ (indx, x, y))
+VISIT_GL_CALL(VertexAttrib2fv,
+ void,
+ (GLuint indx, const GLfloat* values),
+ (indx, values))
+VISIT_GL_CALL(VertexAttrib3f,
+ void,
+ (GLuint indx, GLfloat x, GLfloat y, GLfloat z),
+ (indx, x, y, z))
+VISIT_GL_CALL(VertexAttrib3fv,
+ void,
+ (GLuint indx, const GLfloat* values),
+ (indx, values))
+VISIT_GL_CALL(VertexAttrib4f,
+ void,
+ (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w),
+ (indx, x, y, z, w))
+VISIT_GL_CALL(VertexAttrib4fv,
+ void,
+ (GLuint indx, const GLfloat* values),
+ (indx, values))
+VISIT_GL_CALL(VertexAttribPointer,
+ void,
+ (GLuint indx,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void* ptr),
+ (indx, size, type, normalized, stride, ptr))
+VISIT_GL_CALL(Viewport,
+ void,
+ (GLint x, GLint y, GLsizei width, GLsizei height),
+ (x, y, width, height))
diff --git a/chromium/mojo/public/c/gles2/gles2_export.h b/chromium/mojo/public/c/gles2/gles2_export.h
new file mode 100644
index 00000000000..4f8796da069
--- /dev/null
+++ b/chromium/mojo/public/c/gles2/gles2_export.h
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_GLES2_GLES2_EXPORT_H_
+#define MOJO_PUBLIC_C_GLES2_GLES2_EXPORT_H_
+
+#if defined(WIN32)
+
+#if defined(MOJO_GLES2_IMPLEMENTATION)
+#define MOJO_GLES2_EXPORT __declspec(dllexport)
+#else
+#define MOJO_GLES2_EXPORT __declspec(dllimport)
+#endif
+
+#else // !defined(WIN32)
+
+#if defined(MOJO_GLES2_IMPLEMENTATION)
+#define MOJO_GLES2_EXPORT __attribute__((visibility("default")))
+#else
+#define MOJO_GLES2_EXPORT
+#endif
+
+#endif // defined(WIN32)
+
+#endif // MOJO_PUBLIC_C_GLES2_GLES2_EXPORT_H_
diff --git a/chromium/mojo/public/c/gles2/gles2_types.h b/chromium/mojo/public/c/gles2/gles2_types.h
new file mode 100644
index 00000000000..dd2a21314cc
--- /dev/null
+++ b/chromium/mojo/public/c/gles2/gles2_types.h
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_GLES2_GLES2_TYPES_H_
+#define MOJO_PUBLIC_C_GLES2_GLES2_TYPES_H_
+
+// Note: This header should be compilable as C.
+
+#include <stdint.h>
+
+#include "mojo/public/c/gles2/gles2_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct MojoGLES2ContextPrivate* MojoGLES2Context;
+typedef void (*MojoGLES2ContextLost)(void* closure);
+typedef void (*MojoGLES2DrawAnimationFrame)(void* closure);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // MOJO_PUBLIC_C_GLES2_GLES2_TYPES_H_
diff --git a/chromium/mojo/public/c/system/buffer.h b/chromium/mojo/public/c/system/buffer.h
new file mode 100644
index 00000000000..86cf8223ee0
--- /dev/null
+++ b/chromium/mojo/public/c/system/buffer.h
@@ -0,0 +1,187 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains types/constants and functions specific to buffers (and in
+// particular shared buffers).
+// TODO(vtl): Reorganize this file (etc.) to separate general buffer functions
+// from (shared) buffer creation.
+//
+// Note: This header should be compilable as C.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_BUFFER_H_
+#define MOJO_PUBLIC_C_SYSTEM_BUFFER_H_
+
+#include "mojo/public/c/system/macros.h"
+#include "mojo/public/c/system/system_export.h"
+#include "mojo/public/c/system/types.h"
+
+// |MojoCreateSharedBufferOptions|: Used to specify creation parameters for a
+// shared buffer to |MojoCreateSharedBuffer()|.
+// |uint32_t struct_size|: Set to the size of the
+// |MojoCreateSharedBufferOptions| struct. (Used to allow for future
+// extensions.)
+// |MojoCreateSharedBufferOptionsFlags flags|: Reserved for future use.
+// |MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE|: No flags; default mode.
+//
+// TODO(vtl): Maybe add a flag to indicate whether the memory should be
+// executable or not?
+// TODO(vtl): Also a flag for discardable (ashmem-style) buffers.
+
+typedef uint32_t MojoCreateSharedBufferOptionsFlags;
+
+#ifdef __cplusplus
+const MojoCreateSharedBufferOptionsFlags
+ MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE = 0;
+#else
+#define MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE \
+ ((MojoCreateSharedBufferOptionsFlags) 0)
+#endif
+
+MOJO_COMPILE_ASSERT(MOJO_ALIGNOF(int64_t) == 8, int64_t_has_weird_alignment);
+struct MOJO_ALIGNAS(8) MojoCreateSharedBufferOptions {
+ uint32_t struct_size;
+ MojoCreateSharedBufferOptionsFlags flags;
+};
+MOJO_COMPILE_ASSERT(sizeof(MojoCreateSharedBufferOptions) == 8,
+ MojoCreateSharedBufferOptions_has_wrong_size);
+
+// |MojoDuplicateBufferHandleOptions|: Used to specify parameters in duplicating
+// access to a shared buffer to |MojoDuplicateBufferHandle()|.
+// |uint32_t struct_size|: Set to the size of the
+// |MojoDuplicateBufferHandleOptions| struct. (Used to allow for future
+// extensions.)
+// |MojoDuplicateBufferHandleOptionsFlags flags|: Reserved for future use.
+// |MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE|: No flags; default
+// mode.
+//
+// TODO(vtl): Add flags to remove writability (and executability)? Also, COW?
+
+typedef uint32_t MojoDuplicateBufferHandleOptionsFlags;
+
+#ifdef __cplusplus
+const MojoDuplicateBufferHandleOptionsFlags
+ MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE = 0;
+#else
+#define MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE \
+ ((MojoDuplicateBufferHandleOptionsFlags) 0)
+#endif
+
+struct MojoDuplicateBufferHandleOptions {
+ uint32_t struct_size;
+ MojoDuplicateBufferHandleOptionsFlags flags;
+};
+MOJO_COMPILE_ASSERT(sizeof(MojoDuplicateBufferHandleOptions) == 8,
+ MojoDuplicateBufferHandleOptions_has_wrong_size);
+
+// |MojoMapBufferFlags|: Used to specify different modes to |MojoMapBuffer()|.
+// |MOJO_MAP_BUFFER_FLAG_NONE| - No flags; default mode.
+
+typedef uint32_t MojoMapBufferFlags;
+
+#ifdef __cplusplus
+const MojoMapBufferFlags MOJO_MAP_BUFFER_FLAG_NONE = 0;
+#else
+#define MOJO_MAP_BUFFER_FLAG_NONE ((MojoMapBufferFlags) 0)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Note: See the comment in functions.h about the meaning of the "optional"
+// label for pointer parameters.
+
+// Creates a buffer of size |num_bytes| bytes that can be shared between
+// applications (by duplicating the handle -- see |MojoDuplicateBufferHandle()|
+// -- and passing it over a message pipe). To access the buffer, one must call
+// |MojoMapBuffer()|.
+//
+// |options| may be set to null for a shared buffer with the default options.
+//
+// On success, |*shared_buffer_handle| will be set to the handle for the shared
+// buffer. (On failure, it is not modified.)
+//
+// Note: While more than |num_bytes| bytes may apparently be
+// available/visible/readable/writable, trying to use those extra bytes is
+// undefined behavior.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+// |*options| is invalid or |shared_buffer_handle| looks invalid).
+// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has
+// been reached (e.g., if the requested size was too large, or if the
+// maximum number of handles was exceeded).
+// |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|.
+MOJO_SYSTEM_EXPORT MojoResult MojoCreateSharedBuffer(
+ const struct MojoCreateSharedBufferOptions* options, // Optional.
+ uint64_t num_bytes, // In.
+ MojoHandle* shared_buffer_handle); // Out.
+
+// Duplicates the handle |buffer_handle| to a buffer. This creates another
+// handle (returned in |*new_buffer_handle| on success), which can then be sent
+// to another application over a message pipe, while retaining access to the
+// |buffer_handle| (and any mappings that it may have).
+//
+// |options| may be set to null to duplicate the buffer handle with the default
+// options.
+//
+// On success, |*shared_buffer_handle| will be set to the handle for the new
+// buffer handle. (On failure, it is not modified.)
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+// |buffer_handle| is not a valid buffer handle, |*options| is invalid, or
+// |new_buffer_handle| looks invalid).
+// |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|.
+MOJO_SYSTEM_EXPORT MojoResult MojoDuplicateBufferHandle(
+ MojoHandle buffer_handle,
+ const struct MojoDuplicateBufferHandleOptions* options, // Optional.
+ MojoHandle* new_buffer_handle); // Out.
+
+// Maps the part (at offset |offset| of length |num_bytes|) of the buffer given
+// by |buffer_handle| into memory, with options specified by |flags|. |offset +
+// num_bytes| must be less than or equal to the size of the buffer. On success,
+// |*buffer| points to memory with the requested part of the buffer. (On
+// failure, it is not modified.)
+//
+// A single buffer handle may have multiple active mappings (possibly depending
+// on the buffer type). The permissions (e.g., writable or executable) of the
+// returned memory may depend on the properties of the buffer and properties
+// attached to the buffer handle as well as |flags|.
+//
+// Note: Though data outside the specified range may apparently be
+// available/visible/readable/writable, trying to use those extra bytes is
+// undefined behavior.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+// |buffer_handle| is not a valid buffer handle, the range specified by
+// |offset| and |num_bytes| is not valid, or |buffer| looks invalid).
+// |MOJO_RESULT_RESOURCE_EXHAUSTED| if the mapping operation itself failed
+// (e.g., due to not having appropriate address space available).
+MOJO_SYSTEM_EXPORT MojoResult MojoMapBuffer(MojoHandle buffer_handle,
+ uint64_t offset,
+ uint64_t num_bytes,
+ void** buffer, // Out.
+ MojoMapBufferFlags flags);
+
+// Unmaps a buffer pointer that was mapped by |MojoMapBuffer()|. |buffer| must
+// have been the result of |MojoMapBuffer()| (not some pointer strictly inside
+// the mapped memory), and the entire mapping will be removed (partial unmapping
+// is not supported). A mapping may only be unmapped exactly once.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if |buffer| is invalid (e.g., if it is not
+// the result of |MojoMapBuffer()| or it has already been unmapped).
+MOJO_SYSTEM_EXPORT MojoResult MojoUnmapBuffer(void* buffer); // In.
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // MOJO_PUBLIC_C_SYSTEM_BUFFER_H_
diff --git a/chromium/mojo/public/c/system/core.h b/chromium/mojo/public/c/system/core.h
new file mode 100644
index 00000000000..5ea03fc5a5e
--- /dev/null
+++ b/chromium/mojo/public/c/system/core.h
@@ -0,0 +1,20 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is a catch-all header that includes everything.
+//
+// Note: This header should be compilable as C.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_CORE_H_
+#define MOJO_PUBLIC_C_SYSTEM_CORE_H_
+
+#include "mojo/public/c/system/buffer.h"
+#include "mojo/public/c/system/data_pipe.h"
+#include "mojo/public/c/system/functions.h"
+#include "mojo/public/c/system/macros.h"
+#include "mojo/public/c/system/message_pipe.h"
+#include "mojo/public/c/system/system_export.h"
+#include "mojo/public/c/system/types.h"
+
+#endif // MOJO_PUBLIC_C_SYSTEM_CORE_H_
diff --git a/chromium/mojo/public/c/system/data_pipe.h b/chromium/mojo/public/c/system/data_pipe.h
new file mode 100644
index 00000000000..e28cf6eff11
--- /dev/null
+++ b/chromium/mojo/public/c/system/data_pipe.h
@@ -0,0 +1,367 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains types/constants and functions specific to data pipes.
+//
+// Note: This header should be compilable as C.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_DATA_PIPE_H_
+#define MOJO_PUBLIC_C_SYSTEM_DATA_PIPE_H_
+
+#include "mojo/public/c/system/macros.h"
+#include "mojo/public/c/system/system_export.h"
+#include "mojo/public/c/system/types.h"
+
+// |MojoCreateDataPipeOptions|: Used to specify creation parameters for a data
+// pipe to |MojoCreateDataPipe()|.
+// |uint32_t struct_size|: Set to the size of the |MojoCreateDataPipeOptions|
+// struct. (Used to allow for future extensions.)
+// |MojoCreateDataPipeOptionsFlags flags|: Used to specify different modes of
+// operation.
+// |MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE|: No flags; default mode.
+// |MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD|: May discard data for
+// whatever reason; best-effort delivery. In particular, if the capacity
+// is reached, old data may be discard to make room for new data.
+// |uint32_t element_num_bytes|: The size of an element, in bytes. All
+// transactions and buffers will consist of an integral number of
+// elements. Must be nonzero.
+// |uint32_t capacity_num_bytes|: The capacity of the data pipe, in number of
+// bytes; must be a multiple of |element_num_bytes|. The data pipe will
+// always be able to queue AT LEAST this much data. Set to zero to opt for
+// a system-dependent automatically-calculated capacity (which will always
+// be at least one element).
+
+typedef uint32_t MojoCreateDataPipeOptionsFlags;
+
+#ifdef __cplusplus
+const MojoCreateDataPipeOptionsFlags
+ MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE = 0;
+const MojoCreateDataPipeOptionsFlags
+ MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD = 1 << 0;
+#else
+#define MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE \
+ ((MojoCreateDataPipeOptionsFlags) 0)
+#define MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD \
+ ((MojoCreateDataPipeOptionsFlags) 1 << 0)
+#endif
+
+MOJO_COMPILE_ASSERT(MOJO_ALIGNOF(int64_t) == 8, int64_t_has_weird_alignment);
+struct MOJO_ALIGNAS(8) MojoCreateDataPipeOptions {
+ uint32_t struct_size;
+ MojoCreateDataPipeOptionsFlags flags;
+ uint32_t element_num_bytes;
+ uint32_t capacity_num_bytes;
+};
+MOJO_COMPILE_ASSERT(sizeof(MojoCreateDataPipeOptions) == 16,
+ MojoCreateDataPipeOptions_has_wrong_size);
+
+// |MojoWriteDataFlags|: Used to specify different modes to |MojoWriteData()|
+// and |MojoBeginWriteData()|.
+// |MOJO_WRITE_DATA_FLAG_NONE| - No flags; default mode.
+// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| - Write either all the elements
+// requested or none of them.
+
+typedef uint32_t MojoWriteDataFlags;
+
+#ifdef __cplusplus
+const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_NONE = 0;
+const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_ALL_OR_NONE = 1 << 0;
+#else
+#define MOJO_WRITE_DATA_FLAG_NONE ((MojoWriteDataFlags) 0)
+#define MOJO_WRITE_DATA_FLAG_ALL_OR_NONE ((MojoWriteDataFlags) 1 << 0)
+#endif
+
+// |MojoReadDataFlags|: Used to specify different modes to |MojoReadData()| and
+// |MojoBeginReadData()|.
+// |MOJO_READ_DATA_FLAG_NONE| - No flags; default mode.
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| - Read (or discard) either the requested
+// number of elements or none.
+// |MOJO_READ_DATA_FLAG_DISCARD| - Discard (up to) the requested number of
+// elements.
+// |MOJO_READ_DATA_FLAG_QUERY| - Query the number of elements available to
+// read. For use with |MojoReadData()| only. Mutually exclusive with
+// |MOJO_READ_DATA_FLAG_DISCARD| and |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is
+// ignored if this flag is set.
+
+typedef uint32_t MojoReadDataFlags;
+
+#ifdef __cplusplus
+const MojoReadDataFlags MOJO_READ_DATA_FLAG_NONE = 0;
+const MojoReadDataFlags MOJO_READ_DATA_FLAG_ALL_OR_NONE = 1 << 0;
+const MojoReadDataFlags MOJO_READ_DATA_FLAG_DISCARD = 1 << 1;
+const MojoReadDataFlags MOJO_READ_DATA_FLAG_QUERY = 1 << 2;
+#else
+#define MOJO_READ_DATA_FLAG_NONE ((MojoReadDataFlags) 0)
+#define MOJO_READ_DATA_FLAG_ALL_OR_NONE ((MojoReadDataFlags) 1 << 0)
+#define MOJO_READ_DATA_FLAG_DISCARD ((MojoReadDataFlags) 1 << 1)
+#define MOJO_READ_DATA_FLAG_QUERY ((MojoReadDataFlags) 1 << 2)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Note: See the comment in functions.h about the meaning of the "optional"
+// label for pointer parameters.
+
+// Creates a data pipe, which is a unidirectional communication channel for
+// unframed data, with the given options. Data is unframed, but must come as
+// (multiples of) discrete elements, of the size given in |options|. See
+// |MojoCreateDataPipeOptions| for a description of the different options
+// available for data pipes.
+//
+// |options| may be set to null for a data pipe with the default options (which
+// will have an element size of one byte and have some system-dependent
+// capacity).
+//
+// On success, |*data_pipe_producer_handle| will be set to the handle for the
+// producer and |*data_pipe_consumer_handle| will be set to the handle for the
+// consumer. (On failure, they are not modified.)
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+// |*options| is invalid or one of the handle pointers looks invalid).
+// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has
+// been reached (e.g., if the requested capacity was too large, or if the
+// maximum number of handles was exceeded).
+// |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|.
+MOJO_SYSTEM_EXPORT MojoResult MojoCreateDataPipe(
+ const struct MojoCreateDataPipeOptions* options, // Optional.
+ MojoHandle* data_pipe_producer_handle, // Out.
+ MojoHandle* data_pipe_consumer_handle); // Out.
+
+// Writes the given data to the data pipe producer given by
+// |data_pipe_producer_handle|. |elements| points to data of size |*num_bytes|;
+// |*num_bytes| should be a multiple of the data pipe's element size. If
+// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| is set in |flags|, either all the data
+// will be written or none is.
+//
+// On success, |*num_bytes| is set to the amount of data that was actually
+// written.
+//
+// Note: If the data pipe has the "may discard" option flag (specified on
+// creation), this will discard as much data as required to write the given
+// data, starting with the earliest written data that has not been consumed.
+// However, even with "may discard", if |*num_bytes| is greater than the data
+// pipe's capacity (and |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| is not set), this
+// will write the maximum amount possible (namely, the data pipe's capacity) and
+// set |*num_bytes| to that amount. It will *not* discard data from |elements|.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+// |data_pipe_producer_dispatcher| is not a handle to a data pipe
+// producer, |elements| does not look like a valid pointer, or
+// |*num_bytes| is not a multiple of the data pipe's element size).
+// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been
+// closed.
+// |MOJO_RESULT_OUT_OF_RANGE| if |flags| has
+// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and the required amount of data
+// (specified by |*num_bytes|) could not be written.
+// |MOJO_RESULT_BUSY| if there is a two-phase write ongoing with
+// |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been
+// called, but not yet the matching |MojoEndWriteData()|).
+// |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the
+// consumer is still open) and |flags| does *not* have
+// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set.
+//
+// TODO(vtl): Should there be a way of querying how much data can be written?
+MOJO_SYSTEM_EXPORT MojoResult MojoWriteData(
+ MojoHandle data_pipe_producer_handle,
+ const void* elements,
+ uint32_t* num_bytes, // In/out.
+ MojoWriteDataFlags flags);
+
+// Begins a two-phase write to the data pipe producer given by
+// |data_pipe_producer_handle|. On success, |*buffer| will be a pointer to which
+// the caller can write |*buffer_num_bytes| bytes of data. If flags has
+// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set, then the output value
+// |*buffer_num_bytes| will be at least as large as its input value, which must
+// also be a multiple of the element size (if |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE|
+// is not set, the input value of |*buffer_num_bytes| is ignored).
+//
+// During a two-phase write, |data_pipe_producer_handle| is *not* writable.
+// E.g., if another thread tries to write to it, it will get |MOJO_RESULT_BUSY|;
+// that thread can then wait for |data_pipe_producer_handle| to become writable
+// again.
+//
+// Once the caller has finished writing data to |*buffer|, it should call
+// |MojoEndWriteData()| to specify the amount written and to complete the
+// two-phase write.
+//
+// Note: If the data pipe has the "may discard" option flag (specified on
+// creation) and |flags| has |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set, this may
+// discard some data.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+// |data_pipe_producer_handle| is not a handle to a data pipe producer,
+// |buffer| or |buffer_num_bytes| does not look like a valid pointer, or
+// flags has |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and
+// |*buffer_num_bytes| is not a multiple of the element size).
+// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been
+// closed.
+// |MOJO_RESULT_OUT_OF_RANGE| if |flags| has
+// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and the required amount of data
+// (specified by |*buffer_num_bytes|) cannot be written contiguously at
+// this time. (Note that there may be space available for the required
+// amount of data, but the "next" write position may not be large enough.)
+// |MOJO_RESULT_BUSY| if there is already a two-phase write ongoing with
+// |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been
+// called, but not yet the matching |MojoEndWriteData()|).
+// |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the
+// consumer is still open).
+MOJO_SYSTEM_EXPORT MojoResult MojoBeginWriteData(
+ MojoHandle data_pipe_producer_handle,
+ void** buffer, // Out.
+ uint32_t* buffer_num_bytes, // In/out.
+ MojoWriteDataFlags flags);
+
+// Ends a two-phase write to the data pipe producer given by
+// |data_pipe_producer_handle| that was begun by a call to
+// |MojoBeginWriteData()| on the same handle. |num_bytes_written| should
+// indicate the amount of data actually written; it must be less than or equal
+// to the value of |*buffer_num_bytes| output by |MojoBeginWriteData()| and must
+// be a multiple of the element size. The buffer given by |*buffer| from
+// |MojoBeginWriteData()| must have been filled with exactly |num_bytes_written|
+// bytes of data.
+//
+// On failure, the two-phase write (if any) is ended (so the handle may become
+// writable again, if there's space available) but no data written to |*buffer|
+// is "put into" the data pipe.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if |data_pipe_producer_handle| is not a
+// handle to a data pipe producer or |num_bytes_written| is invalid
+// (greater than the maximum value provided by |MojoBeginWriteData()| or
+// not a multiple of the element size).
+// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer is not in a
+// two-phase write (e.g., |MojoBeginWriteData()| was not called or
+// |MojoEndWriteData()| has already been called).
+MOJO_SYSTEM_EXPORT MojoResult MojoEndWriteData(
+ MojoHandle data_pipe_producer_handle,
+ uint32_t num_bytes_written);
+
+// Reads data from the data pipe consumer given by |data_pipe_consumer_handle|.
+// May also be used to discard data or query the amount of data available.
+//
+// If |flags| has neither |MOJO_READ_DATA_FLAG_DISCARD| nor
+// |MOJO_READ_DATA_FLAG_QUERY| set, this tries to read up to |*num_bytes| (which
+// must be a multiple of the data pipe's element size) bytes of data to
+// |elements| and set |*num_bytes| to the amount actually read. If flags has
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, it will either read exactly
+// |*num_bytes| bytes of data or none.
+//
+// If flags has |MOJO_READ_DATA_FLAG_DISCARD| set, it discards up to
+// |*num_bytes| (which again be a multiple of the element size) bytes of data,
+// setting |*num_bytes| to the amount actually discarded. If flags has
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE|, it will either discard exactly
+// |*num_bytes| bytes of data or none. In this case, |MOJO_READ_DATA_FLAG_QUERY|
+// must not be set, and |elements| is ignored (and should typically be set to
+// null).
+//
+// If flags has |MOJO_READ_DATA_FLAG_QUERY| set, it queries the amount of data
+// available, setting |*num_bytes| to the number of bytes available. In this
+// case, |MOJO_READ_DATA_FLAG_DISCARD| must not be set, and
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is ignored, as are |elements| and the input
+// value of |*num_bytes|.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success (see above for a description of the different
+// operations).
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g.,
+// |data_pipe_consumer_handle| is invalid, the combination of flags in
+// |flags| is invalid, etc.).
+// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been
+// closed and data (or the required amount of data) was not available to
+// be read or discarded.
+// |MOJO_RESULT_OUT_OF_RANGE| if |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
+// set and the required amount of data is not available to be read or
+// discarded (and the producer is still open).
+// |MOJO_RESULT_BUSY| if there is a two-phase read ongoing with
+// |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been
+// called, but not yet the matching |MojoEndReadData()|).
+// |MOJO_RESULT_SHOULD_WAIT| if there is no data to be read or discarded (and
+// the producer is still open) and |flags| does *not* have
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set.
+MOJO_SYSTEM_EXPORT MojoResult MojoReadData(
+ MojoHandle data_pipe_consumer_handle,
+ void* elements, // Out.
+ uint32_t* num_bytes, // In/out.
+ MojoReadDataFlags flags);
+
+// Begins a two-phase read from the data pipe consumer given by
+// |data_pipe_consumer_handle|. On success, |*buffer| will be a pointer from
+// which the caller can read |*buffer_num_bytes| bytes of data. If flags has
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, then the output value
+// |*buffer_num_bytes| will be at least as large as its input value, which must
+// also be a multiple of the element size (if |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
+// is not set, the input value of |*buffer_num_bytes| is ignored). |flags| must
+// not have |MOJO_READ_DATA_FLAG_DISCARD| or |MOJO_READ_DATA_FLAG_QUERY| set.
+//
+// During a two-phase read, |data_pipe_consumer_handle| is *not* readable.
+// E.g., if another thread tries to read from it, it will get
+// |MOJO_RESULT_BUSY|; that thread can then wait for |data_pipe_consumer_handle|
+// to become readable again.
+//
+// Once the caller has finished reading data from |*buffer|, it should call
+// |MojoEndReadData()| to specify the amount read and to complete the two-phase
+// read.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+// |data_pipe_consumer_handle| is not a handle to a data pipe consumer,
+// |buffer| or |buffer_num_bytes| does not look like a valid pointer,
+// |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set and
+// |*buffer_num_bytes| is not a multiple of the element size, or |flags|
+// has invalid flags set).
+// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been
+// closed.
+// |MOJO_RESULT_OUT_OF_RANGE| if |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
+// set and the required amount of data (specified by |*buffer_num_bytes|)
+// cannot be read from a contiguous buffer at this time. (Note that there
+// may be the required amount of data, but it may not be contiguous.)
+// |MOJO_RESULT_BUSY| if there is already a two-phase read ongoing with
+// |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been
+// called, but not yet the matching |MojoEndReadData()|).
+// |MOJO_RESULT_SHOULD_WAIT| if no data can currently be read (and the
+// producer is still open).
+MOJO_SYSTEM_EXPORT MojoResult MojoBeginReadData(
+ MojoHandle data_pipe_consumer_handle,
+ const void** buffer, // Out.
+ uint32_t* buffer_num_bytes, // In/out.
+ MojoReadDataFlags flags);
+
+// Ends a two-phase read from the data pipe consumer given by
+// |data_pipe_consumer_handle| that was begun by a call to |MojoBeginReadData()|
+// on the same handle. |num_bytes_read| should indicate the amount of data
+// actually read; it must be less than or equal to the value of
+// |*buffer_num_bytes| output by |MojoBeginReadData()| and must be a multiple of
+// the element size.
+//
+// On failure, the two-phase read (if any) is ended (so the handle may become
+// readable again) but no data is "removed" from the data pipe.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if |data_pipe_consumer_handle| is not a
+// handle to a data pipe consumer or |num_bytes_written| is invalid
+// (greater than the maximum value provided by |MojoBeginReadData()| or
+// not a multiple of the element size).
+// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer is not in a
+// two-phase read (e.g., |MojoBeginReadData()| was not called or
+// |MojoEndReadData()| has already been called).
+MOJO_SYSTEM_EXPORT MojoResult MojoEndReadData(
+ MojoHandle data_pipe_consumer_handle,
+ uint32_t num_bytes_read);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // MOJO_PUBLIC_C_SYSTEM_DATA_PIPE_H_
diff --git a/chromium/mojo/public/c/system/functions.h b/chromium/mojo/public/c/system/functions.h
new file mode 100644
index 00000000000..9d2ef6ca800
--- /dev/null
+++ b/chromium/mojo/public/c/system/functions.h
@@ -0,0 +1,87 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains basic functions common to different Mojo system APIs.
+//
+// Note: This header should be compilable as C.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_FUNCTIONS_H_
+#define MOJO_PUBLIC_C_SYSTEM_FUNCTIONS_H_
+
+// Note: This header should be compilable as C.
+
+#include "mojo/public/c/system/system_export.h"
+#include "mojo/public/c/system/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Note: Pointer parameters that are labelled "optional" may be null (at least
+// under some circumstances). Non-const pointer parameters are also labeled
+// "in", "out", or "in/out", to indicate how they are used. (Note that how/if
+// such a parameter is used may depend on other parameters or the requested
+// operation's success/failure. E.g., a separate |flags| parameter may control
+// whether a given "in/out" parameter is used for input, output, or both.)
+
+// Platform-dependent monotonically increasing tick count representing "right
+// now." The resolution of this clock is ~1-15ms. Resolution varies depending
+// on hardware/operating system configuration.
+MOJO_SYSTEM_EXPORT MojoTimeTicks MojoGetTimeTicksNow(void);
+
+// Closes the given |handle|.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle.
+//
+// Concurrent operations on |handle| may succeed (or fail as usual) if they
+// happen before the close, be cancelled with result |MOJO_RESULT_CANCELLED| if
+// they properly overlap (this is likely the case with |MojoWait()|, etc.), or
+// fail with |MOJO_RESULT_INVALID_ARGUMENT| if they happen after.
+MOJO_SYSTEM_EXPORT MojoResult MojoClose(MojoHandle handle);
+
+// Waits on the given handle until a signal indicated by |signals| is satisfied
+// or until |deadline| has passed.
+//
+// Returns:
+// |MOJO_RESULT_OK| if some signal in |signals| was satisfied (or is already
+// satisfied).
+// |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle (e.g., if
+// it has already been closed).
+// |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline has passed without any of
+// the signals being satisfied.
+// |MOJO_RESULT_FAILED_PRECONDITION| if it is or becomes impossible that any
+// signal in |signals| will ever be satisfied.
+//
+// If there are multiple waiters (on different threads, obviously) waiting on
+// the same handle and signal, and that signal becomes is satisfied, all waiters
+// will be awoken.
+MOJO_SYSTEM_EXPORT MojoResult MojoWait(MojoHandle handle,
+ MojoHandleSignals signals,
+ MojoDeadline deadline);
+
+// Waits on |handles[0]|, ..., |handles[num_handles-1]| for at least one of them
+// to satisfy a signal indicated by |signals[0]|, ..., |signals[num_handles-1]|,
+// respectively, or until |deadline| has passed.
+//
+// Returns:
+// The index |i| (from 0 to |num_handles-1|) if |handle[i]| satisfies a signal
+// from |signals[i]|.
+// |MOJO_RESULT_INVALID_ARGUMENT| if some |handle[i]| is not a valid handle
+// (e.g., if it has already been closed).
+// |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline has passed without any of
+// handles satisfying any of its signals.
+// |MOJO_RESULT_FAILED_PRECONDITION| if it is or becomes impossible that SOME
+// |handle[i]| will ever satisfy any of the signals in |signals[i]|.
+MOJO_SYSTEM_EXPORT MojoResult MojoWaitMany(const MojoHandle* handles,
+ const MojoHandleSignals* signals,
+ uint32_t num_handles,
+ MojoDeadline deadline);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // MOJO_PUBLIC_C_SYSTEM_FUNCTIONS_H_
diff --git a/chromium/mojo/public/c/system/macros.h b/chromium/mojo/public/c/system/macros.h
new file mode 100644
index 00000000000..f1e3c7d6831
--- /dev/null
+++ b/chromium/mojo/public/c/system/macros.h
@@ -0,0 +1,72 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_MACROS_H_
+#define MOJO_PUBLIC_C_SYSTEM_MACROS_H_
+
+#include <stddef.h>
+
+// Annotate a variable indicating it's okay if it's unused.
+// Use like:
+// int x MOJO_ALLOW_UNUSED = ...;
+#if defined(__GNUC__)
+#define MOJO_ALLOW_UNUSED __attribute__((unused))
+#else
+#define MOJO_ALLOW_UNUSED
+#endif
+
+// Annotate a function indicating that the caller must examine the return value.
+// Use like:
+// int foo() MOJO_WARN_UNUSED_RESULT;
+// Note that it can only be used on the prototype, and not the definition.
+#if defined(__GNUC__)
+#define MOJO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+#define MOJO_WARN_UNUSED_RESULT
+#endif
+
+// Assert things at compile time. (|msg| should be a valid identifier name.)
+// This macro is currently C++-only, but we want to use it in the C core.h.
+// Use like:
+// MOJO_COMPILE_ASSERT(sizeof(Foo) == 12, Foo_has_invalid_size);
+#if __cplusplus >= 201103L
+#define MOJO_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
+#elif defined(__cplusplus)
+namespace mojo { template <bool> struct CompileAssert {}; }
+#define MOJO_COMPILE_ASSERT(expr, msg) \
+ typedef ::mojo::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+#else
+#define MOJO_COMPILE_ASSERT(expr, msg)
+#endif
+
+// Like the C++11 |alignof| operator.
+#if __cplusplus >= 201103L
+#define MOJO_ALIGNOF(type) alignof(type)
+#elif defined(__GNUC__)
+#define MOJO_ALIGNOF(type) __alignof__(type)
+#elif defined(_MSC_VER)
+// The use of |sizeof| is to work around a bug in MSVC 2010 (see
+// http://goo.gl/isH0C; supposedly fixed since then).
+#define MOJO_ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type))
+#else
+#error "Please define MOJO_ALIGNOF() for your compiler."
+#endif
+
+// Specify the alignment of a |struct|, etc.
+// Use like:
+// struct MOJO_ALIGNAS(8) Foo { ... };
+// Unlike the C++11 |alignas()|, |alignment| must be an integer. It may not be a
+// type, nor can it be an expression like |MOJO_ALIGNOF(type)| (due to the
+// non-C++11 MSVS version).
+#if __cplusplus >= 201103L
+#define MOJO_ALIGNAS(alignment) alignas(alignment)
+#elif defined(__GNUC__)
+#define MOJO_ALIGNAS(alignment) __attribute__((aligned(alignment)))
+#elif defined(_MSC_VER)
+#define MOJO_ALIGNAS(alignment) __declspec(align(alignment))
+#else
+#error "Please define MOJO_ALIGNAS() for your compiler."
+#endif
+
+#endif // MOJO_PUBLIC_C_SYSTEM_MACROS_H_
diff --git a/chromium/mojo/public/c/system/message_pipe.h b/chromium/mojo/public/c/system/message_pipe.h
new file mode 100644
index 00000000000..0d0b61b7c5b
--- /dev/null
+++ b/chromium/mojo/public/c/system/message_pipe.h
@@ -0,0 +1,178 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains types/constants and functions specific to message pipes.
+//
+// Note: This header should be compilable as C.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_MESSAGE_PIPE_H_
+#define MOJO_PUBLIC_C_SYSTEM_MESSAGE_PIPE_H_
+
+#include "mojo/public/c/system/macros.h"
+#include "mojo/public/c/system/system_export.h"
+#include "mojo/public/c/system/types.h"
+
+// |MojoCreateMessagePipeOptions|: Used to specify creation parameters for a
+// message pipe to |MojoCreateMessagePipe()|.
+// |uint32_t struct_size|: Set to the size of the
+// |MojoCreateMessagePipeOptions| struct. (Used to allow for future
+// extensions.)
+// |MojoCreateMessagePipeOptionsFlags flags|: Reserved for future use.
+// |MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE|: No flags; default mode.
+
+typedef uint32_t MojoCreateMessagePipeOptionsFlags;
+
+#ifdef __cplusplus
+const MojoCreateMessagePipeOptionsFlags
+ MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE = 0;
+#else
+#define MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE \
+ ((MojoCreateMessagePipeOptionsFlags) 0)
+#endif
+
+MOJO_COMPILE_ASSERT(MOJO_ALIGNOF(int64_t) == 8, int64_t_has_weird_alignment);
+struct MOJO_ALIGNAS(8) MojoCreateMessagePipeOptions {
+ uint32_t struct_size;
+ MojoCreateMessagePipeOptionsFlags flags;
+};
+MOJO_COMPILE_ASSERT(sizeof(MojoCreateMessagePipeOptions) == 8,
+ MojoCreateMessagePipeOptions_has_wrong_size);
+
+// |MojoWriteMessageFlags|: Used to specify different modes to
+// |MojoWriteMessage()|.
+// |MOJO_WRITE_MESSAGE_FLAG_NONE| - No flags; default mode.
+
+typedef uint32_t MojoWriteMessageFlags;
+
+#ifdef __cplusplus
+const MojoWriteMessageFlags MOJO_WRITE_MESSAGE_FLAG_NONE = 0;
+#else
+#define MOJO_WRITE_MESSAGE_FLAG_NONE ((MojoWriteMessageFlags) 0)
+#endif
+
+// |MojoReadMessageFlags|: Used to specify different modes to
+// |MojoReadMessage()|.
+// |MOJO_READ_MESSAGE_FLAG_NONE| - No flags; default mode.
+// |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| - If the message is unable to be read
+// for whatever reason (e.g., the caller-supplied buffer is too small),
+// discard the message (i.e., simply dequeue it).
+
+typedef uint32_t MojoReadMessageFlags;
+
+#ifdef __cplusplus
+const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_NONE = 0;
+const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_MAY_DISCARD = 1 << 0;
+#else
+#define MOJO_READ_MESSAGE_FLAG_NONE ((MojoReadMessageFlags) 0)
+#define MOJO_READ_MESSAGE_FLAG_MAY_DISCARD ((MojoReadMessageFlags) 1 << 0)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Note: See the comment in functions.h about the meaning of the "optional"
+// label for pointer parameters.
+
+// Creates a message pipe, which is a bidirectional communication channel for
+// framed data (i.e., messages). Messages can contain plain data and/or Mojo
+// handles.
+//
+// |options| may be set to null for a message pipe with the default options.
+//
+// On success, |*message_pipe_handle0| and |*message_pipe_handle1| are set to
+// handles for the two endpoints (ports) for the message pipe.
+//
+// Returns:
+// |MOJO_RESULT_OK| on success.
+// |MOJO_RESULT_INVALID_ARGUMENT| if |message_pipe_handle0| and/or
+// |message_pipe_handle1| do not appear to be valid pointers.
+// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has
+// been reached.
+//
+// TODO(vtl): Add an options struct pointer argument.
+MOJO_SYSTEM_EXPORT MojoResult MojoCreateMessagePipe(
+ const struct MojoCreateMessagePipeOptions* options, // Optional.
+ MojoHandle* message_pipe_handle0, // Out.
+ MojoHandle* message_pipe_handle1); // Out.
+
+// Writes a message to the message pipe endpoint given by |message_pipe_handle|,
+// with message data specified by |bytes| of size |num_bytes| and attached
+// handles specified by |handles| of count |num_handles|, and options specified
+// by |flags|. If there is no message data, |bytes| may be null, in which case
+// |num_bytes| must be zero. If there are no attached handles, |handles| may be
+// null, in which case |num_handles| must be zero.
+//
+// If handles are attached, on success the handles will no longer be valid (the
+// receiver will receive equivalent, but logically different, handles). Handles
+// to be sent should not be in simultaneous use (e.g., on another thread).
+//
+// Returns:
+// |MOJO_RESULT_OK| on success (i.e., the message was enqueued).
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+// |message_pipe_handle| is not a valid handle, or some of the
+// requirements above are not satisfied).
+// |MOJO_RESULT_RESOURCE_EXHAUSTED| if some system limit has been reached, or
+// the number of handles to send is too large (TODO(vtl): reconsider the
+// latter case).
+// |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed.
+// Note that closing an endpoint is not necessarily synchronous (e.g.,
+// across processes), so this function may be succeed even if the other
+// endpoint has been closed (in which case the message would be dropped).
+// |MOJO_RESULT_BUSY| if some handle to be sent is currently in use.
+//
+// TODO(vtl): Add a notion of capacity for message pipes, and return
+// |MOJO_RESULT_SHOULD_WAIT| if the message pipe is full.
+MOJO_SYSTEM_EXPORT MojoResult MojoWriteMessage(
+ MojoHandle message_pipe_handle,
+ const void* bytes, // Optional.
+ uint32_t num_bytes,
+ const MojoHandle* handles, // Optional.
+ uint32_t num_handles,
+ MojoWriteMessageFlags flags);
+
+// Reads a message from the message pipe endpoint given by
+// |message_pipe_handle|; also usable to query the size of the next message or
+// discard the next message. |bytes|/|*num_bytes| indicate the buffer/buffer
+// size to receive the message data (if any) and |handles|/|*num_handles|
+// indicate the buffer/maximum handle count to receive the attached handles (if
+// any).
+//
+// |num_bytes| and |num_handles| are optional "in-out" parameters. If non-null,
+// on return |*num_bytes| and |*num_handles| will usually indicate the number
+// of bytes and number of attached handles in the "next" message, respectively,
+// whether that message was read or not. (If null, the number of bytes/handles
+// is treated as zero.)
+//
+// If |bytes| is null, then |*num_bytes| must be zero, and similarly for
+// |handles| and |*num_handles|.
+//
+// Partial reads are NEVER done. Either a full read is done and |MOJO_RESULT_OK|
+// returned, or the read is NOT done and |MOJO_RESULT_RESOURCE_EXHAUSTED| is
+// returned (if |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| was set, the message is
+// also discarded in this case).
+//
+// Returns:
+// |MOJO_RESULT_OK| on success (i.e., a message was actually read).
+// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid.
+// |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed.
+// |MOJO_RESULT_RESOURCE_EXHAUSTED| if one of the buffers to receive the
+// message/attached handles (|bytes|/|*num_bytes| or
+// |handles|/|*num_handles|) was too small. (TODO(vtl): Reconsider this
+// error code; should distinguish this from the hitting-system-limits
+// case.)
+// |MOJO_RESULT_SHOULD_WAIT| if no message was available to be read.
+MOJO_SYSTEM_EXPORT MojoResult MojoReadMessage(
+ MojoHandle message_pipe_handle,
+ void* bytes, // Optional out.
+ uint32_t* num_bytes, // Optional in/out.
+ MojoHandle* handles, // Optional out.
+ uint32_t* num_handles, // Optional in/out.
+ MojoReadMessageFlags flags);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // MOJO_PUBLIC_C_SYSTEM_MESSAGE_PIPE_H_
diff --git a/chromium/mojo/public/c/system/system_export.h b/chromium/mojo/public/c/system/system_export.h
new file mode 100644
index 00000000000..bc3b459843f
--- /dev/null
+++ b/chromium/mojo/public/c/system/system_export.h
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_SYSTEM_EXPORT_H_
+#define MOJO_PUBLIC_C_SYSTEM_SYSTEM_EXPORT_H_
+
+#if defined(COMPONENT_BUILD) && defined(MOJO_USE_SYSTEM_IMPL)
+#if defined(WIN32)
+
+#if defined(MOJO_SYSTEM_IMPLEMENTATION)
+#define MOJO_SYSTEM_EXPORT __declspec(dllexport)
+#else
+#define MOJO_SYSTEM_EXPORT __declspec(dllimport)
+#endif
+
+#else // !defined(WIN32)
+
+#if defined(MOJO_SYSTEM_IMPLEMENTATION)
+#define MOJO_SYSTEM_EXPORT __attribute__((visibility("default")))
+#else
+#define MOJO_SYSTEM_EXPORT
+#endif
+
+#endif // defined(WIN32)
+
+#else // !defined(COMPONENT_BUILD) || !defined(MOJO_USE_SYSTEM_IMPL)
+
+#define MOJO_SYSTEM_EXPORT
+
+#endif // defined(COMPONENT_BUILD) && defined(MOJO_USE_SYSTEM_IMPL)
+
+#endif // MOJO_PUBLIC_C_SYSTEM_SYSTEM_EXPORT_H_
diff --git a/chromium/mojo/public/c/system/types.h b/chromium/mojo/public/c/system/types.h
new file mode 100644
index 00000000000..e992d110e3a
--- /dev/null
+++ b/chromium/mojo/public/c/system/types.h
@@ -0,0 +1,176 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains types and constants/macros common to different Mojo system
+// APIs.
+//
+// Note: This header should be compilable as C.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_TYPES_H_
+#define MOJO_PUBLIC_C_SYSTEM_TYPES_H_
+
+#include <stdint.h>
+
+#include "mojo/public/c/system/macros.h"
+
+// TODO(vtl): Notes: Use of undefined flags will lead to undefined behavior
+// (typically they'll be ignored), not necessarily an error.
+
+// |MojoTimeTicks|: Used to specify time ticks. Value is in microseconds.
+
+typedef int64_t MojoTimeTicks;
+
+// |MojoHandle|: Handles to Mojo objects.
+// |MOJO_HANDLE_INVALID| - A value that is never a valid handle.
+
+typedef uint32_t MojoHandle;
+
+#ifdef __cplusplus
+const MojoHandle MOJO_HANDLE_INVALID = 0;
+#else
+#define MOJO_HANDLE_INVALID ((MojoHandle) 0)
+#endif
+
+// |MojoResult|: Result codes for Mojo operations. Non-negative values are
+// success codes; negative values are error/failure codes.
+// |MOJO_RESULT_OK| - Not an error; returned on success. Note that positive
+// |MojoResult|s may also be used to indicate success.
+// |MOJO_RESULT_CANCELLED| - Operation was cancelled, typically by the caller.
+// |MOJO_RESULT_UNKNOWN| - Unknown error (e.g., if not enough information is
+// available for a more specific error).
+// |MOJO_RESULT_INVALID_ARGUMENT| - Caller specified an invalid argument. This
+// differs from |MOJO_RESULT_FAILED_PRECONDITION| in that the former
+// indicates arguments that are invalid regardless of the state of the
+// system.
+// |MOJO_RESULT_DEADLINE_EXCEEDED| - Deadline expired before the operation
+// could complete.
+// |MOJO_RESULT_NOT_FOUND| - Some requested entity was not found (i.e., does
+// not exist).
+// |MOJO_RESULT_ALREADY_EXISTS| - Some entity or condition that we attempted
+// to create already exists.
+// |MOJO_RESULT_PERMISSION_DENIED| - The caller does not have permission to
+// for the operation (use |MOJO_RESULT_RESOURCE_EXHAUSTED| for rejections
+// caused by exhausting some resource instead).
+// |MOJO_RESULT_RESOURCE_EXHAUSTED| - Some resource required for the call
+// (possibly some quota) has been exhausted.
+// |MOJO_RESULT_FAILED_PRECONDITION| - The system is not in a state required
+// for the operation (use this if the caller must do something to rectify
+// the state before retrying).
+// |MOJO_RESULT_ABORTED| - The operation was aborted by the system, possibly
+// due to a concurrency issue (use this if the caller may retry at a
+// higher level).
+// |MOJO_RESULT_OUT_OF_RANGE| - The operation was attempted past the valid
+// range. Unlike |MOJO_RESULT_INVALID_ARGUMENT|, this indicates that the
+// operation may be/become valid depending on the system state. (This
+// error is similar to |MOJO_RESULT_FAILED_PRECONDITION|, but is more
+// specific.)
+// |MOJO_RESULT_UNIMPLEMENTED| - The operation is not implemented, supported,
+// or enabled.
+// |MOJO_RESULT_INTERNAL| - Internal error: this should never happen and
+// indicates that some invariant expected by the system has been broken.
+// |MOJO_RESULT_UNAVAILABLE| - The operation is (temporarily) currently
+// unavailable. The caller may simply retry the operation (possibly with a
+// backoff).
+// |MOJO_RESULT_DATA_LOSS| - Unrecoverable data loss or corruption.
+// |MOJO_RESULT_BUSY| - One of the resources involved is currently being used
+// (possibly on another thread) in a way that prevents the current
+// operation from proceeding, e.g., if the other operation may result in
+// the resource being invalidated.
+// |MOJO_RESULT_SHOULD_WAIT| - The request cannot currently be completed
+// (e.g., if the data requested is not yet available). The caller should
+// wait for it to be feasible using |MojoWait()| or |MojoWaitMany()|.
+//
+// Note that positive values are also available as success codes.
+//
+// The codes from |MOJO_RESULT_OK| to |MOJO_RESULT_DATA_LOSS| come from
+// Google3's canonical error codes.
+//
+// TODO(vtl): Add a |MOJO_RESULT_UNSATISFIABLE|?
+
+typedef int32_t MojoResult;
+
+#ifdef __cplusplus
+const MojoResult MOJO_RESULT_OK = 0;
+const MojoResult MOJO_RESULT_CANCELLED = -1;
+const MojoResult MOJO_RESULT_UNKNOWN = -2;
+const MojoResult MOJO_RESULT_INVALID_ARGUMENT = -3;
+const MojoResult MOJO_RESULT_DEADLINE_EXCEEDED = -4;
+const MojoResult MOJO_RESULT_NOT_FOUND = -5;
+const MojoResult MOJO_RESULT_ALREADY_EXISTS = -6;
+const MojoResult MOJO_RESULT_PERMISSION_DENIED = -7;
+const MojoResult MOJO_RESULT_RESOURCE_EXHAUSTED = -8;
+const MojoResult MOJO_RESULT_FAILED_PRECONDITION = -9;
+const MojoResult MOJO_RESULT_ABORTED = -10;
+const MojoResult MOJO_RESULT_OUT_OF_RANGE = -11;
+const MojoResult MOJO_RESULT_UNIMPLEMENTED = -12;
+const MojoResult MOJO_RESULT_INTERNAL = -13;
+const MojoResult MOJO_RESULT_UNAVAILABLE = -14;
+const MojoResult MOJO_RESULT_DATA_LOSS = -15;
+const MojoResult MOJO_RESULT_BUSY = -16;
+const MojoResult MOJO_RESULT_SHOULD_WAIT = -17;
+#else
+#define MOJO_RESULT_OK ((MojoResult) 0)
+#define MOJO_RESULT_CANCELLED ((MojoResult) -1)
+#define MOJO_RESULT_UNKNOWN ((MojoResult) -2)
+#define MOJO_RESULT_INVALID_ARGUMENT ((MojoResult) -3)
+#define MOJO_RESULT_DEADLINE_EXCEEDED ((MojoResult) -4)
+#define MOJO_RESULT_NOT_FOUND ((MojoResult) -5)
+#define MOJO_RESULT_ALREADY_EXISTS ((MojoResult) -6)
+#define MOJO_RESULT_PERMISSION_DENIED ((MojoResult) -7)
+#define MOJO_RESULT_RESOURCE_EXHAUSTED ((MojoResult) -8)
+#define MOJO_RESULT_FAILED_PRECONDITION ((MojoResult) -9)
+#define MOJO_RESULT_ABORTED ((MojoResult) -10)
+#define MOJO_RESULT_OUT_OF_RANGE ((MojoResult) -11)
+#define MOJO_RESULT_UNIMPLEMENTED ((MojoResult) -12)
+#define MOJO_RESULT_INTERNAL ((MojoResult) -13)
+#define MOJO_RESULT_UNAVAILABLE ((MojoResult) -14)
+#define MOJO_RESULT_DATA_LOSS ((MojoResult) -15)
+#define MOJO_RESULT_BUSY ((MojoResult) -16)
+#define MOJO_RESULT_SHOULD_WAIT ((MojoResult) -17)
+#endif
+
+// |MojoDeadline|: Used to specify deadlines (timeouts), in microseconds (except
+// for |MOJO_DEADLINE_INDEFINITE|).
+// |MOJO_DEADLINE_INDEFINITE| - Used to indicate "forever".
+
+typedef uint64_t MojoDeadline;
+
+#ifdef __cplusplus
+const MojoDeadline MOJO_DEADLINE_INDEFINITE = static_cast<MojoDeadline>(-1);
+#else
+#define MOJO_DEADLINE_INDEFINITE ((MojoDeadline) -1)
+#endif
+
+// |MojoHandleSignals|: Used to specify signals that can be waited on for a
+// handle (and which can be triggered), e.g., the ability to read or write to
+// the handle.
+// |MOJO_HANDLE_SIGNAL_NONE| - No flags. |MojoWait()|, etc. will return
+// |MOJO_RESULT_FAILED_PRECONDITION| if you attempt to wait on this.
+// |MOJO_HANDLE_SIGNAL_READABLE| - Can read (e.g., a message) from the handle.
+// |MOJO_HANDLE_SIGNAL_WRITABLE| - Can write (e.g., a message) to the handle.
+
+typedef uint32_t MojoHandleSignals;
+
+#ifdef __cplusplus
+const MojoHandleSignals MOJO_HANDLE_SIGNAL_NONE = 0;
+const MojoHandleSignals MOJO_HANDLE_SIGNAL_READABLE = 1 << 0;
+const MojoHandleSignals MOJO_HANDLE_SIGNAL_WRITABLE = 1 << 1;
+#else
+#define MOJO_HANDLE_SIGNAL_NONE ((MojoHandleSignals) 0)
+#define MOJO_HANDLE_SIGNAL_READABLE ((MojoHandleSignals) 1 << 0)
+#define MOJO_HANDLE_SIGNAL_WRITABLE ((MojoHandleSignals) 1 << 1)
+#endif
+
+// TODO(vtl): Add out parameters with this to MojoWait/MojoWaitMany.
+// Note: This struct is not extensible (and only has 32-bit quantities), so it's
+// 32-bit-aligned.
+MOJO_COMPILE_ASSERT(MOJO_ALIGNOF(int32_t) == 4, int32_t_has_weird_alignment);
+struct MOJO_ALIGNAS(4) MojoHandleSignalsState {
+ MojoHandleSignals satisfied_signals;
+ MojoHandleSignals satisfiable_signals;
+};
+MOJO_COMPILE_ASSERT(sizeof(MojoHandleSignalsState) == 8,
+ MojoHandleSignalsState_has_wrong_size);
+
+#endif // MOJO_PUBLIC_C_SYSTEM_TYPES_H_
diff --git a/chromium/mojo/public/c/test_support/test_support.h b/chromium/mojo/public/c/test_support/test_support.h
new file mode 100644
index 00000000000..2b686b272eb
--- /dev/null
+++ b/chromium/mojo/public/c/test_support/test_support.h
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_H_
+#define MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_H_
+
+// Note: This header should be compilable as C.
+
+#include <stdio.h>
+
+#include "mojo/public/c/test_support/test_support_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MOJO_TEST_SUPPORT_EXPORT void MojoTestSupportLogPerfResult(
+ const char* test_name,
+ double value,
+ const char* units);
+
+// Opens a "/"-delimited file path relative to the source root.
+MOJO_TEST_SUPPORT_EXPORT FILE* MojoTestSupportOpenSourceRootRelativeFile(
+ const char* source_root_relative_path);
+
+// Enumerates a "/"-delimited directory path relative to the source root.
+// Returns only regular files. The return value is a heap-allocated array of
+// heap-allocated strings. Each must be free'd separately.
+//
+// The return value is built like so:
+//
+// char** rv = (char**) calloc(N + 1, sizeof(char*));
+// rv[0] = strdup("a");
+// rv[1] = strdup("b");
+// rv[2] = strdup("c");
+// ...
+// rv[N] = NULL;
+//
+MOJO_TEST_SUPPORT_EXPORT
+char** MojoTestSupportEnumerateSourceRootRelativeDirectory(
+ const char* source_root_relative_path);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_H_
diff --git a/chromium/mojo/public/c/test_support/test_support_export.h b/chromium/mojo/public/c/test_support/test_support_export.h
new file mode 100644
index 00000000000..e22a9e30144
--- /dev/null
+++ b/chromium/mojo/public/c/test_support/test_support_export.h
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_EXPORT_H_
+#define MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_EXPORT_H_
+
+#if defined(WIN32)
+
+#if defined(MOJO_TEST_SUPPORT_IMPLEMENTATION)
+#define MOJO_TEST_SUPPORT_EXPORT __declspec(dllexport)
+#else
+#define MOJO_TEST_SUPPORT_EXPORT __declspec(dllimport)
+#endif
+
+#else // !defined(WIN32)
+
+#if defined(MOJO_TEST_SUPPORT_IMPLEMENTATION)
+#define MOJO_TEST_SUPPORT_EXPORT __attribute__((visibility("default")))
+#else
+#define MOJO_TEST_SUPPORT_EXPORT
+#endif
+
+#endif // defined(WIN32)
+
+#endif // MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_EXPORT_H_
diff --git a/chromium/mojo/public/cpp/DEPS b/chromium/mojo/public/cpp/DEPS
new file mode 100644
index 00000000000..74acd7c7ed3
--- /dev/null
+++ b/chromium/mojo/public/cpp/DEPS
@@ -0,0 +1,18 @@
+include_rules = [
+ # Require explicit dependencies in each directory.
+ "-mojo/public",
+ # But everyone can depend on the C and C++ system headers.
+ "+mojo/public/c/system",
+ "+mojo/public/cpp/system",
+ # Ditto for the C environment headers (but not the C++ environment, since it
+ # has dependencies of its own).
+ "+mojo/public/c/environment",
+]
+
+specific_include_rules = {
+ r".*_(unit|perf)test\.cc": [
+ "+testing",
+ "+mojo/public/cpp/test_support",
+ "+mojo/public/cpp/utility",
+ ],
+}
diff --git a/chromium/mojo/public/cpp/README.md b/chromium/mojo/public/cpp/README.md
new file mode 100644
index 00000000000..8f03d984b9a
--- /dev/null
+++ b/chromium/mojo/public/cpp/README.md
@@ -0,0 +1,71 @@
+Mojo Public C++ API
+===================
+
+This directory contains C++ language bindings for the Mojo Public API.
+
+A number of subdirectories provide wrappers for the lower-level C APIs (in
+subdirectories of the same name, under mojo/public/c/). Typically, these
+wrappers provide increased convenience and/or type-safety.
+
+Other subdirectories provide support (static) libraries of various sorts. In
+this case, the organization is to have the public interface for the library in
+defined in header files in the subdirectory itself and the implementation of the
+library at a lower level, under a lib (sub)subdirectory. A developer should be
+able to substitute their own implementation of any such support library, and
+expect other support libraries, which may depend on that library, to work
+properly.
+
+Bindings
+--------
+
+The bindings/ subdirectory contains a support (static) library needed by the
+code generated by the bindings generator tool (in mojo/public/tools/bindings/),
+which translates Mojo IDL (.mojom) files into idiomatic C++ (among other
+languages).
+
+This library depends on the Environment library.
+
+Environment
+-----------
+
+The environment/ subdirectory contains a support (static) library that
+represents shared state needed to support the Bindings and GLES2 libraries.
+
+This library depends on the Utility library.
+
+
+GLES2
+-----
+
+The gles2/ subdirectory contains C++ wrappers (and some additional helpers) of
+the API defined in mojo/public/c/gles2/ (which provides access to GLES2).
+
+These wrappers depend on the Environment library.
+
+Shell
+-----
+
+The shell/ subdirectory contains a support (static) library that aids in writing
+Mojo applications and interacting with the Shell service.
+
+System
+------
+
+The system/ subdirectory contains C++ wrappers (and some additional helpers) of
+the API defined in mojo/public/c/system/, which defines the basic, "core" API,
+especially used to communicate with Mojo services.
+
+Test Support
+------------
+
+The test_support/ subdirectory contains C++ wrappers of the test-only API
+defined in mojo/public/c/test_support/. It is not meant for general use by Mojo
+applications.
+
+Utility
+-------
+
+The utility/ subdirectory contains a support (static) library that provides
+various basic functionality. Most notably, it provides an implementation of a
+RunLoop based on MojoWaitMany() that applications may use as the basis for
+asynchronous message processing.
diff --git a/chromium/mojo/public/cpp/application/DEPS b/chromium/mojo/public/cpp/application/DEPS
new file mode 100644
index 00000000000..e808b79707e
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/DEPS
@@ -0,0 +1,14 @@
+include_rules = [
+ "+mojo/public/cpp/bindings",
+ "+mojo/public/interfaces/service_provider",
+]
+
+specific_include_rules = {
+ "mojo_main_chromium.cc": [
+ "+base",
+ "+mojo/public/cpp"
+ ],
+ "mojo_main_standalone.cc": [
+ "+mojo/public/cpp"
+ ],
+}
diff --git a/chromium/mojo/public/cpp/application/application.h b/chromium/mojo/public/cpp/application/application.h
new file mode 100644
index 00000000000..da7a0ed7c61
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/application.h
@@ -0,0 +1,121 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_APPLICATION_APPLICATION_H_
+#define MOJO_PUBLIC_APPLICATION_APPLICATION_H_
+#include <vector>
+
+#include "mojo/public/cpp/application/connect.h"
+#include "mojo/public/cpp/application/lib/service_connector.h"
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
+
+#if defined(WIN32)
+#if !defined(CDECL)
+#define CDECL __cdecl
+#endif
+#define APPLICATION_EXPORT __declspec(dllexport)
+#else
+#define CDECL
+#define APPLICATION_EXPORT __attribute__((visibility("default")))
+#endif
+
+// DSOs can either implement MojoMain directly or include
+// mojo_main_{standalone|chromium}.cc in their project and implement
+// Application::Create();
+// TODO(davemoore): Establish this as part of our SDK for third party mojo
+// application writers.
+extern "C" APPLICATION_EXPORT MojoResult CDECL MojoMain(
+ MojoHandle service_provider_handle);
+
+namespace mojo {
+
+// Utility class for creating ServiceProviders that vend service instances.
+// To use define a class that implements your specific server api, e.g. FooImpl
+// to implement a service named Foo.
+// That class must subclass an InterfaceImpl specialization.
+//
+// If there is context that is to be shared amongst all instances, define a
+// constructor with that class as its only argument, otherwise define an empty
+// constructor.
+//
+// class FooImpl : public InterfaceImpl<Foo> {
+// public:
+// FooImpl() {}
+// };
+//
+// or
+//
+// class BarImpl : public InterfaceImpl<Bar> {
+// public:
+// // context will remain valid for the lifetime of BarImpl.
+// BarImpl(BarContext* context) : context_(context) {}
+// private:
+// BarContext* context;
+// };
+//
+// Create an Application instance that collects any service implementations.
+//
+// Application app(service_provider_handle);
+// app.AddService<FooImpl>();
+//
+// BarContext context;
+// app.AddService<BarImpl>(&context);
+//
+//
+class Application {
+ public:
+ Application();
+ explicit Application(ScopedMessagePipeHandle service_provider_handle);
+ explicit Application(MojoHandle service_provider_handle);
+ virtual ~Application();
+
+ // Override this method to control what urls are allowed to connect to a
+ // service.
+ virtual bool AllowIncomingConnection(const mojo::String& service_name,
+ const mojo::String& requestor_url);
+
+ template <typename Impl, typename Context>
+ void AddService(Context* context) {
+ service_registry_.AddServiceConnector(
+ new internal::ServiceConnector<Impl, Context>(Impl::Name_, context));
+ }
+
+ template <typename Impl>
+ void AddService() {
+ service_registry_.AddServiceConnector(
+ new internal::ServiceConnector<Impl, void>(Impl::Name_, NULL));
+ }
+
+ template <typename Interface>
+ void ConnectTo(const std::string& url, InterfacePtr<Interface>* ptr) {
+ mojo::ConnectToService(service_provider(), url, ptr);
+ }
+
+ ServiceProvider* service_provider() {
+ return service_registry_.remote_service_provider();
+ }
+
+ void BindServiceProvider(ScopedMessagePipeHandle service_provider_handle);
+
+ protected:
+ // Override this to do any necessary initialization. There's no need to call
+ // Application's implementation.
+ // The service_provider will be bound to its pipe before this is called.
+ virtual void Initialize();
+
+ private:
+ friend MojoResult (::MojoMain)(MojoHandle);
+
+ // Implement this method to create the specific subclass of Application.
+ static Application* Create();
+
+ internal::ServiceRegistry service_registry_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Application);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_APPLICATION_APPLICATION_H_
diff --git a/chromium/mojo/public/cpp/application/connect.h b/chromium/mojo/public/cpp/application/connect.h
new file mode 100644
index 00000000000..e4ba641e2ed
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/connect.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_APPLICATION_CONNECT_H_
+#define MOJO_PUBLIC_CPP_APPLICATION_CONNECT_H_
+
+#include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
+
+namespace mojo {
+
+template <typename Interface>
+inline void ConnectToService(ServiceProvider* service_provider,
+ const std::string& url,
+ InterfacePtr<Interface>* ptr) {
+ MessagePipe pipe;
+ ptr->Bind(pipe.handle0.Pass());
+ service_provider->ConnectToService(
+ url, Interface::Name_, pipe.handle1.Pass(), std::string());
+}
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_APPLICATION_CONNECT_H_
diff --git a/chromium/mojo/public/cpp/application/lib/application.cc b/chromium/mojo/public/cpp/application/lib/application.cc
new file mode 100644
index 00000000000..78f5a8bbd0e
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/lib/application.cc
@@ -0,0 +1,34 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/application/application.h"
+
+namespace mojo {
+
+Application::Application() : service_registry_(this) {}
+
+Application::Application(ScopedMessagePipeHandle service_provider_handle)
+ : service_registry_(this, service_provider_handle.Pass()) {}
+
+Application::Application(MojoHandle service_provider_handle)
+ : service_registry_(
+ this,
+ mojo::MakeScopedHandle(
+ MessagePipeHandle(service_provider_handle)).Pass()) {}
+
+Application::~Application() {}
+
+bool Application::AllowIncomingConnection(const mojo::String& service_name,
+ const mojo::String& requestor_url) {
+ return true;
+}
+
+void Application::BindServiceProvider(
+ ScopedMessagePipeHandle service_provider_handle) {
+ service_registry_.BindRemoteServiceProvider(service_provider_handle.Pass());
+}
+
+void Application::Initialize() {}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/application/lib/mojo_main_chromium.cc b/chromium/mojo/public/cpp/application/lib/mojo_main_chromium.cc
new file mode 100644
index 00000000000..cda7cd02d18
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/lib/mojo_main_chromium.cc
@@ -0,0 +1,23 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
+#include "mojo/public/cpp/application/application.h"
+
+extern "C" APPLICATION_EXPORT MojoResult CDECL MojoMain(
+ MojoHandle service_provider_handle) {
+ base::CommandLine::Init(0, NULL);
+ base::AtExitManager at_exit;
+ base::MessageLoop loop;
+
+ scoped_ptr<mojo::Application> app(mojo::Application::Create());
+ app->BindServiceProvider(
+ mojo::MakeScopedHandle(mojo::MessagePipeHandle(service_provider_handle)));
+ app->Initialize();
+ loop.Run();
+
+ return MOJO_RESULT_OK;
+}
diff --git a/chromium/mojo/public/cpp/application/lib/mojo_main_standalone.cc b/chromium/mojo/public/cpp/application/lib/mojo_main_standalone.cc
new file mode 100644
index 00000000000..05825aa3319
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/lib/mojo_main_standalone.cc
@@ -0,0 +1,22 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/application/application.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+
+extern "C" APPLICATION_EXPORT MojoResult CDECL MojoMain(
+ MojoHandle service_provider_handle) {
+ mojo::Environment env;
+ mojo::RunLoop loop;
+
+ mojo::Application* app = mojo::Application::Create();
+ app->BindServiceProvider(
+ mojo::MakeScopedHandle(mojo::MessagePipeHandle(service_provider_handle)));
+ app->Initialize();
+ loop.Run();
+ delete app;
+
+ return MOJO_RESULT_OK;
+}
diff --git a/chromium/mojo/public/cpp/application/lib/service_connector.cc b/chromium/mojo/public/cpp/application/lib/service_connector.cc
new file mode 100644
index 00000000000..5cc4421b7aa
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/lib/service_connector.cc
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/application/lib/service_connector.h"
+
+namespace mojo {
+namespace internal {
+
+ServiceConnectorBase::ServiceConnectorBase(const std::string& name)
+ : name_(name),
+ registry_(NULL) {
+}
+
+ServiceConnectorBase::~ServiceConnectorBase() {}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/application/lib/service_connector.h b/chromium/mojo/public/cpp/application/lib/service_connector.h
new file mode 100644
index 00000000000..30786adb55d
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/lib/service_connector.h
@@ -0,0 +1,133 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_
+#define MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_
+
+#include <assert.h>
+
+#include <vector>
+
+#include "mojo/public/cpp/application/lib/service_registry.h"
+#include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
+
+namespace mojo {
+namespace internal {
+
+template <class ServiceImpl, typename Context>
+class ServiceConnector;
+
+// Specialization of ServiceConnection.
+// ServiceImpl: Subclass of InterfaceImpl<...>.
+// Context: Type of shared context.
+template <class ServiceImpl, typename Context>
+class ServiceConnection : public ServiceImpl {
+ public:
+ ServiceConnection() : ServiceImpl() {}
+ ServiceConnection(Context* context) : ServiceImpl(context) {}
+
+ virtual void OnConnectionError() MOJO_OVERRIDE {
+ service_connector_->RemoveConnection(static_cast<ServiceImpl*>(this));
+ ServiceImpl::OnConnectionError();
+ }
+
+private:
+ friend class ServiceConnector<ServiceImpl, Context>;
+
+ // Called shortly after this class is instantiated.
+ void set_service_connector(
+ ServiceConnector<ServiceImpl, Context>* connector) {
+ service_connector_ = connector;
+ }
+
+ ServiceConnector<ServiceImpl, Context>* service_connector_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnection);
+};
+
+template <typename ServiceImpl, typename Context>
+struct ServiceConstructor {
+ static ServiceConnection<ServiceImpl, Context>* New(Context* context) {
+ return new ServiceConnection<ServiceImpl, Context>(context);
+ }
+};
+
+template <typename ServiceImpl>
+struct ServiceConstructor<ServiceImpl, void> {
+ public:
+ static ServiceConnection<ServiceImpl, void>* New(void* context) {
+ return new ServiceConnection<ServiceImpl, void>();
+ }
+};
+
+class ServiceConnectorBase {
+ public:
+ ServiceConnectorBase(const std::string& name);
+ virtual ~ServiceConnectorBase();
+ virtual void ConnectToService(const std::string& url,
+ const std::string& name,
+ ScopedMessagePipeHandle client_handle) = 0;
+ std::string name() const { return name_; }
+ void set_registry(ServiceRegistry* registry) { registry_ = registry; }
+
+ protected:
+ std::string name_;
+ ServiceRegistry* registry_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnectorBase);
+};
+
+template <class ServiceImpl, typename Context=void>
+class ServiceConnector : public internal::ServiceConnectorBase {
+ public:
+ ServiceConnector(const std::string& name, Context* context = NULL)
+ : ServiceConnectorBase(name), context_(context) {}
+
+ virtual ~ServiceConnector() {
+ ConnectionList doomed;
+ doomed.swap(connections_);
+ for (typename ConnectionList::iterator it = doomed.begin();
+ it != doomed.end(); ++it) {
+ delete *it;
+ }
+ assert(connections_.empty()); // No one should have added more!
+ }
+
+ virtual void ConnectToService(const std::string& url,
+ const std::string& name,
+ ScopedMessagePipeHandle handle) MOJO_OVERRIDE {
+ ServiceConnection<ServiceImpl, Context>* impl =
+ ServiceConstructor<ServiceImpl, Context>::New(context_);
+ impl->set_service_connector(this);
+ BindToPipe(impl, handle.Pass());
+
+ connections_.push_back(impl);
+ }
+
+ void RemoveConnection(ServiceImpl* impl) {
+ // Called from ~ServiceImpl, in response to a connection error.
+ for (typename ConnectionList::iterator it = connections_.begin();
+ it != connections_.end(); ++it) {
+ if (*it == impl) {
+ delete impl;
+ connections_.erase(it);
+ return;
+ }
+ }
+ }
+
+ Context* context() const { return context_; }
+
+ private:
+ typedef std::vector<ServiceImpl*> ConnectionList;
+ ConnectionList connections_;
+ Context* context_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnector);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_
diff --git a/chromium/mojo/public/cpp/application/lib/service_registry.cc b/chromium/mojo/public/cpp/application/lib/service_registry.cc
new file mode 100644
index 00000000000..bc901dfb924
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/lib/service_registry.cc
@@ -0,0 +1,78 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/application/lib/service_registry.h"
+
+#include "mojo/public/cpp/application/application.h"
+#include "mojo/public/cpp/application/lib/service_connector.h"
+
+namespace mojo {
+namespace internal {
+
+ServiceRegistry::ServiceRegistry(Application* application)
+ : application_(application) {
+}
+
+ServiceRegistry::ServiceRegistry(
+ Application* application,
+ ScopedMessagePipeHandle service_provider_handle)
+ : application_(application) {
+ remote_service_provider_.Bind(service_provider_handle.Pass());
+ remote_service_provider_.set_client(this);
+}
+
+ServiceRegistry::~ServiceRegistry() {
+ for (NameToServiceConnectorMap::iterator i =
+ name_to_service_connector_.begin();
+ i != name_to_service_connector_.end(); ++i) {
+ delete i->second;
+ }
+ name_to_service_connector_.clear();
+}
+
+void ServiceRegistry::AddServiceConnector(
+ ServiceConnectorBase* service_connector) {
+ name_to_service_connector_[service_connector->name()] = service_connector;
+ service_connector->set_registry(this);
+}
+
+void ServiceRegistry::RemoveServiceConnector(
+ ServiceConnectorBase* service_connector) {
+ NameToServiceConnectorMap::iterator it =
+ name_to_service_connector_.find(service_connector->name());
+ assert(it != name_to_service_connector_.end());
+ delete it->second;
+ name_to_service_connector_.erase(it);
+ if (name_to_service_connector_.empty())
+ remote_service_provider_.reset();
+}
+
+void ServiceRegistry::BindRemoteServiceProvider(
+ ScopedMessagePipeHandle service_provider_handle) {
+ remote_service_provider_.Bind(service_provider_handle.Pass());
+ remote_service_provider_.set_client(this);
+}
+
+void ServiceRegistry::ConnectToService(const mojo::String& service_url,
+ const mojo::String& service_name,
+ ScopedMessagePipeHandle client_handle,
+ const mojo::String& requestor_url) {
+ if (name_to_service_connector_.find(service_name) ==
+ name_to_service_connector_.end() ||
+ !application_->AllowIncomingConnection(service_name, requestor_url)) {
+ client_handle.reset();
+ return;
+ }
+
+ internal::ServiceConnectorBase* service_connector =
+ name_to_service_connector_[service_name];
+ assert(service_connector);
+ // requestor_url is ignored because the service_connector stores the url
+ // of the requestor safely.
+ return service_connector->ConnectToService(
+ service_url, service_name, client_handle.Pass());
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/application/lib/service_registry.h b/chromium/mojo/public/cpp/application/lib/service_registry.h
new file mode 100644
index 00000000000..478cd055ef2
--- /dev/null
+++ b/chromium/mojo/public/cpp/application/lib/service_registry.h
@@ -0,0 +1,55 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_REGISTRY_H_
+#define MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_REGISTRY_H_
+
+#include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
+
+namespace mojo {
+
+class Application;
+
+namespace internal {
+
+class ServiceConnectorBase;
+
+class ServiceRegistry : public ServiceProvider {
+ public:
+ ServiceRegistry(Application* application);
+ ServiceRegistry(Application* application,
+ ScopedMessagePipeHandle service_provider_handle);
+ virtual ~ServiceRegistry();
+
+ void AddServiceConnector(ServiceConnectorBase* service_connector);
+ void RemoveServiceConnector(ServiceConnectorBase* service_connector);
+
+ ServiceProvider* remote_service_provider() {
+ return remote_service_provider_.get();
+ }
+
+ void BindRemoteServiceProvider(
+ ScopedMessagePipeHandle service_provider_handle);
+
+ // ServiceProvider method.
+ virtual void ConnectToService(const mojo::String& service_url,
+ const mojo::String& service_name,
+ ScopedMessagePipeHandle client_handle,
+ const mojo::String& requestor_url)
+ MOJO_OVERRIDE;
+
+ private:
+ Application* application_;
+ typedef std::map<std::string, ServiceConnectorBase*>
+ NameToServiceConnectorMap;
+ NameToServiceConnectorMap name_to_service_connector_;
+ ServiceProviderPtr remote_service_provider_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceRegistry);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_REGISTRY_H_
diff --git a/chromium/mojo/public/cpp/bindings/BUILD.gn b/chromium/mojo/public/cpp/bindings/BUILD.gn
new file mode 100644
index 00000000000..2cc35aa52ff
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/BUILD.gn
@@ -0,0 +1,53 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("bindings") {
+ sources = [
+ "array.h",
+ "callback.h",
+ "error_handler.h",
+ "interface_ptr.h",
+ "message.h",
+ "message_filter.h",
+ "no_interface.h",
+ "string.h",
+ "struct_ptr.h",
+ "sync_dispatcher.h",
+ "type_converter.h",
+ "lib/array_internal.cc",
+ "lib/array_internal.h",
+ "lib/array_serialization.h",
+ "lib/bindings_internal.h",
+ "lib/bindings_serialization.cc",
+ "lib/bindings_serialization.h",
+ "lib/bounds_checker.cc",
+ "lib/bounds_checker.h",
+ "lib/buffer.h",
+ "lib/callback_internal.h",
+ "lib/connector.cc",
+ "lib/connector.h",
+ "lib/filter_chain.cc",
+ "lib/filter_chain.h",
+ "lib/fixed_buffer.cc",
+ "lib/fixed_buffer.h",
+ "lib/message.cc",
+ "lib/message_builder.cc",
+ "lib/message_builder.h",
+ "lib/message_filter.cc",
+ "lib/message_internal.h",
+ "lib/message_queue.cc",
+ "lib/message_queue.h",
+ "lib/no_interface.cc",
+ "lib/router.cc",
+ "lib/router.h",
+ "lib/shared_data.h",
+ "lib/shared_ptr.h",
+ "lib/string_serialization.cc",
+ "lib/string_serialization.h",
+ "lib/sync_dispatcher.cc",
+ "lib/template_util.h",
+ "lib/validation_errors.cc",
+ "lib/validation_errors.h",
+ ]
+}
diff --git a/chromium/mojo/public/cpp/bindings/DEPS b/chromium/mojo/public/cpp/bindings/DEPS
new file mode 100644
index 00000000000..2a0496e9d9c
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+mojo/public/cpp/environment",
+]
diff --git a/chromium/mojo/public/cpp/bindings/array.h b/chromium/mojo/public/cpp/bindings/array.h
new file mode 100644
index 00000000000..daf7125bb3c
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/array.h
@@ -0,0 +1,143 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_
+
+#include <string.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/template_util.h"
+#include "mojo/public/cpp/bindings/type_converter.h"
+
+namespace mojo {
+
+// Provides read-only access to array data.
+template <typename T>
+class Array {
+ MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(Array, RValue)
+ public:
+ typedef internal::ArrayTraits<T, internal::IsMoveOnlyType<T>::value>
+ Traits;
+ typedef typename Traits::ConstRefType ConstRefType;
+ typedef typename Traits::RefType RefType;
+ typedef typename Traits::StorageType StorageType;
+ typedef typename Traits::ForwardType ForwardType;
+
+ typedef internal::Array_Data<typename internal::WrapperTraits<T>::DataType>
+ Data_;
+
+ Array() : is_null_(true) {}
+ explicit Array(size_t size) : vec_(size), is_null_(false) {
+ Traits::Initialize(&vec_);
+ }
+ ~Array() { Traits::Finalize(&vec_); }
+
+ Array(RValue other) : is_null_(true) { Take(other.object); }
+ Array& operator=(RValue other) {
+ Take(other.object);
+ return *this;
+ }
+
+ static Array New(size_t size) {
+ return Array(size).Pass();
+ }
+
+ template <typename U>
+ static Array From(const U& other) {
+ return TypeConverter<Array, U>::ConvertFrom(other);
+ }
+
+ template <typename U>
+ U To() const {
+ return TypeConverter<Array, U>::ConvertTo(*this);
+ }
+
+ void reset() {
+ if (!vec_.empty()) {
+ Traits::Finalize(&vec_);
+ vec_.clear();
+ }
+ is_null_ = true;
+ }
+
+ bool is_null() const { return is_null_; }
+
+ size_t size() const { return vec_.size(); }
+
+ ConstRefType at(size_t offset) const { return Traits::at(&vec_, offset); }
+ ConstRefType operator[](size_t offset) const { return at(offset); }
+
+ RefType at(size_t offset) { return Traits::at(&vec_, offset); }
+ RefType operator[](size_t offset) { return at(offset); }
+
+ void push_back(ForwardType value) {
+ is_null_ = false;
+ Traits::PushBack(&vec_, value);
+ }
+
+ void resize(size_t size) {
+ is_null_ = false;
+ Traits::Resize(&vec_, size);
+ }
+
+ const std::vector<StorageType>& storage() const {
+ return vec_;
+ }
+ operator const std::vector<StorageType>&() const {
+ return vec_;
+ }
+
+ void Swap(Array* other) {
+ std::swap(is_null_, other->is_null_);
+ vec_.swap(other->vec_);
+ }
+ void Swap(std::vector<StorageType>* other) {
+ is_null_ = false;
+ vec_.swap(*other);
+ }
+
+ private:
+ typedef std::vector<StorageType> Array::*Testable;
+
+ public:
+ operator Testable() const { return is_null_ ? 0 : &Array::vec_; }
+
+ private:
+ void Take(Array* other) {
+ reset();
+ Swap(other);
+ }
+
+ std::vector<StorageType> vec_;
+ bool is_null_;
+};
+
+template <typename T, typename E>
+class TypeConverter<Array<T>, std::vector<E> > {
+ public:
+ static Array<T> ConvertFrom(const std::vector<E>& input) {
+ Array<T> result(input.size());
+ for (size_t i = 0; i < input.size(); ++i)
+ result[i] = TypeConverter<T, E>::ConvertFrom(input[i]);
+ return result.Pass();
+ }
+ static std::vector<E> ConvertTo(const Array<T>& input) {
+ std::vector<E> result;
+ if (!input.is_null()) {
+ result.resize(input.size());
+ for (size_t i = 0; i < input.size(); ++i)
+ result[i] = TypeConverter<T, E>::ConvertTo(input[i]);
+ }
+ return result;
+ }
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_
diff --git a/chromium/mojo/public/cpp/bindings/callback.h b/chromium/mojo/public/cpp/bindings/callback.h
new file mode 100644
index 00000000000..d8ff4718232
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/callback.h
@@ -0,0 +1,462 @@
+// This file was GENERATED by command:
+// pump.py callback.h.pump
+// DO NOT EDIT BY HAND!!!
+
+
+
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
+
+#include "mojo/public/cpp/bindings/lib/callback_internal.h"
+#include "mojo/public/cpp/bindings/lib/shared_ptr.h"
+#include "mojo/public/cpp/bindings/lib/template_util.h"
+
+namespace mojo {
+
+template <typename Sig>
+class Callback;
+
+template <>
+class Callback<void()> {
+ public:
+ struct Runnable {
+ virtual ~Runnable() {}
+ virtual void Run() const = 0;
+ };
+
+ Callback() {}
+
+ // The Callback assumes ownership of |runnable|.
+ explicit Callback(Runnable* runnable) : sink_(runnable) {}
+
+ // Any class that is copy-constructable and has a compatible Run method may
+ // be adapted to a Callback using this constructor.
+ template <typename Sink>
+ Callback(const Sink& sink) : sink_(new Adapter<Sink>(sink)) {}
+
+ void Run() const {
+ if (sink_.get())
+ sink_->Run();
+ }
+
+ private:
+ template <typename Sink>
+ struct Adapter : public Runnable {
+ explicit Adapter(const Sink& sink) : sink(sink) {}
+ virtual void Run() const MOJO_OVERRIDE {
+ sink.Run();
+ }
+ Sink sink;
+ };
+
+ internal::SharedPtr<Runnable> sink_;
+};
+
+template <typename A1>
+class Callback<void(A1)> {
+ public:
+ struct Runnable {
+ virtual ~Runnable() {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1) const = 0;
+ };
+
+ Callback() {}
+
+ // The Callback assumes ownership of |runnable|.
+ explicit Callback(Runnable* runnable) : sink_(runnable) {}
+
+ // Any class that is copy-constructable and has a compatible Run method may
+ // be adapted to a Callback using this constructor.
+ template <typename Sink>
+ Callback(const Sink& sink) : sink_(new Adapter<Sink>(sink)) {}
+
+ void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1) const {
+ if (sink_.get())
+ sink_->Run(
+ internal::Forward(a1));
+ }
+
+ private:
+ template <typename Sink>
+ struct Adapter : public Runnable {
+ explicit Adapter(const Sink& sink) : sink(sink) {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1) const
+ MOJO_OVERRIDE {
+ sink.Run(
+ internal::Forward(a1));
+ }
+ Sink sink;
+ };
+
+ internal::SharedPtr<Runnable> sink_;
+};
+
+template <typename A1, typename A2>
+class Callback<void(A1, A2)> {
+ public:
+ struct Runnable {
+ virtual ~Runnable() {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2) const = 0;
+ };
+
+ Callback() {}
+
+ // The Callback assumes ownership of |runnable|.
+ explicit Callback(Runnable* runnable) : sink_(runnable) {}
+
+ // Any class that is copy-constructable and has a compatible Run method may
+ // be adapted to a Callback using this constructor.
+ template <typename Sink>
+ Callback(const Sink& sink) : sink_(new Adapter<Sink>(sink)) {}
+
+ void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2) const {
+ if (sink_.get())
+ sink_->Run(
+ internal::Forward(a1),
+ internal::Forward(a2));
+ }
+
+ private:
+ template <typename Sink>
+ struct Adapter : public Runnable {
+ explicit Adapter(const Sink& sink) : sink(sink) {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2) const
+ MOJO_OVERRIDE {
+ sink.Run(
+ internal::Forward(a1),
+ internal::Forward(a2));
+ }
+ Sink sink;
+ };
+
+ internal::SharedPtr<Runnable> sink_;
+};
+
+template <typename A1, typename A2, typename A3>
+class Callback<void(A1, A2, A3)> {
+ public:
+ struct Runnable {
+ virtual ~Runnable() {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3) const = 0;
+ };
+
+ Callback() {}
+
+ // The Callback assumes ownership of |runnable|.
+ explicit Callback(Runnable* runnable) : sink_(runnable) {}
+
+ // Any class that is copy-constructable and has a compatible Run method may
+ // be adapted to a Callback using this constructor.
+ template <typename Sink>
+ Callback(const Sink& sink) : sink_(new Adapter<Sink>(sink)) {}
+
+ void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3) const {
+ if (sink_.get())
+ sink_->Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3));
+ }
+
+ private:
+ template <typename Sink>
+ struct Adapter : public Runnable {
+ explicit Adapter(const Sink& sink) : sink(sink) {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3) const
+ MOJO_OVERRIDE {
+ sink.Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3));
+ }
+ Sink sink;
+ };
+
+ internal::SharedPtr<Runnable> sink_;
+};
+
+template <typename A1, typename A2, typename A3, typename A4>
+class Callback<void(A1, A2, A3, A4)> {
+ public:
+ struct Runnable {
+ virtual ~Runnable() {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4) const = 0;
+ };
+
+ Callback() {}
+
+ // The Callback assumes ownership of |runnable|.
+ explicit Callback(Runnable* runnable) : sink_(runnable) {}
+
+ // Any class that is copy-constructable and has a compatible Run method may
+ // be adapted to a Callback using this constructor.
+ template <typename Sink>
+ Callback(const Sink& sink) : sink_(new Adapter<Sink>(sink)) {}
+
+ void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4) const {
+ if (sink_.get())
+ sink_->Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3),
+ internal::Forward(a4));
+ }
+
+ private:
+ template <typename Sink>
+ struct Adapter : public Runnable {
+ explicit Adapter(const Sink& sink) : sink(sink) {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4) const
+ MOJO_OVERRIDE {
+ sink.Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3),
+ internal::Forward(a4));
+ }
+ Sink sink;
+ };
+
+ internal::SharedPtr<Runnable> sink_;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5>
+class Callback<void(A1, A2, A3, A4, A5)> {
+ public:
+ struct Runnable {
+ virtual ~Runnable() {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4,
+ typename internal::Callback_ParamTraits<A5>::ForwardType a5) const = 0;
+ };
+
+ Callback() {}
+
+ // The Callback assumes ownership of |runnable|.
+ explicit Callback(Runnable* runnable) : sink_(runnable) {}
+
+ // Any class that is copy-constructable and has a compatible Run method may
+ // be adapted to a Callback using this constructor.
+ template <typename Sink>
+ Callback(const Sink& sink) : sink_(new Adapter<Sink>(sink)) {}
+
+ void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4,
+ typename internal::Callback_ParamTraits<A5>::ForwardType a5) const {
+ if (sink_.get())
+ sink_->Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3),
+ internal::Forward(a4),
+ internal::Forward(a5));
+ }
+
+ private:
+ template <typename Sink>
+ struct Adapter : public Runnable {
+ explicit Adapter(const Sink& sink) : sink(sink) {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4,
+ typename internal::Callback_ParamTraits<A5>::ForwardType a5) const
+ MOJO_OVERRIDE {
+ sink.Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3),
+ internal::Forward(a4),
+ internal::Forward(a5));
+ }
+ Sink sink;
+ };
+
+ internal::SharedPtr<Runnable> sink_;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+ typename A6>
+class Callback<void(A1, A2, A3, A4, A5, A6)> {
+ public:
+ struct Runnable {
+ virtual ~Runnable() {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4,
+ typename internal::Callback_ParamTraits<A5>::ForwardType a5,
+ typename internal::Callback_ParamTraits<A6>::ForwardType a6) const = 0;
+ };
+
+ Callback() {}
+
+ // The Callback assumes ownership of |runnable|.
+ explicit Callback(Runnable* runnable) : sink_(runnable) {}
+
+ // Any class that is copy-constructable and has a compatible Run method may
+ // be adapted to a Callback using this constructor.
+ template <typename Sink>
+ Callback(const Sink& sink) : sink_(new Adapter<Sink>(sink)) {}
+
+ void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4,
+ typename internal::Callback_ParamTraits<A5>::ForwardType a5,
+ typename internal::Callback_ParamTraits<A6>::ForwardType a6) const {
+ if (sink_.get())
+ sink_->Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3),
+ internal::Forward(a4),
+ internal::Forward(a5),
+ internal::Forward(a6));
+ }
+
+ private:
+ template <typename Sink>
+ struct Adapter : public Runnable {
+ explicit Adapter(const Sink& sink) : sink(sink) {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4,
+ typename internal::Callback_ParamTraits<A5>::ForwardType a5,
+ typename internal::Callback_ParamTraits<A6>::ForwardType a6) const
+ MOJO_OVERRIDE {
+ sink.Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3),
+ internal::Forward(a4),
+ internal::Forward(a5),
+ internal::Forward(a6));
+ }
+ Sink sink;
+ };
+
+ internal::SharedPtr<Runnable> sink_;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+ typename A6, typename A7>
+class Callback<void(A1, A2, A3, A4, A5, A6, A7)> {
+ public:
+ struct Runnable {
+ virtual ~Runnable() {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4,
+ typename internal::Callback_ParamTraits<A5>::ForwardType a5,
+ typename internal::Callback_ParamTraits<A6>::ForwardType a6,
+ typename internal::Callback_ParamTraits<A7>::ForwardType a7) const = 0;
+ };
+
+ Callback() {}
+
+ // The Callback assumes ownership of |runnable|.
+ explicit Callback(Runnable* runnable) : sink_(runnable) {}
+
+ // Any class that is copy-constructable and has a compatible Run method may
+ // be adapted to a Callback using this constructor.
+ template <typename Sink>
+ Callback(const Sink& sink) : sink_(new Adapter<Sink>(sink)) {}
+
+ void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4,
+ typename internal::Callback_ParamTraits<A5>::ForwardType a5,
+ typename internal::Callback_ParamTraits<A6>::ForwardType a6,
+ typename internal::Callback_ParamTraits<A7>::ForwardType a7) const {
+ if (sink_.get())
+ sink_->Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3),
+ internal::Forward(a4),
+ internal::Forward(a5),
+ internal::Forward(a6),
+ internal::Forward(a7));
+ }
+
+ private:
+ template <typename Sink>
+ struct Adapter : public Runnable {
+ explicit Adapter(const Sink& sink) : sink(sink) {}
+ virtual void Run(
+ typename internal::Callback_ParamTraits<A1>::ForwardType a1,
+ typename internal::Callback_ParamTraits<A2>::ForwardType a2,
+ typename internal::Callback_ParamTraits<A3>::ForwardType a3,
+ typename internal::Callback_ParamTraits<A4>::ForwardType a4,
+ typename internal::Callback_ParamTraits<A5>::ForwardType a5,
+ typename internal::Callback_ParamTraits<A6>::ForwardType a6,
+ typename internal::Callback_ParamTraits<A7>::ForwardType a7) const
+ MOJO_OVERRIDE {
+ sink.Run(
+ internal::Forward(a1),
+ internal::Forward(a2),
+ internal::Forward(a3),
+ internal::Forward(a4),
+ internal::Forward(a5),
+ internal::Forward(a6),
+ internal::Forward(a7));
+ }
+ Sink sink;
+ };
+
+ internal::SharedPtr<Runnable> sink_;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
diff --git a/chromium/mojo/public/cpp/bindings/callback.h.pump b/chromium/mojo/public/cpp/bindings/callback.h.pump
new file mode 100644
index 00000000000..a0f23d5f77e
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/callback.h.pump
@@ -0,0 +1,80 @@
+$$ This is a pump file for generating file templates. Pump is a python
+$$ script that is part of the Google Test suite of utilities. Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+$var MAX_ARITY = 7
+
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
+
+#include "mojo/public/cpp/bindings/lib/callback_internal.h"
+#include "mojo/public/cpp/bindings/lib/shared_ptr.h"
+#include "mojo/public/cpp/bindings/lib/template_util.h"
+
+namespace mojo {
+
+template <typename Sig>
+class Callback;
+
+$range ARITY 0..MAX_ARITY
+$for ARITY [[
+$range ARG 1..ARITY
+
+template <$for ARG , [[typename A$(ARG)]]>
+class Callback<void($for ARG , [[A$(ARG)]])> {
+ public:
+ struct Runnable {
+ virtual ~Runnable() {}
+ virtual void Run(
+ $for ARG ,
+ [[typename internal::Callback_ParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const = 0;
+ };
+
+ Callback() {}
+
+ // The Callback assumes ownership of |runnable|.
+ explicit Callback(Runnable* runnable) : sink_(runnable) {}
+
+ // Any class that is copy-constructable and has a compatible Run method may
+ // be adapted to a Callback using this constructor.
+ template <typename Sink>
+ Callback(const Sink& sink) : sink_(new Adapter<Sink>(sink)) {}
+
+ void Run(
+ $for ARG ,
+ [[typename internal::Callback_ParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const {
+ if (sink_.get())
+ sink_->Run(
+ $for ARG ,
+ [[internal::Forward(a$(ARG))]]);
+ }
+
+ private:
+ template <typename Sink>
+ struct Adapter : public Runnable {
+ explicit Adapter(const Sink& sink) : sink(sink) {}
+ virtual void Run(
+ $for ARG ,
+ [[typename internal::Callback_ParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const MOJO_OVERRIDE {
+ sink.Run(
+ $for ARG ,
+ [[internal::Forward(a$(ARG))]]);
+ }
+ Sink sink;
+ };
+
+ internal::SharedPtr<Runnable> sink_;
+};
+
+]] $$ for ARITY
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
diff --git a/chromium/mojo/public/cpp/bindings/error_handler.h b/chromium/mojo/public/cpp/bindings/error_handler.h
new file mode 100644
index 00000000000..8ce1af27264
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/error_handler.h
@@ -0,0 +1,19 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_ERROR_HANDLER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_ERROR_HANDLER_H_
+
+namespace mojo {
+
+// This interface is used to report connection errors.
+class ErrorHandler {
+ public:
+ virtual ~ErrorHandler() {}
+ virtual void OnConnectionError() = 0;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_ERROR_HANDLER_H_
diff --git a/chromium/mojo/public/cpp/bindings/interface_impl.h b/chromium/mojo/public/cpp/bindings/interface_impl.h
new file mode 100644
index 00000000000..8ba5e7ffa4a
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/interface_impl.h
@@ -0,0 +1,109 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_IMPL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_IMPL_H_
+
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/lib/interface_impl_internal.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+// InterfaceImpl<..> is designed to be the base class of an interface
+// implementation. It may be bound to a pipe or a proxy, see BindToPipe and
+// BindToProxy.
+template <typename Interface>
+class InterfaceImpl : public internal::InterfaceImplBase<Interface> {
+ public:
+ typedef typename Interface::Client Client;
+
+ InterfaceImpl() : internal_state_(this) {}
+ virtual ~InterfaceImpl() {}
+
+ // Returns a proxy to the client interface. This is null upon construction,
+ // and becomes non-null after OnClientConnected. NOTE: It remains non-null
+ // until this instance is deleted.
+ Client* client() { return internal_state_.client(); }
+
+ // Called when the client has connected to this instance.
+ virtual void OnConnectionEstablished() {}
+
+ // Called when the client is no longer connected to this instance. NOTE: The
+ // client() method continues to return a non-null pointer after this method
+ // is called. After this method is called, any method calls made on client()
+ // will be silently ignored.
+ virtual void OnConnectionError() {}
+
+ // DO NOT USE. Exposed only for internal use and for testing.
+ internal::InterfaceImplState<Interface>* internal_state() {
+ return &internal_state_;
+ }
+
+ private:
+ internal::InterfaceImplState<Interface> internal_state_;
+ MOJO_DISALLOW_COPY_AND_ASSIGN(InterfaceImpl);
+};
+
+// Takes an instance of an InterfaceImpl<..> subclass and binds it to the given
+// MessagePipe. The instance is returned for convenience in member initializer
+// lists, etc. If the pipe is closed, the instance's OnConnectionError method
+// will be called.
+//
+// The instance is also bound to the current thread. Its methods will only be
+// called on the current thread, and if the current thread exits, then it will
+// also be deleted, and along with it, its end point of the pipe will be closed.
+//
+// Before returning, the instance's OnConnectionEstablished method is called.
+template <typename Impl>
+Impl* BindToPipe(
+ Impl* instance,
+ ScopedMessagePipeHandle handle,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ instance->internal_state()->Bind(handle.Pass(), waiter);
+ return instance;
+}
+
+// Takes an instance of an InterfaceImpl<..> subclass and binds it to the given
+// InterfacePtr<..>. The instance is returned for convenience in member
+// initializer lists, etc. If the pipe is closed, the instance's
+// OnConnectionError method will be called.
+//
+// The instance is also bound to the current thread. Its methods will only be
+// called on the current thread, and if the current thread exits, then it will
+// also be deleted, and along with it, its end point of the pipe will be closed.
+//
+// Before returning, the instance's OnConnectionEstablished method is called.
+template <typename Impl, typename Interface>
+Impl* BindToProxy(
+ Impl* instance,
+ InterfacePtr<Interface>* ptr,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ instance->internal_state()->BindProxy(ptr, waiter);
+ return instance;
+}
+
+// Takes an instance of an InterfaceImpl<..> subclass and binds it to the given
+// InterfaceRequest<..>. The instance is returned for convenience in member
+// initializer lists, etc. If the pipe is closed, the instance's
+// OnConnectionError method will be called.
+//
+// The instance is also bound to the current thread. Its methods will only be
+// called on the current thread, and if the current thread exits, then it will
+// also be deleted, and along with it, its end point of the pipe will be closed.
+//
+// Before returning, the instance will receive a SetClient call, providing it
+// with a proxy to the client on the other end of the pipe.
+template <typename Impl, typename Interface>
+Impl* BindToRequest(
+ Impl* instance,
+ InterfaceRequest<Interface>* request,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ return BindToPipe(instance, request->PassMessagePipe(), waiter);
+}
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_IMPL_H_
diff --git a/chromium/mojo/public/cpp/bindings/interface_ptr.h b/chromium/mojo/public/cpp/bindings/interface_ptr.h
new file mode 100644
index 00000000000..726896d9cce
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/interface_ptr.h
@@ -0,0 +1,124 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
+
+#include <assert.h>
+
+#include <algorithm>
+
+#include "mojo/public/cpp/bindings/error_handler.h"
+#include "mojo/public/cpp/bindings/lib/interface_ptr_internal.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+class ErrorHandler;
+
+// InterfacePtr represents a proxy to a remote instance of an interface.
+template <typename Interface>
+class InterfacePtr {
+ MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InterfacePtr, RValue)
+ public:
+ InterfacePtr() {}
+
+ InterfacePtr(RValue other) {
+ internal_state_.Swap(&other.object->internal_state_);
+ }
+ InterfacePtr& operator=(RValue other) {
+ reset();
+ internal_state_.Swap(&other.object->internal_state_);
+ return *this;
+ }
+
+ ~InterfacePtr() {}
+
+ Interface* get() const {
+ return internal_state_.instance();
+ }
+ Interface* operator->() const { return get(); }
+ Interface& operator*() const { return *get(); }
+
+ void reset() {
+ State doomed;
+ internal_state_.Swap(&doomed);
+ }
+
+ // This method configures the InterfacePtr<..> to be a proxy to a remote
+ // object on the other end of the given pipe.
+ //
+ // The proxy is bound to the current thread, which means its methods may
+ // only be called on the current thread.
+ //
+ // To move a bound InterfacePtr<..> to another thread, call
+ // ResetAndReturnMessagePipe. Then create a new InterfacePtr<..> on another
+ // thread, and bind the new InterfacePtr<..> to the message pipe on that
+ // thread.
+ void Bind(
+ ScopedMessagePipeHandle handle,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ reset();
+ internal_state_.ConfigureProxy(handle.Pass(), waiter);
+ }
+
+ // The client interface may only be set after this InterfacePtr<..> is bound.
+ void set_client(typename Interface::Client* client) {
+ internal_state_.set_client(client);
+ }
+
+ // This method may be called to query if the underlying pipe has encountered
+ // an error. If true, this means method calls made on this interface will be
+ // dropped (and may have already been dropped) on the floor.
+ bool encountered_error() const {
+ assert(internal_state_.router());
+ return internal_state_.router()->encountered_error();
+ }
+
+ // This method may be called to register an ErrorHandler to observe a
+ // connection error on the underlying pipe. The callback runs asynchronously
+ // from the current message loop.
+ void set_error_handler(ErrorHandler* error_handler) {
+ assert(internal_state_.router());
+ internal_state_.router()->set_error_handler(error_handler);
+ }
+
+ // Returns the underlying message pipe handle (if any) and resets the
+ // InterfacePtr<..> to its uninitialized state. This method is helpful if you
+ // need to move a proxy to another thread. See related notes for Bind.
+ ScopedMessagePipeHandle PassMessagePipe() {
+ State state;
+ internal_state_.Swap(&state);
+ return state.router() ?
+ state.router()->PassMessagePipe() : ScopedMessagePipeHandle();
+ }
+
+ // DO NOT USE. Exposed only for internal use and for testing.
+ internal::InterfacePtrState<Interface>* internal_state() {
+ return &internal_state_;
+ }
+
+ private:
+ typedef internal::InterfacePtrState<Interface> State;
+ State internal_state_;
+};
+
+// Takes a handle to the proxy end-point of a pipe. On the other end is
+// presumed to be an interface implementation of type |Interface|. Returns a
+// generated proxy to that interface, which may be used on the current thread.
+// It is valid to call set_client on the returned InterfacePtr<..> to set an
+// instance of Interface::Client.
+template <typename Interface>
+InterfacePtr<Interface> MakeProxy(
+ ScopedMessagePipeHandle handle,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ InterfacePtr<Interface> ptr;
+ if (handle.is_valid())
+ ptr.Bind(handle.Pass(), waiter);
+ return ptr.Pass();
+}
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
diff --git a/chromium/mojo/public/cpp/bindings/interface_request.h b/chromium/mojo/public/cpp/bindings/interface_request.h
new file mode 100644
index 00000000000..6b7d3033c9d
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/interface_request.h
@@ -0,0 +1,76 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_
+
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+
+namespace mojo {
+
+// Used in methods that return instances of remote objects.
+template <typename Interface>
+class InterfaceRequest {
+ MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InterfaceRequest, RValue)
+ public:
+ InterfaceRequest() {}
+
+ InterfaceRequest(RValue other) {
+ handle_ = other.object->handle_.Pass();
+ }
+ InterfaceRequest& operator=(RValue other) {
+ handle_ = other.object->handle_.Pass();
+ return *this;
+ }
+
+ // Returns true if the request has yet to be completed.
+ bool is_pending() const { return handle_.is_valid(); }
+
+ void Bind(ScopedMessagePipeHandle handle) {
+ handle_ = handle.Pass();
+ }
+
+ ScopedMessagePipeHandle PassMessagePipe() {
+ return handle_.Pass();
+ }
+
+ private:
+ ScopedMessagePipeHandle handle_;
+};
+
+template <typename Interface>
+InterfaceRequest<Interface> MakeRequest(ScopedMessagePipeHandle handle) {
+ InterfaceRequest<Interface> request;
+ request.Bind(handle.Pass());
+ return request.Pass();
+}
+
+// Used to construct a request that synchronously binds an InterfacePtr<..>,
+// making it immediately usable upon return. The resulting request object may
+// then be later bound to an InterfaceImpl<..> via BindToRequest.
+//
+// Given the following interface:
+//
+// interface Foo {
+// CreateBar(Bar& bar);
+// }
+//
+// The caller of CreateBar would have code similar to the following:
+//
+// InterfacePtr<Foo> foo = ...;
+// InterfacePtr<Bar> bar;
+// foo->CreateBar(Get(&bar));
+//
+// Upon return from CreateBar, |bar| is ready to have methods called on it.
+//
+template <typename Interface>
+InterfaceRequest<Interface> Get(InterfacePtr<Interface>* ptr) {
+ MessagePipe pipe;
+ ptr->Bind(pipe.handle0.Pass());
+ return MakeRequest<Interface>(pipe.handle1.Pass());
+}
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/DEPS b/chromium/mojo/public/cpp/bindings/lib/DEPS
new file mode 100644
index 00000000000..b809b58d337
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ "+mojo/public/cpp/bindings",
+ "+mojo/public/cpp/environment",
+ "+mojo/public/cpp/system",
+]
diff --git a/chromium/mojo/public/cpp/bindings/lib/TODO b/chromium/mojo/public/cpp/bindings/lib/TODO
new file mode 100644
index 00000000000..21bcb6fe7a2
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/TODO
@@ -0,0 +1,6 @@
+TODOs:
+ - Ensure validation checks are solid
+ - Add tests of validation logic
+ - Optimize Buffer classes?
+ - Add compile-time asserts to verify object packing and padding.
+ - Investigate making arrays of objects not be arrays of pointers.
diff --git a/chromium/mojo/public/cpp/bindings/lib/array_internal.cc b/chromium/mojo/public/cpp/bindings/lib/array_internal.cc
new file mode 100644
index 00000000000..3f7f1ce0b16
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/array_internal.cc
@@ -0,0 +1,70 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+
+namespace mojo {
+namespace internal {
+
+ArrayDataTraits<bool>::BitRef::~BitRef() {
+}
+
+ArrayDataTraits<bool>::BitRef::BitRef(uint8_t* storage, uint8_t mask)
+ : storage_(storage),
+ mask_(mask) {
+}
+
+ArrayDataTraits<bool>::BitRef&
+ArrayDataTraits<bool>::BitRef::operator=(bool value) {
+ if (value) {
+ *storage_ |= mask_;
+ } else {
+ *storage_ &= ~mask_;
+ }
+ return *this;
+}
+
+ArrayDataTraits<bool>::BitRef&
+ArrayDataTraits<bool>::BitRef::operator=(const BitRef& value) {
+ return (*this) = static_cast<bool>(value);
+}
+
+ArrayDataTraits<bool>::BitRef::operator bool() const {
+ return (*storage_ & mask_) != 0;
+}
+
+// static
+void ArraySerializationHelper<Handle, true>::EncodePointersAndHandles(
+ const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ for (uint32_t i = 0; i < header->num_elements; ++i)
+ EncodeHandle(&elements[i], handles);
+}
+
+// static
+void ArraySerializationHelper<Handle, true>::DecodePointersAndHandles(
+ const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ for (uint32_t i = 0; i < header->num_elements; ++i)
+ DecodeHandle(&elements[i], handles);
+}
+
+// static
+bool ArraySerializationHelper<Handle, true>::ValidateElements(
+ const ArrayHeader* header,
+ const ElementType* elements,
+ BoundsChecker* bounds_checker) {
+ for (uint32_t i = 0; i < header->num_elements; ++i) {
+ if (!bounds_checker->ClaimHandle(elements[i])) {
+ ReportValidationError(VALIDATION_ERROR_ILLEGAL_HANDLE);
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/array_internal.h b/chromium/mojo/public/cpp/bindings/lib/array_internal.h
new file mode 100644
index 00000000000..8ea00991251
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/array_internal.h
@@ -0,0 +1,384 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
+
+#include <new>
+#include <vector>
+
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
+#include "mojo/public/cpp/bindings/lib/buffer.h"
+#include "mojo/public/cpp/bindings/lib/validation_errors.h"
+
+namespace mojo {
+template <typename T> class Array;
+class String;
+
+namespace internal {
+
+template <typename T>
+struct ArrayDataTraits {
+ typedef T StorageType;
+ typedef T& Ref;
+ typedef T const& ConstRef;
+
+ static size_t GetStorageSize(size_t num_elements) {
+ return sizeof(StorageType) * num_elements;
+ }
+ static Ref ToRef(StorageType* storage, size_t offset) {
+ return storage[offset];
+ }
+ static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
+ return storage[offset];
+ }
+};
+
+template <typename P>
+struct ArrayDataTraits<P*> {
+ typedef StructPointer<P> StorageType;
+ typedef P*& Ref;
+ typedef P* const& ConstRef;
+
+ static size_t GetStorageSize(size_t num_elements) {
+ return sizeof(StorageType) * num_elements;
+ }
+ static Ref ToRef(StorageType* storage, size_t offset) {
+ return storage[offset].ptr;
+ }
+ static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
+ return storage[offset].ptr;
+ }
+};
+
+template <typename T>
+struct ArrayDataTraits<Array_Data<T>*> {
+ typedef ArrayPointer<T> StorageType;
+ typedef Array_Data<T>*& Ref;
+ typedef Array_Data<T>* const& ConstRef;
+
+ static size_t GetStorageSize(size_t num_elements) {
+ return sizeof(StorageType) * num_elements;
+ }
+ static Ref ToRef(StorageType* storage, size_t offset) {
+ return storage[offset].ptr;
+ }
+ static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
+ return storage[offset].ptr;
+ }
+};
+
+// Specialization of Arrays for bools, optimized for space. It has the
+// following differences from a generalized Array:
+// * Each element takes up a single bit of memory.
+// * Accessing a non-const single element uses a helper class |BitRef|, which
+// emulates a reference to a bool.
+template <>
+struct ArrayDataTraits<bool> {
+ // Helper class to emulate a reference to a bool, used for direct element
+ // access.
+ class BitRef {
+ public:
+ ~BitRef();
+ BitRef& operator=(bool value);
+ BitRef& operator=(const BitRef& value);
+ operator bool() const;
+ private:
+ friend struct ArrayDataTraits<bool>;
+ BitRef(uint8_t* storage, uint8_t mask);
+ BitRef();
+ uint8_t* storage_;
+ uint8_t mask_;
+ };
+
+ typedef uint8_t StorageType;
+ typedef BitRef Ref;
+ typedef bool ConstRef;
+
+ static size_t GetStorageSize(size_t num_elements) {
+ return ((num_elements + 7) / 8);
+ }
+ static BitRef ToRef(StorageType* storage, size_t offset) {
+ return BitRef(&storage[offset / 8], 1 << (offset % 8));
+ }
+ static bool ToConstRef(const StorageType* storage, size_t offset) {
+ return (storage[offset / 8] & (1 << (offset % 8))) != 0;
+ }
+};
+
+// What follows is code to support the serialization of Array_Data<T>. There
+// are two interesting cases: arrays of primitives and arrays of objects.
+// Arrays of objects are represented as arrays of pointers to objects.
+
+template <typename T, bool kIsHandle> struct ArraySerializationHelper;
+
+template <typename T>
+struct ArraySerializationHelper<T, false> {
+ typedef typename ArrayDataTraits<T>::StorageType ElementType;
+
+ static void EncodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ }
+
+ static void DecodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ }
+
+ static bool ValidateElements(const ArrayHeader* header,
+ const ElementType* elements,
+ BoundsChecker* bounds_checker) {
+ return true;
+ }
+};
+
+template <>
+struct ArraySerializationHelper<Handle, true> {
+ typedef ArrayDataTraits<Handle>::StorageType ElementType;
+
+ static void EncodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles);
+
+ static void DecodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles);
+
+ static bool ValidateElements(const ArrayHeader* header,
+ const ElementType* elements,
+ BoundsChecker* bounds_checker);
+};
+
+template <typename H>
+struct ArraySerializationHelper<H, true> {
+ typedef typename ArrayDataTraits<H>::StorageType ElementType;
+
+ static void EncodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ ArraySerializationHelper<Handle, true>::EncodePointersAndHandles(
+ header, elements, handles);
+ }
+
+ static void DecodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ ArraySerializationHelper<Handle, true>::DecodePointersAndHandles(
+ header, elements, handles);
+ }
+
+ static bool ValidateElements(const ArrayHeader* header,
+ const ElementType* elements,
+ BoundsChecker* bounds_checker) {
+ return ArraySerializationHelper<Handle, true>::ValidateElements(
+ header, elements, bounds_checker);
+ }
+};
+
+template <typename P>
+struct ArraySerializationHelper<P*, false> {
+ typedef typename ArrayDataTraits<P*>::StorageType ElementType;
+
+ static void EncodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ for (uint32_t i = 0; i < header->num_elements; ++i)
+ Encode(&elements[i], handles);
+ }
+
+ static void DecodePointersAndHandles(const ArrayHeader* header,
+ ElementType* elements,
+ std::vector<Handle>* handles) {
+ for (uint32_t i = 0; i < header->num_elements; ++i)
+ Decode(&elements[i], handles);
+ }
+
+ static bool ValidateElements(const ArrayHeader* header,
+ const ElementType* elements,
+ BoundsChecker* bounds_checker) {
+ for (uint32_t i = 0; i < header->num_elements; ++i) {
+ if (!ValidateEncodedPointer(&elements[i].offset)) {
+ ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER);
+ return false;
+ }
+ if (!P::Validate(DecodePointerRaw(&elements[i].offset), bounds_checker))
+ return false;
+ }
+ return true;
+ }
+};
+
+template <typename T>
+class Array_Data {
+ public:
+ typedef ArrayDataTraits<T> Traits;
+ typedef typename Traits::StorageType StorageType;
+ typedef typename Traits::Ref Ref;
+ typedef typename Traits::ConstRef ConstRef;
+ typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper;
+
+ static Array_Data<T>* New(size_t num_elements, Buffer* buf) {
+ size_t num_bytes = sizeof(Array_Data<T>) +
+ Traits::GetStorageSize(num_elements);
+ return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes,
+ num_elements);
+ }
+
+ static bool Validate(const void* data, BoundsChecker* bounds_checker) {
+ if (!data)
+ return true;
+ if (!IsAligned(data)) {
+ ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT);
+ return false;
+ }
+ if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) {
+ ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
+ return false;
+ }
+ const ArrayHeader* header = static_cast<const ArrayHeader*>(data);
+ if (header->num_bytes < (sizeof(Array_Data<T>) +
+ Traits::GetStorageSize(header->num_elements))) {
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER);
+ return false;
+ }
+ if (!bounds_checker->ClaimMemory(data, header->num_bytes)) {
+ ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
+ return false;
+ }
+
+ const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data);
+ return Helper::ValidateElements(&object->header_, object->storage(),
+ bounds_checker);
+ }
+
+ size_t size() const { return header_.num_elements; }
+
+ Ref at(size_t offset) {
+ assert(offset < static_cast<size_t>(header_.num_elements));
+ return Traits::ToRef(storage(), offset);
+ }
+
+ ConstRef at(size_t offset) const {
+ assert(offset < static_cast<size_t>(header_.num_elements));
+ return Traits::ToConstRef(storage(), offset);
+ }
+
+ StorageType* storage() {
+ return reinterpret_cast<StorageType*>(
+ reinterpret_cast<char*>(this) + sizeof(*this));
+ }
+
+ const StorageType* storage() const {
+ return reinterpret_cast<const StorageType*>(
+ reinterpret_cast<const char*>(this) + sizeof(*this));
+ }
+
+ void EncodePointersAndHandles(std::vector<Handle>* handles) {
+ Helper::EncodePointersAndHandles(&header_, storage(), handles);
+ }
+
+ void DecodePointersAndHandles(std::vector<Handle>* handles) {
+ Helper::DecodePointersAndHandles(&header_, storage(), handles);
+ }
+
+ private:
+ Array_Data(size_t num_bytes, size_t num_elements) {
+ header_.num_bytes = static_cast<uint32_t>(num_bytes);
+ header_.num_elements = static_cast<uint32_t>(num_elements);
+ }
+ ~Array_Data() {}
+
+ internal::ArrayHeader header_;
+
+ // Elements of type internal::ArrayDataTraits<T>::StorageType follow.
+};
+MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data);
+
+// UTF-8 encoded
+typedef Array_Data<char> String_Data;
+
+template <typename T, bool kIsMoveOnlyType> struct ArrayTraits {};
+
+template <typename T> struct ArrayTraits<T, false> {
+ typedef T StorageType;
+ typedef typename std::vector<T>::reference RefType;
+ typedef typename std::vector<T>::const_reference ConstRefType;
+ typedef ConstRefType ForwardType;
+ static inline void Initialize(std::vector<T>* vec) {
+ }
+ static inline void Finalize(std::vector<T>* vec) {
+ }
+ static inline ConstRefType at(const std::vector<T>* vec, size_t offset) {
+ return vec->at(offset);
+ }
+ static inline RefType at(std::vector<T>* vec, size_t offset) {
+ return vec->at(offset);
+ }
+ static inline void Resize(std::vector<T>* vec, size_t size) {
+ vec->resize(size);
+ }
+ static inline void PushBack(std::vector<T>* vec, ForwardType value) {
+ vec->push_back(value);
+ }
+};
+
+template <typename T> struct ArrayTraits<T, true> {
+ struct StorageType {
+ char buf[sizeof(T) + (8 - (sizeof(T) % 8)) % 8]; // Make 8-byte aligned.
+ };
+ typedef T& RefType;
+ typedef const T& ConstRefType;
+ typedef T ForwardType;
+ static inline void Initialize(std::vector<StorageType>* vec) {
+ for (size_t i = 0; i < vec->size(); ++i)
+ new (vec->at(i).buf) T();
+ }
+ static inline void Finalize(std::vector<StorageType>* vec) {
+ for (size_t i = 0; i < vec->size(); ++i)
+ reinterpret_cast<T*>(vec->at(i).buf)->~T();
+ }
+ static inline ConstRefType at(const std::vector<StorageType>* vec,
+ size_t offset) {
+ return *reinterpret_cast<const T*>(vec->at(offset).buf);
+ }
+ static inline RefType at(std::vector<StorageType>* vec, size_t offset) {
+ return *reinterpret_cast<T*>(vec->at(offset).buf);
+ }
+ static inline void Resize(std::vector<StorageType>* vec, size_t size) {
+ size_t old_size = vec->size();
+ for (size_t i = size; i < old_size; i++)
+ reinterpret_cast<T*>(vec->at(i).buf)->~T();
+ ResizeStorage(vec, size);
+ for (size_t i = old_size; i < vec->size(); i++)
+ new (vec->at(i).buf) T();
+ }
+ static inline void PushBack(std::vector<StorageType>* vec, RefType value) {
+ size_t old_size = vec->size();
+ ResizeStorage(vec, old_size + 1);
+ new (vec->at(old_size).buf) T(value.Pass());
+ }
+ static inline void ResizeStorage(std::vector<StorageType>* vec, size_t size) {
+ if (size <= vec->capacity()) {
+ vec->resize(size);
+ return;
+ }
+ std::vector<StorageType> new_storage(size);
+ for (size_t i = 0; i < vec->size(); i++)
+ new (new_storage.at(i).buf) T(at(vec, i).Pass());
+ vec->swap(new_storage);
+ Finalize(&new_storage);
+ }
+};
+
+template <> struct WrapperTraits<String, false> {
+ typedef String_Data* DataType;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/array_serialization.h b/chromium/mojo/public/cpp/bindings/lib/array_serialization.h
new file mode 100644
index 00000000000..83403d52502
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/array_serialization.h
@@ -0,0 +1,179 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
+
+#include <string>
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/string_serialization.h"
+
+namespace mojo {
+
+template <typename E>
+inline size_t GetSerializedSize_(const Array<E>& input);
+
+template <typename E, typename F>
+inline void Serialize_(Array<E> input, internal::Buffer* buf,
+ internal::Array_Data<F>** output);
+template <typename E, typename F>
+inline void Deserialize_(internal::Array_Data<F>* data, Array<E>* output);
+
+namespace internal {
+
+template <typename E, typename F, bool move_only = IsMoveOnlyType<E>::value>
+struct ArraySerializer;
+
+template <typename E, typename F> struct ArraySerializer<E, F, false> {
+ MOJO_COMPILE_ASSERT(sizeof(E) == sizeof(F), wrong_array_serializer);
+ static size_t GetSerializedSize(const Array<E>& input) {
+ return sizeof(Array_Data<F>) + Align(input.size() * sizeof(E));
+ }
+ static void SerializeElements(
+ Array<E> input, Buffer* buf, Array_Data<F>* output) {
+ memcpy(output->storage(), &input.storage()[0], input.size() * sizeof(E));
+ }
+ static void DeserializeElements(
+ Array_Data<F>* input, Array<E>* output) {
+ std::vector<E> result(input->size());
+ memcpy(&result[0], input->storage(), input->size() * sizeof(E));
+ output->Swap(&result);
+ }
+};
+
+template <> struct ArraySerializer<bool, bool, false> {
+ static size_t GetSerializedSize(const Array<bool>& input) {
+ return sizeof(Array_Data<bool>) + Align((input.size() + 7) / 8);
+ }
+ static void SerializeElements(
+ Array<bool> input, Buffer* buf, Array_Data<bool>* output) {
+ // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy?
+ for (size_t i = 0; i < input.size(); ++i)
+ output->at(i) = input[i];
+ }
+ static void DeserializeElements(
+ Array_Data<bool>* input, Array<bool>* output) {
+ Array<bool> result(input->size());
+ // TODO(darin): Can this be a memcpy somehow instead of a bit-by-bit copy?
+ for (size_t i = 0; i < input->size(); ++i)
+ result.at(i) = input->at(i);
+ output->Swap(&result);
+ }
+};
+
+template <typename H> struct ArraySerializer<ScopedHandleBase<H>, H, true> {
+ static size_t GetSerializedSize(const Array<ScopedHandleBase<H> >& input) {
+ return sizeof(Array_Data<H>) + Align(input.size() * sizeof(H));
+ }
+ static void SerializeElements(
+ Array<ScopedHandleBase<H> > input,
+ Buffer* buf,
+ Array_Data<H>* output) {
+ for (size_t i = 0; i < input.size(); ++i)
+ output->at(i) = input[i].release(); // Transfer ownership of the handle.
+ }
+ static void DeserializeElements(
+ Array_Data<H>* input, Array<ScopedHandleBase<H> >* output) {
+ Array<ScopedHandleBase<H> > result(input->size());
+ for (size_t i = 0; i < input->size(); ++i)
+ result.at(i) = MakeScopedHandle(FetchAndReset(&input->at(i)));
+ output->Swap(&result);
+ }
+};
+
+template <typename S> struct ArraySerializer<S, typename S::Data_*, true> {
+ static size_t GetSerializedSize(const Array<S>& input) {
+ size_t size = sizeof(Array_Data<typename S::Data_*>) +
+ input.size() * sizeof(internal::StructPointer<typename S::Data_>);
+ for (size_t i = 0; i < input.size(); ++i)
+ size += GetSerializedSize_(input[i]);
+ return size;
+ }
+ static void SerializeElements(
+ Array<S> input,
+ Buffer* buf,
+ Array_Data<typename S::Data_*>* output) {
+ for (size_t i = 0; i < input.size(); ++i) {
+ typename S::Data_* element;
+ Serialize_(input[i].Pass(), buf, &element);
+ output->at(i) = element;
+ }
+ }
+ static void DeserializeElements(
+ Array_Data<typename S::Data_*>* input, Array<S>* output) {
+ Array<S> result(input->size());
+ for (size_t i = 0; i < input->size(); ++i) {
+ S element;
+ Deserialize_(input->at(i), &element);
+ result[i] = element.Pass();
+ }
+ output->Swap(&result);
+ }
+};
+
+template <> struct ArraySerializer<String, String_Data*, false> {
+ static size_t GetSerializedSize(const Array<String>& input) {
+ size_t size = sizeof(Array_Data<String_Data*>) +
+ input.size() * sizeof(internal::StringPointer);
+ for (size_t i = 0; i < input.size(); ++i)
+ size += GetSerializedSize_(input[i]);
+ return size;
+ }
+ static void SerializeElements(
+ Array<String> input,
+ Buffer* buf,
+ Array_Data<String_Data*>* output) {
+ for (size_t i = 0; i < input.size(); ++i) {
+ String_Data* element;
+ Serialize_(input[i], buf, &element);
+ output->at(i) = element;
+ }
+ }
+ static void DeserializeElements(
+ Array_Data<String_Data*>* input, Array<String>* output) {
+ Array<String> result(input->size());
+ for (size_t i = 0; i < input->size(); ++i)
+ Deserialize_(input->at(i), &result[i]);
+ output->Swap(&result);
+ }
+};
+
+} // namespace internal
+
+template <typename E>
+inline size_t GetSerializedSize_(const Array<E>& input) {
+ if (!input)
+ return 0;
+ typedef typename internal::WrapperTraits<E>::DataType F;
+ return internal::ArraySerializer<E, F>::GetSerializedSize(input);
+}
+
+template <typename E, typename F>
+inline void Serialize_(Array<E> input, internal::Buffer* buf,
+ internal::Array_Data<F>** output) {
+ if (input) {
+ internal::Array_Data<F>* result =
+ internal::Array_Data<F>::New(input.size(), buf);
+ internal::ArraySerializer<E, F>::SerializeElements(
+ internal::Forward(input), buf, result);
+ *output = result;
+ } else {
+ *output = NULL;
+ }
+}
+
+template <typename E, typename F>
+inline void Deserialize_(internal::Array_Data<F>* input,
+ Array<E>* output) {
+ if (input) {
+ internal::ArraySerializer<E, F>::DeserializeElements(input, output);
+ } else {
+ output->reset();
+ }
+}
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h b/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h
new file mode 100644
index 00000000000..6e87cbd1fb5
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -0,0 +1,86 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
+
+#include "mojo/public/cpp/bindings/lib/template_util.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+class String;
+
+namespace internal {
+template <typename T> class Array_Data;
+
+#pragma pack(push, 1)
+
+struct StructHeader {
+ uint32_t num_bytes;
+ uint32_t num_fields;
+};
+MOJO_COMPILE_ASSERT(sizeof(StructHeader) == 8, bad_sizeof_StructHeader);
+
+struct ArrayHeader {
+ uint32_t num_bytes;
+ uint32_t num_elements;
+};
+MOJO_COMPILE_ASSERT(sizeof(ArrayHeader) == 8, bad_sizeof_ArrayHeader);
+
+template <typename T>
+union StructPointer {
+ uint64_t offset;
+ T* ptr;
+};
+MOJO_COMPILE_ASSERT(sizeof(StructPointer<char>) == 8, bad_sizeof_StructPointer);
+
+template <typename T>
+union ArrayPointer {
+ uint64_t offset;
+ Array_Data<T>* ptr;
+};
+MOJO_COMPILE_ASSERT(sizeof(ArrayPointer<char>) == 8, bad_sizeof_ArrayPointer);
+
+union StringPointer {
+ uint64_t offset;
+ Array_Data<char>* ptr;
+};
+MOJO_COMPILE_ASSERT(sizeof(StringPointer) == 8, bad_sizeof_StringPointer);
+
+#pragma pack(pop)
+
+template <typename T>
+void ResetIfNonNull(T* ptr) {
+ if (ptr)
+ *ptr = T();
+}
+
+template <typename T>
+T FetchAndReset(T* ptr) {
+ T temp = *ptr;
+ *ptr = T();
+ return temp;
+}
+
+template <typename H> struct IsHandle {
+ static const bool value = IsBaseOf<Handle, H>::value;
+};
+
+template <typename T, bool move_only = IsMoveOnlyType<T>::value>
+struct WrapperTraits;
+
+template <typename T> struct WrapperTraits<T, false> {
+ typedef T DataType;
+};
+template <typename H> struct WrapperTraits<ScopedHandleBase<H>, true> {
+ typedef H DataType;
+};
+template <typename S> struct WrapperTraits<S, true> {
+ typedef typename S::Data_* DataType;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.cc b/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.cc
new file mode 100644
index 00000000000..d5f77853684
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.cc
@@ -0,0 +1,118 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+
+#include <assert.h>
+
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
+#include "mojo/public/cpp/bindings/lib/validation_errors.h"
+
+namespace mojo {
+namespace internal {
+
+namespace {
+
+const size_t kAlignment = 8;
+
+template<typename T>
+T AlignImpl(T t) {
+ return t + (kAlignment - (t % kAlignment)) % kAlignment;
+}
+
+} // namespace
+
+size_t Align(size_t size) {
+ return AlignImpl(size);
+}
+
+char* AlignPointer(char* ptr) {
+ return reinterpret_cast<char*>(AlignImpl(reinterpret_cast<uintptr_t>(ptr)));
+}
+
+bool IsAligned(const void* ptr) {
+ return !(reinterpret_cast<uintptr_t>(ptr) % kAlignment);
+}
+
+void EncodePointer(const void* ptr, uint64_t* offset) {
+ if (!ptr) {
+ *offset = 0;
+ return;
+ }
+
+ const char* p_obj = reinterpret_cast<const char*>(ptr);
+ const char* p_slot = reinterpret_cast<const char*>(offset);
+ assert(p_obj > p_slot);
+
+ *offset = static_cast<uint64_t>(p_obj - p_slot);
+}
+
+const void* DecodePointerRaw(const uint64_t* offset) {
+ if (!*offset)
+ return NULL;
+ return reinterpret_cast<const char*>(offset) + *offset;
+}
+
+bool ValidateEncodedPointer(const uint64_t* offset) {
+ // Cast to uintptr_t so overflow behavior is well defined.
+ return reinterpret_cast<uintptr_t>(offset) + *offset >=
+ reinterpret_cast<uintptr_t>(offset);
+}
+
+void EncodeHandle(Handle* handle, std::vector<Handle>* handles) {
+ if (handle->is_valid()) {
+ handles->push_back(*handle);
+ handle->set_value(static_cast<MojoHandle>(handles->size() - 1));
+ } else {
+ handle->set_value(kEncodedInvalidHandleValue);
+ }
+}
+
+void DecodeHandle(Handle* handle, std::vector<Handle>* handles) {
+ if (handle->value() == kEncodedInvalidHandleValue) {
+ *handle = Handle();
+ return;
+ }
+ assert(handle->value() < handles->size());
+ // Just leave holes in the vector so we don't screw up other indices.
+ *handle = FetchAndReset(&handles->at(handle->value()));
+}
+
+bool ValidateStructHeader(const void* data,
+ uint32_t min_num_bytes,
+ uint32_t min_num_fields,
+ BoundsChecker* bounds_checker) {
+ assert(min_num_bytes >= sizeof(StructHeader));
+
+ if (!IsAligned(data)) {
+ ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT);
+ return false;
+ }
+ if (!bounds_checker->IsValidRange(data, sizeof(StructHeader))) {
+ ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
+ return false;
+ }
+
+ const StructHeader* header = static_cast<const StructHeader*>(data);
+
+ // TODO(yzshen): Currently our binding code cannot handle structs of smaller
+ // size or with fewer fields than the version that it sees. That needs to be
+ // changed in order to provide backward compatibility.
+ if (header->num_bytes < min_num_bytes ||
+ header->num_fields < min_num_fields) {
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
+ return false;
+ }
+
+ if (!bounds_checker->ClaimMemory(data, header->num_bytes)) {
+ ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.h b/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.h
new file mode 100644
index 00000000000..6bebf90bf95
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/bindings_serialization.h
@@ -0,0 +1,83 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
+
+#include <vector>
+
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+namespace internal {
+
+class BoundsChecker;
+
+// Please note that this is a different value than |mojo::kInvalidHandleValue|,
+// which is the "decoded" invalid handle.
+const MojoHandle kEncodedInvalidHandleValue = static_cast<MojoHandle>(-1);
+
+size_t Align(size_t size);
+char* AlignPointer(char* ptr);
+
+bool IsAligned(const void* ptr);
+
+// Pointers are encoded as relative offsets. The offsets are relative to the
+// address of where the offset value is stored, such that the pointer may be
+// recovered with the expression:
+//
+// ptr = reinterpret_cast<char*>(offset) + *offset
+//
+// A null pointer is encoded as an offset value of 0.
+//
+void EncodePointer(const void* ptr, uint64_t* offset);
+// Note: This function doesn't validate the encoded pointer value.
+const void* DecodePointerRaw(const uint64_t* offset);
+
+// Note: This function doesn't validate the encoded pointer value.
+template <typename T>
+inline void DecodePointer(const uint64_t* offset, T** ptr) {
+ *ptr = reinterpret_cast<T*>(const_cast<void*>(DecodePointerRaw(offset)));
+}
+
+// Checks whether decoding the pointer will overflow and produce a pointer
+// smaller than |offset|.
+bool ValidateEncodedPointer(const uint64_t* offset);
+
+// Handles are encoded as indices into a vector of handles. These functions
+// manipulate the value of |handle|, mapping it to and from an index.
+void EncodeHandle(Handle* handle, std::vector<Handle>* handles);
+// Note: This function doesn't validate the encoded handle value.
+void DecodeHandle(Handle* handle, std::vector<Handle>* handles);
+
+// The following 2 functions are used to encode/decode all objects (structs and
+// arrays) in a consistent manner.
+
+template <typename T>
+inline void Encode(T* obj, std::vector<Handle>* handles) {
+ if (obj->ptr)
+ obj->ptr->EncodePointersAndHandles(handles);
+ EncodePointer(obj->ptr, &obj->offset);
+}
+
+// Note: This function doesn't validate the encoded pointer and handle values.
+template <typename T>
+inline void Decode(T* obj, std::vector<Handle>* handles) {
+ DecodePointer(&obj->offset, &obj->ptr);
+ if (obj->ptr)
+ obj->ptr->DecodePointersAndHandles(handles);
+}
+
+// If returns true, this function also claims the memory range of the size
+// specified in the struct header, starting from |data|.
+// Note: |min_num_bytes| must be no less than sizeof(StructHeader).
+bool ValidateStructHeader(const void* data,
+ uint32_t min_num_bytes,
+ uint32_t min_num_fields,
+ BoundsChecker* bounds_checker);
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/bounds_checker.cc b/chromium/mojo/public/cpp/bindings/lib/bounds_checker.cc
new file mode 100644
index 00000000000..cf1f3238e03
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/bounds_checker.cc
@@ -0,0 +1,77 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
+
+#include <assert.h>
+
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+namespace internal {
+
+BoundsChecker::BoundsChecker(const void* data, uint32_t data_num_bytes,
+ size_t num_handles)
+ : data_begin_(reinterpret_cast<uintptr_t>(data)),
+ data_end_(data_begin_ + data_num_bytes),
+ handle_begin_(0),
+ handle_end_(static_cast<uint32_t>(num_handles)) {
+ if (data_end_ < data_begin_) {
+ // The calculation of |data_end_| overflowed.
+ // It shouldn't happen but if it does, set the range to empty so
+ // IsValidRange() and ClaimMemory() always fail.
+ assert(false); // Not reached.
+ data_end_ = data_begin_;
+ }
+ if (handle_end_ < num_handles) {
+ // Assigning |num_handles| to |handle_end_| overflowed.
+ // It shouldn't happen but if it does, set the handle index range to empty.
+ assert(false); // Not reached.
+ handle_end_ = 0;
+ }
+}
+
+BoundsChecker::~BoundsChecker() {
+}
+
+bool BoundsChecker::ClaimMemory(const void* position, uint32_t num_bytes) {
+ uintptr_t begin = reinterpret_cast<uintptr_t>(position);
+ uintptr_t end = begin + num_bytes;
+
+ if (!InternalIsValidRange(begin, end))
+ return false;
+
+ data_begin_ = end;
+ return true;
+}
+
+bool BoundsChecker::ClaimHandle(const Handle& encoded_handle) {
+ uint32_t index = encoded_handle.value();
+ if (index == kEncodedInvalidHandleValue)
+ return true;
+
+ if (index < handle_begin_ || index >= handle_end_)
+ return false;
+
+ // |index| + 1 shouldn't overflow, because |index| is not the max value of
+ // uint32_t (it is less than |handle_end_|).
+ handle_begin_ = index + 1;
+ return true;
+}
+
+bool BoundsChecker::IsValidRange(const void* position,
+ uint32_t num_bytes) const {
+ uintptr_t begin = reinterpret_cast<uintptr_t>(position);
+ uintptr_t end = begin + num_bytes;
+
+ return InternalIsValidRange(begin, end);
+}
+
+bool BoundsChecker::InternalIsValidRange(uintptr_t begin, uintptr_t end) const {
+ return end > begin && begin >= data_begin_ && end <= data_end_;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/bounds_checker.h b/chromium/mojo/public/cpp/bindings/lib/bounds_checker.h
new file mode 100644
index 00000000000..6c472309dde
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/bounds_checker.h
@@ -0,0 +1,64 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BOUNDS_CHECKER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BOUNDS_CHECKER_H_
+
+#include <stdint.h>
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+class Handle;
+
+namespace internal {
+
+// BoundsChecker is used to validate object sizes, pointers and handle indices
+// for payload of incoming messages.
+class BoundsChecker {
+ public:
+ // [data, data + data_num_bytes) specifies the initial valid memory range.
+ // [0, num_handles) specifies the initial valid range of handle indices.
+ BoundsChecker(const void* data, uint32_t data_num_bytes,
+ size_t num_handles);
+
+ ~BoundsChecker();
+
+ // Claims the specified memory range.
+ // The method succeeds if the range is valid to claim. (Please see
+ // the comments for IsValidRange().)
+ // On success, the valid memory range is shrinked to begin right after the end
+ // of the claimed range.
+ bool ClaimMemory(const void* position, uint32_t num_bytes);
+
+ // Claims the specified encoded handle (which is basically a handle index).
+ // The method succeeds if:
+ // - |encoded_handle|'s value is |kEncodedInvalidHandleValue|.
+ // - the handle is contained inside the valid range of handle indices. In this
+ // case, the valid range is shinked to begin right after the claimed handle.
+ bool ClaimHandle(const Handle& encoded_handle);
+
+ // Returns true if the specified range is not empty, and the range is
+ // contained inside the valid memory range.
+ bool IsValidRange(const void* position, uint32_t num_bytes) const;
+
+ private:
+ bool InternalIsValidRange(uintptr_t begin, uintptr_t end) const;
+
+ // [data_begin_, data_end_) is the valid memory range.
+ uintptr_t data_begin_;
+ uintptr_t data_end_;
+
+ // [handle_begin_, handle_end_) is the valid handle index range.
+ uint32_t handle_begin_;
+ uint32_t handle_end_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(BoundsChecker);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BOUNDS_CHECKER_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/buffer.h b/chromium/mojo/public/cpp/bindings/lib/buffer.h
new file mode 100644
index 00000000000..c3b570e7767
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/buffer.h
@@ -0,0 +1,24 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_
+
+#include <stddef.h>
+
+namespace mojo {
+namespace internal {
+
+// Buffer provides a way to allocate memory. Allocations are 8-byte aligned and
+// zero-initialized. Allocations remain valid for the lifetime of the Buffer.
+class Buffer {
+ public:
+ virtual ~Buffer() {}
+ virtual void* Allocate(size_t num_bytes) = 0;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/callback_internal.h b/chromium/mojo/public/cpp/bindings/lib/callback_internal.h
new file mode 100644
index 00000000000..f76ebef59e6
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/callback_internal.h
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_CALLBACK_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CALLBACK_INTERNAL_H_
+
+namespace mojo {
+class String;
+
+namespace internal {
+
+template <typename T>
+struct Callback_ParamTraits {
+ typedef T ForwardType;
+};
+
+template <>
+struct Callback_ParamTraits<String> {
+ typedef const String& ForwardType;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CALLBACK_INTERNAL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/connector.cc b/chromium/mojo/public/cpp/bindings/lib/connector.cc
new file mode 100644
index 00000000000..aa2c4d12334
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/connector.cc
@@ -0,0 +1,157 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/connector.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "mojo/public/cpp/bindings/error_handler.h"
+
+namespace mojo {
+namespace internal {
+
+// ----------------------------------------------------------------------------
+
+Connector::Connector(ScopedMessagePipeHandle message_pipe,
+ const MojoAsyncWaiter* waiter)
+ : error_handler_(NULL),
+ waiter_(waiter),
+ message_pipe_(message_pipe.Pass()),
+ incoming_receiver_(NULL),
+ async_wait_id_(0),
+ error_(false),
+ drop_writes_(false),
+ enforce_errors_from_incoming_receiver_(true),
+ destroyed_flag_(NULL) {
+ // Even though we don't have an incoming receiver, we still want to monitor
+ // the message pipe to know if is closed or encounters an error.
+ WaitToReadMore();
+}
+
+Connector::~Connector() {
+ if (destroyed_flag_)
+ *destroyed_flag_ = true;
+
+ if (async_wait_id_)
+ waiter_->CancelWait(async_wait_id_);
+}
+
+void Connector::CloseMessagePipe() {
+ Close(message_pipe_.Pass());
+}
+
+ScopedMessagePipeHandle Connector::PassMessagePipe() {
+ if (async_wait_id_) {
+ waiter_->CancelWait(async_wait_id_);
+ async_wait_id_ = 0;
+ }
+ return message_pipe_.Pass();
+}
+
+bool Connector::Accept(Message* message) {
+ assert(message_pipe_.is_valid());
+
+ if (error_)
+ return false;
+
+ if (drop_writes_)
+ return true;
+
+ MojoResult rv = WriteMessageRaw(
+ message_pipe_.get(),
+ message->data(),
+ message->data_num_bytes(),
+ message->mutable_handles()->empty() ? NULL :
+ reinterpret_cast<const MojoHandle*>(
+ &message->mutable_handles()->front()),
+ static_cast<uint32_t>(message->mutable_handles()->size()),
+ MOJO_WRITE_MESSAGE_FLAG_NONE);
+
+ switch (rv) {
+ case MOJO_RESULT_OK:
+ // The handles were successfully transferred, so we don't need the message
+ // to track their lifetime any longer.
+ message->mutable_handles()->clear();
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // There's no point in continuing to write to this pipe since the other
+ // end is gone. Avoid writing any future messages. Hide write failures
+ // from the caller since we'd like them to continue consuming any backlog
+ // of incoming messages before regarding the message pipe as closed.
+ drop_writes_ = true;
+ break;
+ default:
+ // This particular write was rejected, presumably because of bad input.
+ // The pipe is not necessarily in a bad state.
+ return false;
+ }
+ return true;
+}
+
+// static
+void Connector::CallOnHandleReady(void* closure, MojoResult result) {
+ Connector* self = static_cast<Connector*>(closure);
+ self->OnHandleReady(result);
+}
+
+void Connector::OnHandleReady(MojoResult result) {
+ assert(async_wait_id_ != 0);
+ async_wait_id_ = 0;
+
+ if (result == MOJO_RESULT_OK) {
+ // Return immediately if |this| was destroyed. Do not touch any members!
+ if (!ReadMore())
+ return;
+ } else {
+ error_ = true;
+ }
+
+ if (error_ && error_handler_)
+ error_handler_->OnConnectionError();
+}
+
+void Connector::WaitToReadMore() {
+ async_wait_id_ = waiter_->AsyncWait(message_pipe_.get().value(),
+ MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_DEADLINE_INDEFINITE,
+ &Connector::CallOnHandleReady,
+ this);
+}
+
+bool Connector::ReadMore() {
+ while (true) {
+ bool receiver_result = false;
+
+ // Detect if |this| was destroyed during message dispatch. Allow for the
+ // possibility of re-entering ReadMore() through message dispatch.
+ bool was_destroyed_during_dispatch = false;
+ bool* previous_destroyed_flag = destroyed_flag_;
+ destroyed_flag_ = &was_destroyed_during_dispatch;
+
+ MojoResult rv = ReadAndDispatchMessage(
+ message_pipe_.get(), incoming_receiver_, &receiver_result);
+
+ if (was_destroyed_during_dispatch) {
+ if (previous_destroyed_flag)
+ *previous_destroyed_flag = true; // Propagate flag.
+ return false;
+ }
+ destroyed_flag_ = previous_destroyed_flag;
+
+ if (rv == MOJO_RESULT_SHOULD_WAIT) {
+ WaitToReadMore();
+ break;
+ }
+ if (rv != MOJO_RESULT_OK ||
+ (enforce_errors_from_incoming_receiver_ && !receiver_result)) {
+ error_ = true;
+ break;
+ }
+ }
+ return true;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/connector.h b/chromium/mojo/public/cpp/bindings/lib/connector.h
new file mode 100644
index 00000000000..30cd65f4c42
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/connector.h
@@ -0,0 +1,100 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_
+
+#include "mojo/public/c/environment/async_waiter.h"
+#include "mojo/public/cpp/bindings/lib/message_queue.h"
+#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+class ErrorHandler;
+
+namespace internal {
+
+// The Connector class is responsible for performing read/write operations on a
+// MessagePipe. It writes messages it receives through the MessageReceiver
+// interface that it subclasses, and it forwards messages it reads through the
+// MessageReceiver interface assigned as its incoming receiver.
+//
+// NOTE: MessagePipe I/O is non-blocking.
+//
+class Connector : public MessageReceiver {
+ public:
+ // The Connector takes ownership of |message_pipe|.
+ explicit Connector(
+ ScopedMessagePipeHandle message_pipe,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter());
+ virtual ~Connector();
+
+ // Sets the receiver to handle messages read from the message pipe. The
+ // Connector will read messages from the pipe regardless of whether or not an
+ // incoming receiver has been set.
+ void set_incoming_receiver(MessageReceiver* receiver) {
+ incoming_receiver_ = receiver;
+ }
+
+ // Errors from incoming receivers will force the connector into an error
+ // state, where no more messages will be processed. This method is used
+ // during testing to prevent that from happening.
+ void set_enforce_errors_from_incoming_receiver(bool enforce) {
+ enforce_errors_from_incoming_receiver_ = enforce;
+ }
+
+ // Sets the error handler to receive notifications when an error is
+ // encountered while reading from the pipe or waiting to read from the pipe.
+ void set_error_handler(ErrorHandler* error_handler) {
+ error_handler_ = error_handler;
+ }
+
+ // Returns true if an error was encountered while reading from the pipe or
+ // waiting to read from the pipe.
+ bool encountered_error() const { return error_; }
+
+ // Closes the pipe, triggering the error state. Connector is put into a
+ // quiescent state.
+ void CloseMessagePipe();
+
+ // Releases the pipe, not triggering the error state. Connector is put into
+ // a quiescent state.
+ ScopedMessagePipeHandle PassMessagePipe();
+
+ // MessageReceiver implementation:
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+
+ private:
+ static void CallOnHandleReady(void* closure, MojoResult result);
+ void OnHandleReady(MojoResult result);
+
+ void WaitToReadMore();
+
+ // Returns false if |this| was destroyed during message dispatch.
+ MOJO_WARN_UNUSED_RESULT bool ReadMore();
+
+ ErrorHandler* error_handler_;
+ const MojoAsyncWaiter* waiter_;
+
+ ScopedMessagePipeHandle message_pipe_;
+ MessageReceiver* incoming_receiver_;
+
+ MojoAsyncWaitID async_wait_id_;
+ bool error_;
+ bool drop_writes_;
+ bool enforce_errors_from_incoming_receiver_;
+
+ // If non-null, this will be set to true when the Connector is destroyed. We
+ // use this flag to allow for the Connector to be destroyed as a side-effect
+ // of dispatching an incoming message.
+ bool* destroyed_flag_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Connector);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CONNECTOR_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/filter_chain.cc b/chromium/mojo/public/cpp/bindings/lib/filter_chain.cc
new file mode 100644
index 00000000000..efd4ba19875
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/filter_chain.cc
@@ -0,0 +1,49 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/filter_chain.h"
+
+#include <assert.h>
+
+#include <algorithm>
+
+namespace mojo {
+namespace internal {
+
+FilterChain::FilterChain(MessageReceiver* sink) : sink_(sink) {
+}
+
+FilterChain::FilterChain(RValue other) : sink_(other.object->sink_) {
+ other.object->sink_ = NULL;
+ filters_.swap(other.object->filters_);
+}
+
+FilterChain& FilterChain::operator=(RValue other) {
+ std::swap(sink_, other.object->sink_);
+ filters_.swap(other.object->filters_);
+ return *this;
+}
+
+FilterChain::~FilterChain() {
+ for (std::vector<MessageFilter*>::iterator iter = filters_.begin();
+ iter != filters_.end();
+ ++iter) {
+ delete *iter;
+ }
+}
+
+void FilterChain::SetSink(MessageReceiver* sink) {
+ assert(!sink_);
+ sink_ = sink;
+ if (!filters_.empty())
+ filters_.back()->set_sink(sink);
+}
+
+MessageReceiver* FilterChain::GetHead() {
+ assert(sink_);
+ return filters_.empty() ? sink_ : filters_.front();
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/filter_chain.h b/chromium/mojo/public/cpp/bindings/lib/filter_chain.h
new file mode 100644
index 00000000000..8680f41aaee
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/filter_chain.h
@@ -0,0 +1,66 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_FILTER_CHAIN_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_FILTER_CHAIN_H_
+
+#include <vector>
+
+#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/bindings/message_filter.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+class FilterChain {
+ MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(FilterChain, RValue)
+
+ public:
+ // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while
+ // this object is alive.
+ explicit FilterChain(MessageReceiver* sink = NULL);
+
+ // Move-only constructor and operator=.
+ FilterChain(RValue other);
+ FilterChain& operator=(RValue other);
+
+ ~FilterChain();
+
+ template <typename FilterType>
+ inline void Append();
+
+ // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while
+ // this object is alive.
+ void SetSink(MessageReceiver* sink);
+
+ // Returns a receiver to accept messages. Messages flow through all filters in
+ // the same order as they were appended to the chain. If all filters allow a
+ // message to pass, it will be forwarded to |sink_|.
+ // The returned value is invalidated when this object goes away.
+ MessageReceiver* GetHead();
+
+ private:
+ // Owned by this object.
+ std::vector<MessageFilter*> filters_;
+
+ MessageReceiver* sink_;
+};
+
+template <typename FilterType>
+inline void FilterChain::Append() {
+ FilterType* filter = new FilterType(sink_);
+ if (!filters_.empty())
+ filters_.back()->set_sink(filter);
+ filters_.push_back(filter);
+}
+
+template <>
+inline void FilterChain::Append<PassThroughFilter>() {
+}
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_FILTER_CHAIN_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc
new file mode 100644
index 00000000000..5226231725c
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc
@@ -0,0 +1,53 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+
+namespace mojo {
+namespace internal {
+
+FixedBuffer::FixedBuffer(size_t size)
+ : ptr_(NULL),
+ cursor_(0),
+ size_(internal::Align(size)) {
+ // calloc() required to zero memory and thus avoid info leaks.
+ ptr_ = static_cast<char*>(calloc(size_, 1));
+}
+
+FixedBuffer::~FixedBuffer() {
+ free(ptr_);
+}
+
+void* FixedBuffer::Allocate(size_t delta) {
+ delta = internal::Align(delta);
+
+ if (delta == 0 || delta > size_ - cursor_) {
+ assert(false);
+ return NULL;
+ }
+
+ char* result = ptr_ + cursor_;
+ cursor_ += delta;
+
+ return result;
+}
+
+void* FixedBuffer::Leak() {
+ char* ptr = ptr_;
+ ptr_ = NULL;
+ cursor_ = 0;
+ size_ = 0;
+ return ptr;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h
new file mode 100644
index 00000000000..a3515a2ae86
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h
@@ -0,0 +1,67 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_
+
+#include "mojo/public/cpp/bindings/lib/buffer.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+// FixedBuffer provides a simple way to allocate objects within a fixed chunk
+// of memory. Objects are allocated by calling the |Allocate| method, which
+// extends the buffer accordingly. Objects allocated in this way are not freed
+// explicitly. Instead, they remain valid so long as the FixedBuffer remains
+// valid. The Leak method may be used to steal the underlying memory from the
+// FixedBuffer.
+//
+// Typical usage:
+//
+// {
+// FixedBuffer buf(8 + 8);
+//
+// int* a = static_cast<int*>(buf->Allocate(sizeof(int)));
+// *a = 2;
+//
+// double* b = static_cast<double*>(buf->Allocate(sizeof(double)));
+// *b = 3.14f;
+//
+// void* data = buf.Leak();
+// Process(data);
+//
+// free(data);
+// }
+//
+class FixedBuffer : public Buffer {
+ public:
+ explicit FixedBuffer(size_t size);
+ virtual ~FixedBuffer();
+
+ // Grows the buffer by |num_bytes| and returns a pointer to the start of the
+ // addition. The resulting address is 8-byte aligned, and the content of the
+ // memory is zero-filled.
+ virtual void* Allocate(size_t num_bytes) MOJO_OVERRIDE;
+
+ size_t size() const { return size_; }
+
+ // Returns the internal memory owned by the Buffer to the caller. The Buffer
+ // relinquishes its pointer, effectively resetting the state of the Buffer
+ // and leaving the caller responsible for freeing the returned memory address
+ // when no longer needed.
+ void* Leak();
+
+ private:
+ char* ptr_;
+ size_t cursor_;
+ size_t size_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(FixedBuffer);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/interface_impl_internal.h b/chromium/mojo/public/cpp/bindings/lib/interface_impl_internal.h
new file mode 100644
index 00000000000..f2cc4f0c5b6
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/interface_impl_internal.h
@@ -0,0 +1,94 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
+
+#include "mojo/public/cpp/bindings/error_handler.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/lib/filter_chain.h"
+#include "mojo/public/cpp/bindings/lib/message_header_validator.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename Interface>
+class InterfaceImplBase : public Interface {
+ public:
+ virtual ~InterfaceImplBase() {}
+ virtual void OnConnectionEstablished() = 0;
+ virtual void OnConnectionError() = 0;
+};
+
+template <typename Interface>
+class InterfaceImplState : public ErrorHandler {
+ public:
+ typedef typename Interface::Client Client;
+
+ explicit InterfaceImplState(InterfaceImplBase<Interface>* instance)
+ : router_(NULL),
+ proxy_(NULL) {
+ assert(instance);
+ stub_.set_sink(instance);
+ }
+
+ virtual ~InterfaceImplState() {
+ delete proxy_;
+ if (router_) {
+ router_->set_error_handler(NULL);
+ delete router_;
+ }
+ }
+
+ void BindProxy(
+ InterfacePtr<Interface>* ptr,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ MessagePipe pipe;
+ ptr->Bind(pipe.handle0.Pass(), waiter);
+ Bind(pipe.handle1.Pass(), waiter);
+ }
+
+ void Bind(ScopedMessagePipeHandle handle,
+ const MojoAsyncWaiter* waiter) {
+ assert(!router_);
+
+ FilterChain filters;
+ filters.Append<MessageHeaderValidator>();
+ filters.Append<typename Interface::RequestValidator_>();
+ filters.Append<typename Interface::Client::ResponseValidator_>();
+
+ router_ = new Router(handle.Pass(), filters.Pass(), waiter);
+ router_->set_incoming_receiver(&stub_);
+ router_->set_error_handler(this);
+
+ proxy_ = new typename Client::Proxy_(router_);
+
+ instance()->OnConnectionEstablished();
+ }
+
+ Router* router() { return router_; }
+ Client* client() { return proxy_; }
+
+ private:
+ InterfaceImplBase<Interface>* instance() {
+ return static_cast<InterfaceImplBase<Interface>*>(stub_.sink());
+ }
+
+ virtual void OnConnectionError() MOJO_OVERRIDE {
+ instance()->OnConnectionError();
+ }
+
+ Router* router_;
+ typename Client::Proxy_* proxy_;
+ typename Interface::Stub_ stub_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(InterfaceImplState);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/interface_ptr_internal.h b/chromium/mojo/public/cpp/bindings/lib/interface_ptr_internal.h
new file mode 100644
index 00000000000..a318d6185c5
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/interface_ptr_internal.h
@@ -0,0 +1,84 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "mojo/public/cpp/bindings/lib/filter_chain.h"
+#include "mojo/public/cpp/bindings/lib/message_header_validator.h"
+#include "mojo/public/cpp/bindings/lib/router.h"
+#include "mojo/public/cpp/environment/environment.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename Interface>
+class InterfacePtrState {
+ public:
+ InterfacePtrState() : proxy_(NULL), router_(NULL) {}
+
+ ~InterfacePtrState() {
+ // Destruction order matters here. We delete |proxy_| first, even though
+ // |router_| may have a reference to it, so that |~Interface| may have a
+ // shot at generating new outbound messages (ie, invoking client methods).
+ delete proxy_;
+ delete router_;
+ }
+
+ Interface* instance() const { return proxy_; }
+
+ Router* router() const { return router_; }
+
+ void Swap(InterfacePtrState* other) {
+ std::swap(other->proxy_, proxy_);
+ std::swap(other->router_, router_);
+ }
+
+ void ConfigureProxy(
+ ScopedMessagePipeHandle handle,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
+ assert(!proxy_);
+ assert(!router_);
+
+ FilterChain filters;
+ filters.Append<MessageHeaderValidator>();
+ filters.Append<typename Interface::Client::RequestValidator_>();
+ filters.Append<typename Interface::ResponseValidator_>();
+
+ router_ = new Router(handle.Pass(), filters.Pass(), waiter);
+ ProxyWithStub* proxy = new ProxyWithStub(router_);
+ router_->set_incoming_receiver(&proxy->stub);
+
+ proxy_ = proxy;
+ }
+
+ void set_client(typename Interface::Client* client) {
+ assert(proxy_);
+ proxy_->stub.set_sink(client);
+ }
+
+ private:
+ class ProxyWithStub : public Interface::Proxy_ {
+ public:
+ explicit ProxyWithStub(MessageReceiverWithResponder* receiver)
+ : Interface::Proxy_(receiver) {
+ }
+ typename Interface::Client::Stub_ stub;
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ProxyWithStub);
+ };
+
+ ProxyWithStub* proxy_;
+ Router* router_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(InterfacePtrState);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/message.cc b/chromium/mojo/public/cpp/bindings/lib/message.cc
new file mode 100644
index 00000000000..78017c00793
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message.cc
@@ -0,0 +1,81 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/message.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <algorithm>
+
+namespace mojo {
+
+Message::Message()
+ : data_num_bytes_(0),
+ data_(NULL) {
+}
+
+Message::~Message() {
+ free(data_);
+
+ for (std::vector<Handle>::iterator it = handles_.begin();
+ it != handles_.end(); ++it) {
+ if (it->is_valid())
+ CloseRaw(*it);
+ }
+}
+
+void Message::AllocUninitializedData(uint32_t num_bytes) {
+ assert(!data_);
+ data_num_bytes_ = num_bytes;
+ data_ = static_cast<internal::MessageData*>(malloc(num_bytes));
+}
+
+void Message::AdoptData(uint32_t num_bytes, internal::MessageData* data) {
+ assert(!data_);
+ data_num_bytes_ = num_bytes;
+ data_ = data;
+}
+
+void Message::Swap(Message* other) {
+ std::swap(data_num_bytes_, other->data_num_bytes_);
+ std::swap(data_, other->data_);
+ std::swap(handles_, other->handles_);
+}
+
+MojoResult ReadAndDispatchMessage(MessagePipeHandle handle,
+ MessageReceiver* receiver,
+ bool* receiver_result) {
+ MojoResult rv;
+
+ uint32_t num_bytes = 0, num_handles = 0;
+ rv = ReadMessageRaw(handle,
+ NULL,
+ &num_bytes,
+ NULL,
+ &num_handles,
+ MOJO_READ_MESSAGE_FLAG_NONE);
+ if (rv != MOJO_RESULT_RESOURCE_EXHAUSTED)
+ return rv;
+
+ Message message;
+ message.AllocUninitializedData(num_bytes);
+ message.mutable_handles()->resize(num_handles);
+
+ rv = ReadMessageRaw(handle,
+ message.mutable_data(),
+ &num_bytes,
+ message.mutable_handles()->empty()
+ ? NULL
+ : reinterpret_cast<MojoHandle*>(
+ &message.mutable_handles()->front()),
+ &num_handles,
+ MOJO_READ_MESSAGE_FLAG_NONE);
+ if (receiver && rv == MOJO_RESULT_OK)
+ *receiver_result = receiver->Accept(&message);
+
+ return rv;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_builder.cc b/chromium/mojo/public/cpp/bindings/lib/message_builder.cc
new file mode 100644
index 00000000000..c7466444d04
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message_builder.cc
@@ -0,0 +1,52 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/message_builder.h"
+
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename Header>
+void Allocate(Buffer* buf, Header** header) {
+ *header = static_cast<Header*>(buf->Allocate(sizeof(Header)));
+ (*header)->num_bytes = sizeof(Header);
+}
+
+MessageBuilder::MessageBuilder(uint32_t name, size_t payload_size)
+ : buf_(sizeof(MessageHeader) + payload_size) {
+ MessageHeader* header;
+ Allocate(&buf_, &header);
+ header->num_fields = 2;
+ header->name = name;
+}
+
+MessageBuilder::~MessageBuilder() {
+}
+
+void MessageBuilder::Finish(Message* message) {
+ uint32_t num_bytes = static_cast<uint32_t>(buf_.size());
+ message->AdoptData(num_bytes, static_cast<MessageData*>(buf_.Leak()));
+}
+
+MessageBuilder::MessageBuilder(size_t size)
+ : buf_(size) {
+}
+
+MessageWithRequestIDBuilder::MessageWithRequestIDBuilder(uint32_t name,
+ size_t payload_size,
+ uint32_t flags,
+ uint64_t request_id)
+ : MessageBuilder(sizeof(MessageHeaderWithRequestID) + payload_size) {
+ MessageHeaderWithRequestID* header;
+ Allocate(&buf_, &header);
+ header->num_fields = 3;
+ header->name = name;
+ header->flags = flags;
+ header->request_id = request_id;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_builder.h b/chromium/mojo/public/cpp/bindings/lib/message_builder.h
new file mode 100644
index 00000000000..b4988ff9cb9
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message_builder.h
@@ -0,0 +1,63 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_
+
+#include <stdint.h>
+
+#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
+#include "mojo/public/cpp/bindings/lib/message_internal.h"
+
+namespace mojo {
+class Message;
+
+namespace internal {
+
+class MessageBuilder {
+ public:
+ MessageBuilder(uint32_t name, size_t payload_size);
+ ~MessageBuilder();
+
+ Buffer* buffer() { return &buf_; }
+
+ // Call Finish when done making allocations in |buffer()|. Upon return,
+ // |message| will contain the message data, and |buffer()| will no longer be
+ // valid to reference.
+ void Finish(Message* message);
+
+ protected:
+ explicit MessageBuilder(size_t size);
+ FixedBuffer buf_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(MessageBuilder);
+};
+
+class MessageWithRequestIDBuilder : public MessageBuilder {
+ public:
+ MessageWithRequestIDBuilder(uint32_t name, size_t payload_size,
+ uint32_t flags, uint64_t request_id);
+};
+
+class RequestMessageBuilder : public MessageWithRequestIDBuilder {
+ public:
+ RequestMessageBuilder(uint32_t name, size_t payload_size)
+ : MessageWithRequestIDBuilder(name, payload_size, kMessageExpectsResponse,
+ 0) {
+ }
+};
+
+class ResponseMessageBuilder : public MessageWithRequestIDBuilder {
+ public:
+ ResponseMessageBuilder(uint32_t name, size_t payload_size,
+ uint64_t request_id)
+ : MessageWithRequestIDBuilder(name, payload_size, kMessageIsResponse,
+ request_id) {
+ }
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_filter.cc b/chromium/mojo/public/cpp/bindings/lib/message_filter.cc
new file mode 100644
index 00000000000..b09f40d8c5e
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message_filter.cc
@@ -0,0 +1,23 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/message_filter.h"
+
+namespace mojo {
+
+MessageFilter::MessageFilter(MessageReceiver* sink) : sink_(sink) {
+}
+
+MessageFilter::~MessageFilter() {
+}
+
+PassThroughFilter::PassThroughFilter(MessageReceiver* sink)
+ : MessageFilter(sink) {
+}
+
+bool PassThroughFilter::Accept(Message* message) {
+ return sink_->Accept(message);
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_header_validator.cc b/chromium/mojo/public/cpp/bindings/lib/message_header_validator.cc
new file mode 100644
index 00000000000..a55917afde5
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message_header_validator.cc
@@ -0,0 +1,81 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/message_header_validator.h"
+
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
+#include "mojo/public/cpp/bindings/lib/validation_errors.h"
+
+namespace mojo {
+namespace internal {
+namespace {
+
+bool IsValidMessageHeader(const MessageHeader* header) {
+ // NOTE: Our goal is to preserve support for future extension of the message
+ // header. If we encounter fields we do not understand, we must ignore them.
+
+ // Extra validation of the struct header:
+ if (header->num_fields == 2) {
+ if (header->num_bytes != sizeof(MessageHeader)) {
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
+ return false;
+ }
+ } else if (header->num_fields == 3) {
+ if (header->num_bytes != sizeof(MessageHeaderWithRequestID)) {
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
+ return false;
+ }
+ } else if (header->num_fields > 3) {
+ if (header->num_bytes < sizeof(MessageHeaderWithRequestID)) {
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
+ return false;
+ }
+ }
+
+ // Validate flags (allow unknown bits):
+
+ // These flags require a RequestID.
+ if (header->num_fields < 3 &&
+ ((header->flags & kMessageExpectsResponse) ||
+ (header->flags & kMessageIsResponse))) {
+ ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID);
+ return false;
+ }
+
+ // These flags are mutually exclusive.
+ if ((header->flags & kMessageExpectsResponse) &&
+ (header->flags & kMessageIsResponse)) {
+ ReportValidationError(
+ VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+MessageHeaderValidator::MessageHeaderValidator(MessageReceiver* sink)
+ : MessageFilter(sink) {
+}
+
+bool MessageHeaderValidator::Accept(Message* message) {
+ // Pass 0 as number of handles because we don't expect any in the header, even
+ // if |message| contains handles.
+ BoundsChecker bounds_checker(message->data(), message->data_num_bytes(), 0);
+
+ if (!ValidateStructHeader(message->data(), sizeof(MessageHeader), 2,
+ &bounds_checker)) {
+ return false;
+ }
+
+ if (!IsValidMessageHeader(message->header()))
+ return false;
+
+ return sink_->Accept(message);
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_header_validator.h b/chromium/mojo/public/cpp/bindings/lib/message_header_validator.h
new file mode 100644
index 00000000000..c3f43a07fbc
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message_header_validator.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_HEADER_VALIDATOR_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_HEADER_VALIDATOR_H_
+
+#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/bindings/message_filter.h"
+
+namespace mojo {
+namespace internal {
+
+class MessageHeaderValidator : public MessageFilter {
+ public:
+ explicit MessageHeaderValidator(MessageReceiver* sink = NULL);
+
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_HEADER_VALIDATOR_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_internal.h b/chromium/mojo/public/cpp/bindings/lib/message_internal.h
new file mode 100644
index 00000000000..3c67902b7a8
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message_internal.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_
+
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+
+namespace mojo {
+namespace internal {
+
+#pragma pack(push, 1)
+
+enum {
+ kMessageExpectsResponse = 1 << 0,
+ kMessageIsResponse = 1 << 1
+};
+
+struct MessageHeader : internal::StructHeader {
+ uint32_t name;
+ uint32_t flags;
+};
+MOJO_COMPILE_ASSERT(sizeof(MessageHeader) == 16, bad_sizeof_MessageHeader);
+
+struct MessageHeaderWithRequestID : MessageHeader {
+ uint64_t request_id;
+};
+MOJO_COMPILE_ASSERT(sizeof(MessageHeaderWithRequestID) == 24,
+ bad_sizeof_MessageHeaderWithRequestID);
+
+struct MessageData {
+ MessageHeader header;
+};
+
+MOJO_COMPILE_ASSERT(sizeof(MessageData) == sizeof(MessageHeader),
+ bad_sizeof_MessageData);
+
+#pragma pack(pop)
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_queue.cc b/chromium/mojo/public/cpp/bindings/lib/message_queue.cc
new file mode 100644
index 00000000000..1982ccb14c2
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message_queue.cc
@@ -0,0 +1,50 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/message_queue.h"
+
+#include <assert.h>
+#include <stddef.h>
+
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace mojo {
+namespace internal {
+
+MessageQueue::MessageQueue() {
+}
+
+MessageQueue::~MessageQueue() {
+ while (!queue_.empty())
+ Pop();
+}
+
+bool MessageQueue::IsEmpty() const {
+ return queue_.empty();
+}
+
+Message* MessageQueue::Peek() {
+ assert(!queue_.empty());
+ return queue_.front();
+}
+
+void MessageQueue::Push(Message* message) {
+ queue_.push(new Message());
+ queue_.back()->Swap(message);
+}
+
+void MessageQueue::Pop(Message* message) {
+ assert(!queue_.empty());
+ queue_.front()->Swap(message);
+ Pop();
+}
+
+void MessageQueue::Pop() {
+ assert(!queue_.empty());
+ delete queue_.front();
+ queue_.pop();
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_queue.h b/chromium/mojo/public/cpp/bindings/lib/message_queue.h
new file mode 100644
index 00000000000..4e46b54a250
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message_queue.h
@@ -0,0 +1,47 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_QUEUE_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_QUEUE_H_
+
+#include <queue>
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+class Message;
+
+namespace internal {
+
+// A queue for Message objects.
+class MessageQueue {
+ public:
+ MessageQueue();
+ ~MessageQueue();
+
+ bool IsEmpty() const;
+ Message* Peek();
+
+ // This method transfers ownership of |message->data| and |message->handles|
+ // to the message queue, resetting |message| in the process.
+ void Push(Message* message);
+
+ // Removes the next message from the queue, transferring ownership of its
+ // data and handles to the given |message|.
+ void Pop(Message* message);
+
+ // Removes the next message from the queue, discarding its data and handles.
+ // This is meant to be used in conjunction with |Peek|.
+ void Pop();
+
+ private:
+ std::queue<Message*> queue_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(MessageQueue);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_QUEUE_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/no_interface.cc b/chromium/mojo/public/cpp/bindings/lib/no_interface.cc
new file mode 100644
index 00000000000..9e0945c83b3
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/no_interface.cc
@@ -0,0 +1,20 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/no_interface.h"
+
+namespace mojo {
+
+const char* NoInterface::Name_ = "mojo::NoInterface";
+
+bool NoInterfaceStub::Accept(Message* message) {
+ return false;
+}
+
+bool NoInterfaceStub::AcceptWithResponder(Message* message,
+ MessageReceiver* responder) {
+ return false;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/router.cc b/chromium/mojo/public/cpp/bindings/lib/router.cc
new file mode 100644
index 00000000000..a8222203c47
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/router.cc
@@ -0,0 +1,140 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/router.h"
+
+namespace mojo {
+namespace internal {
+
+// ----------------------------------------------------------------------------
+
+class ResponderThunk : public MessageReceiver {
+ public:
+ explicit ResponderThunk(const SharedData<Router*>& router)
+ : router_(router) {
+ }
+ virtual ~ResponderThunk() {
+ }
+
+ // MessageReceiver implementation:
+ virtual bool Accept(Message* message) MOJO_OVERRIDE {
+ assert(message->has_flag(kMessageIsResponse));
+
+ bool result = false;
+
+ Router* router = router_.value();
+ if (router)
+ result = router->Accept(message);
+
+ return result;
+ }
+
+ private:
+ SharedData<Router*> router_;
+};
+
+// ----------------------------------------------------------------------------
+
+Router::HandleIncomingMessageThunk::HandleIncomingMessageThunk(Router* router)
+ : router_(router) {
+}
+
+Router::HandleIncomingMessageThunk::~HandleIncomingMessageThunk() {
+}
+
+bool Router::HandleIncomingMessageThunk::Accept(Message* message) {
+ return router_->HandleIncomingMessage(message);
+}
+
+// ----------------------------------------------------------------------------
+
+Router::Router(ScopedMessagePipeHandle message_pipe,
+ FilterChain filters,
+ const MojoAsyncWaiter* waiter)
+ : thunk_(this),
+ filters_(filters.Pass()),
+ connector_(message_pipe.Pass(), waiter),
+ weak_self_(this),
+ incoming_receiver_(NULL),
+ next_request_id_(0),
+ testing_mode_(false) {
+ filters_.SetSink(&thunk_);
+ connector_.set_incoming_receiver(filters_.GetHead());
+}
+
+Router::~Router() {
+ weak_self_.set_value(NULL);
+
+ for (ResponderMap::const_iterator i = responders_.begin();
+ i != responders_.end(); ++i) {
+ delete i->second;
+ }
+}
+
+bool Router::Accept(Message* message) {
+ assert(!message->has_flag(kMessageExpectsResponse));
+ return connector_.Accept(message);
+}
+
+bool Router::AcceptWithResponder(Message* message,
+ MessageReceiver* responder) {
+ assert(message->has_flag(kMessageExpectsResponse));
+
+ // Reserve 0 in case we want it to convey special meaning in the future.
+ uint64_t request_id = next_request_id_++;
+ if (request_id == 0)
+ request_id = next_request_id_++;
+
+ message->set_request_id(request_id);
+ if (!connector_.Accept(message))
+ return false;
+
+ // We assume ownership of |responder|.
+ responders_[request_id] = responder;
+ return true;
+}
+
+void Router::EnableTestingMode() {
+ testing_mode_ = true;
+ connector_.set_enforce_errors_from_incoming_receiver(false);
+}
+
+bool Router::HandleIncomingMessage(Message* message) {
+ if (message->has_flag(kMessageExpectsResponse)) {
+ if (incoming_receiver_) {
+ MessageReceiver* responder = new ResponderThunk(weak_self_);
+ bool ok = incoming_receiver_->AcceptWithResponder(message, responder);
+ if (!ok)
+ delete responder;
+ return ok;
+ }
+
+ // If we receive a request expecting a response when the client is not
+ // listening, then we have no choice but to tear down the pipe.
+ connector_.CloseMessagePipe();
+ } else if (message->has_flag(kMessageIsResponse)) {
+ uint64_t request_id = message->request_id();
+ ResponderMap::iterator it = responders_.find(request_id);
+ if (it == responders_.end()) {
+ assert(testing_mode_);
+ return false;
+ }
+ MessageReceiver* responder = it->second;
+ responders_.erase(it);
+ bool ok = responder->Accept(message);
+ delete responder;
+ return ok;
+ } else {
+ if (incoming_receiver_)
+ return incoming_receiver_->Accept(message);
+ // OK to drop message on the floor.
+ }
+
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/router.h b/chromium/mojo/public/cpp/bindings/lib/router.h
new file mode 100644
index 00000000000..76bf1471e2e
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/router.h
@@ -0,0 +1,91 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ROUTER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ROUTER_H_
+
+#include <map>
+
+#include "mojo/public/cpp/bindings/lib/connector.h"
+#include "mojo/public/cpp/bindings/lib/filter_chain.h"
+#include "mojo/public/cpp/bindings/lib/shared_data.h"
+#include "mojo/public/cpp/environment/environment.h"
+
+namespace mojo {
+namespace internal {
+
+class Router : public MessageReceiverWithResponder {
+ public:
+ Router(ScopedMessagePipeHandle message_pipe,
+ FilterChain filters,
+ const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter());
+ virtual ~Router();
+
+ // Sets the receiver to handle messages read from the message pipe that do
+ // not have the kMessageIsResponse flag set.
+ void set_incoming_receiver(MessageReceiverWithResponder* receiver) {
+ incoming_receiver_ = receiver;
+ }
+
+ // Sets the error handler to receive notifications when an error is
+ // encountered while reading from the pipe or waiting to read from the pipe.
+ void set_error_handler(ErrorHandler* error_handler) {
+ connector_.set_error_handler(error_handler);
+ }
+
+ // Returns true if an error was encountered while reading from the pipe or
+ // waiting to read from the pipe.
+ bool encountered_error() const { return connector_.encountered_error(); }
+
+ void CloseMessagePipe() {
+ connector_.CloseMessagePipe();
+ }
+
+ ScopedMessagePipeHandle PassMessagePipe() {
+ return connector_.PassMessagePipe();
+ }
+
+ // MessageReceiver implementation:
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+ virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
+ MOJO_OVERRIDE;
+
+ // Sets this object to testing mode.
+ // In testing mode:
+ // - the object is more tolerant of unrecognized response messages;
+ // - the connector continues working after seeing errors from its incoming
+ // receiver.
+ void EnableTestingMode();
+
+ private:
+ typedef std::map<uint64_t, MessageReceiver*> ResponderMap;
+
+ class HandleIncomingMessageThunk : public MessageReceiver {
+ public:
+ HandleIncomingMessageThunk(Router* router);
+ virtual ~HandleIncomingMessageThunk();
+
+ // MessageReceiver implementation:
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+
+ private:
+ Router* router_;
+ };
+
+ bool HandleIncomingMessage(Message* message);
+
+ HandleIncomingMessageThunk thunk_;
+ FilterChain filters_;
+ Connector connector_;
+ SharedData<Router*> weak_self_;
+ MessageReceiverWithResponder* incoming_receiver_;
+ ResponderMap responders_;
+ uint64_t next_request_id_;
+ bool testing_mode_;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ROUTER_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/shared_data.h b/chromium/mojo/public/cpp/bindings/lib/shared_data.h
new file mode 100644
index 00000000000..c7bd54f8d7c
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/shared_data.h
@@ -0,0 +1,84 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+// Used to allocate an instance of T that can be shared via reference counting.
+template <typename T>
+class SharedData {
+ public:
+ ~SharedData() {
+ holder_->Release();
+ }
+
+ SharedData() : holder_(new Holder()) {
+ }
+
+ explicit SharedData(const T& value) : holder_(new Holder(value)) {
+ }
+
+ SharedData(const SharedData<T>& other) : holder_(other.holder_) {
+ holder_->Retain();
+ }
+
+ SharedData<T>& operator=(const SharedData<T>& other) {
+ if (other.holder_ == holder_)
+ return *this;
+ holder_->Release();
+ holder_ = other.holder_;
+ holder_->Retain();
+ return *this;
+ }
+
+ void reset() {
+ holder_->Release();
+ holder_ = new Holder();
+ }
+
+ void reset(const T& value) {
+ holder_->Release();
+ holder_ = new Holder(value);
+ }
+
+ void set_value(const T& value) {
+ holder_->value = value;
+ }
+ T* mutable_value() {
+ return &holder_->value;
+ }
+ const T& value() const {
+ return holder_->value;
+ }
+
+ private:
+ class Holder {
+ public:
+ Holder() : value(), ref_count_(1) {
+ }
+ Holder(const T& value) : value(value), ref_count_(1) {
+ }
+
+ void Retain() { ++ref_count_; }
+ void Release() { if (--ref_count_ == 0) delete this; }
+
+ T value;
+
+ private:
+ int ref_count_;
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Holder);
+ };
+
+ Holder* holder_;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/shared_ptr.h b/chromium/mojo/public/cpp/bindings/lib/shared_ptr.h
new file mode 100644
index 00000000000..6ae53a5681a
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/shared_ptr.h
@@ -0,0 +1,63 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_PTR_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_PTR_H_
+
+#include "mojo/public/cpp/bindings/lib/shared_data.h"
+
+namespace mojo {
+namespace internal {
+
+// Used to manage a heap-allocated instance of P that can be shared via
+// reference counting. When the last reference is dropped, the instance is
+// deleted.
+template <typename P>
+class SharedPtr {
+ public:
+ SharedPtr() {}
+
+ explicit SharedPtr(P* ptr) {
+ impl_.mutable_value()->ptr = ptr;
+ }
+
+ // Default copy-constructor and assignment operator are OK.
+
+ P* get() {
+ return impl_.value().ptr;
+ }
+ const P* get() const {
+ return impl_.value().ptr;
+ }
+
+ P* operator->() { return get(); }
+ const P* operator->() const { return get(); }
+
+ private:
+ class Impl {
+ public:
+ ~Impl() {
+ if (ptr)
+ delete ptr;
+ }
+
+ Impl() : ptr(NULL) {
+ }
+
+ Impl(P* ptr) : ptr(ptr) {
+ }
+
+ P* ptr;
+
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Impl);
+ };
+
+ SharedData<Impl> impl_;
+};
+
+} // namespace mojo
+} // namespace internal
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_PTR_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/string_serialization.cc b/chromium/mojo/public/cpp/bindings/lib/string_serialization.cc
new file mode 100644
index 00000000000..0044b1b9cff
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/string_serialization.cc
@@ -0,0 +1,38 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/string_serialization.h"
+
+#include <string.h>
+
+namespace mojo {
+
+size_t GetSerializedSize_(const String& input) {
+ if (!input)
+ return 0;
+ return internal::Align(sizeof(internal::String_Data) + input.size());
+}
+
+void Serialize_(const String& input, internal::Buffer* buf,
+ internal::String_Data** output) {
+ if (input) {
+ internal::String_Data* result =
+ internal::String_Data::New(input.size(), buf);
+ memcpy(result->storage(), input.data(), input.size());
+ *output = result;
+ } else {
+ *output = NULL;
+ }
+}
+
+void Deserialize_(internal::String_Data* input, String* output) {
+ if (input) {
+ String result(input->storage(), input->size());
+ result.Swap(output);
+ } else {
+ output->reset();
+ }
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/string_serialization.h b/chromium/mojo/public/cpp/bindings/lib/string_serialization.h
new file mode 100644
index 00000000000..bad2a0c2766
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/string_serialization.h
@@ -0,0 +1,20 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/string.h"
+
+namespace mojo {
+
+size_t GetSerializedSize_(const String& input);
+void Serialize_(const String& input, internal::Buffer* buffer,
+ internal::String_Data** output);
+void Deserialize_(internal::String_Data* input, String* output);
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_dispatcher.cc b/chromium/mojo/public/cpp/bindings/lib/sync_dispatcher.cc
new file mode 100644
index 00000000000..2cde97f6ee4
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/sync_dispatcher.cc
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/sync_dispatcher.h"
+
+#include <stdlib.h>
+
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace mojo {
+
+bool WaitForMessageAndDispatch(MessagePipeHandle handle,
+ MessageReceiver* receiver) {
+ while (true) {
+ bool result;
+ MojoResult rv = ReadAndDispatchMessage(handle, receiver, &result);
+ if (rv == MOJO_RESULT_OK)
+ return result;
+ if (rv == MOJO_RESULT_SHOULD_WAIT)
+ rv = Wait(handle, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE);
+ if (rv != MOJO_RESULT_OK)
+ return false;
+ }
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/template_util.h b/chromium/mojo/public/cpp/bindings/lib/template_util.h
new file mode 100644
index 00000000000..599126691ed
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/template_util.h
@@ -0,0 +1,89 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_
+
+namespace mojo {
+namespace internal {
+
+template<class T, T v>
+struct IntegralConstant {
+ static const T value = v;
+};
+
+template <class T, T v> const T IntegralConstant<T, v>::value;
+
+typedef IntegralConstant<bool, true> TrueType;
+typedef IntegralConstant<bool, false> FalseType;
+
+template <class T> struct IsConst : FalseType {};
+template <class T> struct IsConst<const T> : TrueType {};
+
+template<bool B, typename T = void>
+struct EnableIf {};
+
+template<typename T>
+struct EnableIf<true, T> { typedef T type; };
+
+// Types YesType and NoType are guaranteed such that sizeof(YesType) <
+// sizeof(NoType).
+typedef char YesType;
+
+struct NoType {
+ YesType dummy[2];
+};
+
+// A helper template to determine if given type is non-const move-only-type,
+// i.e. if a value of the given type should be passed via .Pass() in a
+// destructive way.
+template <typename T> struct IsMoveOnlyType {
+ template <typename U>
+ static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
+
+ template <typename U>
+ static NoType Test(...);
+
+ static const bool value = sizeof(Test<T>(0)) == sizeof(YesType) &&
+ !IsConst<T>::value;
+};
+
+template <typename T>
+typename EnableIf<!IsMoveOnlyType<T>::value, T>::type& Forward(T& t) {
+ return t;
+}
+
+template <typename T>
+typename EnableIf<IsMoveOnlyType<T>::value, T>::type Forward(T& t) {
+ return t.Pass();
+}
+
+// This goop is a trick used to implement a template that can be used to
+// determine if a given class is the base class of another given class.
+template<typename, typename> struct IsSame {
+ static bool const value = false;
+};
+template<typename A> struct IsSame<A, A> {
+ static bool const value = true;
+};
+template<typename Base, typename Derived> struct IsBaseOf {
+ private:
+ // This class doesn't work correctly with forward declarations.
+ // Because sizeof cannot be applied to incomplete types, this line prevents us
+ // from passing in forward declarations.
+ typedef char (*EnsureTypesAreComplete)[sizeof(Base) + sizeof(Derived)];
+
+ static Derived* CreateDerived();
+ static char (&Check(Base*))[1];
+ static char (&Check(...))[2];
+
+ public:
+ static bool const value = sizeof Check(CreateDerived()) == 1 &&
+ !IsSame<Base const, void const>::value;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/validation_errors.cc b/chromium/mojo/public/cpp/bindings/lib/validation_errors.cc
new file mode 100644
index 00000000000..ed5904d3963
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/validation_errors.cc
@@ -0,0 +1,64 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/lib/validation_errors.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+namespace mojo {
+namespace internal {
+namespace {
+
+ValidationErrorObserverForTesting* g_validation_error_observer = NULL;
+
+} // namespace
+
+const char* ValidationErrorToString(ValidationError error) {
+ switch (error) {
+ case VALIDATION_ERROR_NONE:
+ return "VALIDATION_ERROR_NONE";
+ case VALIDATION_ERROR_MISALIGNED_OBJECT:
+ return "VALIDATION_ERROR_MISALIGNED_OBJECT";
+ case VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE:
+ return "VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE";
+ case VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER:
+ return "VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER";
+ case VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER:
+ return "VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER";
+ case VALIDATION_ERROR_ILLEGAL_HANDLE:
+ return "VALIDATION_ERROR_ILLEGAL_HANDLE";
+ case VALIDATION_ERROR_ILLEGAL_POINTER:
+ return "VALIDATION_ERROR_ILLEGAL_POINTER";
+ case VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION:
+ return "VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION";
+ case VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID:
+ return "VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID";
+ }
+
+ return "Unknown error";
+}
+
+void ReportValidationError(ValidationError error) {
+ if (g_validation_error_observer) {
+ g_validation_error_observer->set_last_error(error);
+ } else {
+ // TODO(yzshen): Consider adding better logging support.
+ fprintf(stderr, "Invalid message: %s\n", ValidationErrorToString(error));
+ }
+}
+
+ValidationErrorObserverForTesting::ValidationErrorObserverForTesting()
+ : last_error_(VALIDATION_ERROR_NONE) {
+ assert(!g_validation_error_observer);
+ g_validation_error_observer = this;
+}
+
+ValidationErrorObserverForTesting::~ValidationErrorObserverForTesting() {
+ assert(g_validation_error_observer == this);
+ g_validation_error_observer = NULL;
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/validation_errors.h b/chromium/mojo/public/cpp/bindings/lib/validation_errors.h
new file mode 100644
index 00000000000..9b443c371e5
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/validation_errors.h
@@ -0,0 +1,66 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+enum ValidationError {
+ // There is no validation error.
+ VALIDATION_ERROR_NONE,
+ // An object (struct or array) is not 8-byte aligned.
+ VALIDATION_ERROR_MISALIGNED_OBJECT,
+ // An object is not contained inside the message data, or it overlaps other
+ // objects.
+ VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE,
+ // A struct header doesn't make sense, for example:
+ // - |num_bytes| is smaller than the size of the oldest version that we
+ // support.
+ // - |num_fields| is smaller than the field number of the oldest version that
+ // we support.
+ // - |num_bytes| and |num_fields| don't match.
+ VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER,
+ // An array header doesn't make sense, for example:
+ // - |num_bytes| is smaller than the size of the header plus the size required
+ // to store |num_elements| elements.
+ VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
+ // An encoded handle is illegal.
+ VALIDATION_ERROR_ILLEGAL_HANDLE,
+ // An encoded pointer is illegal.
+ VALIDATION_ERROR_ILLEGAL_POINTER,
+ // |flags| in the message header is an invalid flag combination.
+ VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION,
+ // |flags| in the message header indicates that a request ID is required but
+ // there isn't one.
+ VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID,
+};
+
+const char* ValidationErrorToString(ValidationError error);
+
+void ReportValidationError(ValidationError error);
+
+// Only used by validation tests and when there is only one thread doing message
+// validation.
+class ValidationErrorObserverForTesting {
+ public:
+ ValidationErrorObserverForTesting();
+ ~ValidationErrorObserverForTesting();
+
+ ValidationError last_error() const { return last_error_; }
+ void set_last_error(ValidationError error) { last_error_ = error; }
+
+ private:
+ ValidationError last_error_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ValidationErrorObserverForTesting);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_
diff --git a/chromium/mojo/public/cpp/bindings/message.h b/chromium/mojo/public/cpp/bindings/message.h
new file mode 100644
index 00000000000..beb1cd9036f
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/message.h
@@ -0,0 +1,123 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_
+
+#include <assert.h>
+
+#include <vector>
+
+#include "mojo/public/cpp/bindings/lib/message_internal.h"
+
+namespace mojo {
+
+// Message is a holder for the data and handles to be sent over a MessagePipe.
+// Message owns its data and handles, but a consumer of Message is free to
+// mutate the data and handles. The message's data is comprised of a header
+// followed by payload.
+class Message {
+ public:
+ Message();
+ ~Message();
+
+ // These may only be called on a newly created Message object.
+ void AllocUninitializedData(uint32_t num_bytes);
+ void AdoptData(uint32_t num_bytes, internal::MessageData* data);
+
+ // Swaps data and handles between this Message and another.
+ void Swap(Message* other);
+
+ uint32_t data_num_bytes() const { return data_num_bytes_; }
+
+ // Access the raw bytes of the message.
+ const uint8_t* data() const { return
+ reinterpret_cast<const uint8_t*>(data_);
+ }
+ uint8_t* mutable_data() { return reinterpret_cast<uint8_t*>(data_); }
+
+ // Access the header.
+ const internal::MessageHeader* header() const { return &data_->header; }
+
+ uint32_t name() const { return data_->header.name; }
+ bool has_flag(uint32_t flag) const { return !!(data_->header.flags & flag); }
+
+ // Access the request_id field (if present).
+ bool has_request_id() const { return data_->header.num_fields >= 3; }
+ uint64_t request_id() const {
+ assert(has_request_id());
+ return static_cast<const internal::MessageHeaderWithRequestID*>(
+ &data_->header)->request_id;
+ }
+ void set_request_id(uint64_t request_id) {
+ assert(has_request_id());
+ static_cast<internal::MessageHeaderWithRequestID*>(&data_->header)->
+ request_id = request_id;
+ }
+
+ // Access the payload.
+ const uint8_t* payload() const {
+ return reinterpret_cast<const uint8_t*>(data_) + data_->header.num_bytes;
+ }
+ uint8_t* mutable_payload() {
+ return reinterpret_cast<uint8_t*>(data_) + data_->header.num_bytes;
+ }
+ uint32_t payload_num_bytes() const {
+ assert(data_num_bytes_ >= data_->header.num_bytes);
+ return data_num_bytes_ - data_->header.num_bytes;
+ }
+
+ // Access the handles.
+ const std::vector<Handle>* handles() const { return &handles_; }
+ std::vector<Handle>* mutable_handles() { return &handles_; }
+
+ private:
+ uint32_t data_num_bytes_;
+ internal::MessageData* data_; // Heap-allocated using malloc.
+ std::vector<Handle> handles_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Message);
+};
+
+class MessageReceiver {
+ public:
+ virtual ~MessageReceiver() {}
+
+ // The receiver may mutate the given message. Returns true if the message
+ // was accepted and false otherwise, indicating that the message was invalid
+ // or malformed.
+ virtual bool Accept(Message* message) MOJO_WARN_UNUSED_RESULT = 0;
+};
+
+class MessageReceiverWithResponder : public MessageReceiver {
+ public:
+ virtual ~MessageReceiverWithResponder() {}
+
+ // A variant on Accept that registers a MessageReceiver (known as the
+ // responder) to handle the response message generated from the given
+ // message. The responder's Accept method may be called during
+ // AcceptWithResponder or some time after its return.
+ //
+ // NOTE: Upon returning true, AcceptWithResponder assumes ownership of
+ // |responder| and will delete it after calling |responder->Accept| or upon
+ // its own destruction.
+ //
+ virtual bool AcceptWithResponder(
+ Message* message, MessageReceiver* responder) MOJO_WARN_UNUSED_RESULT = 0;
+};
+
+// Read a single message from the pipe and dispatch to the given receiver. The
+// receiver may be null, in which case the message is simply discarded.
+// Returns MOJO_RESULT_SHOULD_WAIT if the caller should wait on the handle to
+// become readable. Returns MOJO_RESULT_OK if a message was dispatched and
+// otherwise returns an error code if something went wrong.
+//
+// NOTE: The message hasn't been validated and may be malformed!
+MojoResult ReadAndDispatchMessage(MessagePipeHandle handle,
+ MessageReceiver* receiver,
+ bool* receiver_result);
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_H_
diff --git a/chromium/mojo/public/cpp/bindings/message_filter.h b/chromium/mojo/public/cpp/bindings/message_filter.h
new file mode 100644
index 00000000000..6d716733ecc
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/message_filter.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_FILTER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_FILTER_H_
+
+#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+// This class is the base class for message filters. Subclasses should
+// implement the pure virtual method Accept() inherited from MessageReceiver to
+// process messages and/or forward them to |sink_|.
+class MessageFilter : public MessageReceiver {
+ public:
+ // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while
+ // this object is alive.
+ explicit MessageFilter(MessageReceiver* sink = NULL);
+ virtual ~MessageFilter();
+
+ void set_sink(MessageReceiver* sink) { sink_ = sink; }
+
+ protected:
+ MessageReceiver* sink_;
+};
+
+// A trivial filter that simply forwards every message it receives to |sink_|.
+class PassThroughFilter : public MessageFilter {
+ public:
+ explicit PassThroughFilter(MessageReceiver* sink = NULL);
+
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_FILTER_H_
diff --git a/chromium/mojo/public/cpp/bindings/no_interface.h b/chromium/mojo/public/cpp/bindings/no_interface.h
new file mode 100644
index 00000000000..83b0eff5000
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/no_interface.h
@@ -0,0 +1,56 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_NO_INTERFACE_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_NO_INTERFACE_H_
+
+#include <assert.h>
+
+#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/bindings/message_filter.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+// NoInterface is for use in cases when a non-existent or empty interface is
+// needed (e.g., when the Mojom "Peer" attribute is not present).
+
+class NoInterfaceProxy;
+class NoInterfaceStub;
+
+class NoInterface {
+ public:
+ static const char* Name_;
+ typedef NoInterfaceProxy Proxy_;
+ typedef NoInterfaceStub Stub_;
+ typedef PassThroughFilter RequestValidator_;
+ typedef PassThroughFilter ResponseValidator_;
+ typedef NoInterface Client;
+ virtual ~NoInterface() {}
+};
+
+class NoInterfaceProxy : public NoInterface {
+ public:
+ explicit NoInterfaceProxy(MessageReceiver* receiver) {}
+};
+
+class NoInterfaceStub : public MessageReceiverWithResponder {
+ public:
+ NoInterfaceStub() {}
+ void set_sink(NoInterface* sink) {}
+ NoInterface* sink() { return NULL; }
+ virtual bool Accept(Message* message) MOJO_OVERRIDE;
+ virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
+ MOJO_OVERRIDE;
+};
+
+
+// AnyInterface is for use in cases where any interface would do (e.g., see the
+// Shell::Connect method).
+
+typedef NoInterface AnyInterface;
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_NO_INTERFACE_H_
diff --git a/chromium/mojo/public/cpp/bindings/string.h b/chromium/mojo/public/cpp/bindings/string.h
new file mode 100644
index 00000000000..a2427844975
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/string.h
@@ -0,0 +1,154 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
+
+#include <assert.h>
+
+#include <string>
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/type_converter.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+class String {
+ public:
+ typedef internal::String_Data Data_;
+
+ String() : is_null_(true) {}
+ String(const std::string& str) : value_(str), is_null_(false) {}
+ String(const char* chars) : is_null_(!chars) {
+ if (chars)
+ value_ = chars;
+ }
+ String(const char* chars, size_t num_chars)
+ : value_(chars, num_chars),
+ is_null_(false) {
+ }
+ template <size_t N>
+ String(const char chars[N]) : value_(chars, N-1), is_null_(false) {}
+
+ template <typename U>
+ static String From(const U& other) {
+ return TypeConverter<String, U>::ConvertFrom(other);
+ }
+
+ template <typename U>
+ U To() const {
+ return TypeConverter<String, U>::ConvertTo(*this);
+ }
+
+ String& operator=(const std::string& str) {
+ value_ = str;
+ is_null_ = false;
+ return *this;
+ }
+ String& operator=(const char* chars) {
+ is_null_ = !chars;
+ if (chars) {
+ value_ = chars;
+ } else {
+ value_.clear();
+ }
+ return *this;
+ }
+
+ void reset() {
+ value_.clear();
+ is_null_ = true;
+ }
+
+ bool is_null() const { return is_null_; }
+
+ size_t size() const { return value_.size(); }
+
+ const char* data() const { return value_.data(); }
+
+ const char& at(size_t offset) const { return value_.at(offset); }
+ const char& operator[](size_t offset) const { return value_[offset]; }
+
+ const std::string& get() const { return value_; }
+ operator const std::string&() const { return value_; }
+
+ void Swap(String* other) {
+ std::swap(is_null_, other->is_null_);
+ value_.swap(other->value_);
+ }
+
+ void Swap(std::string* other) {
+ is_null_ = false;
+ value_.swap(*other);
+ }
+
+ private:
+ typedef std::string String::*Testable;
+
+ public:
+ operator Testable() const { return is_null_ ? 0 : &String::value_; }
+
+ private:
+ std::string value_;
+ bool is_null_;
+};
+
+inline bool operator==(const String& a, const String& b) {
+ return a.is_null() == b.is_null() && a.get() == b.get();
+}
+inline bool operator==(const char* a, const String& b) {
+ return !b.is_null() && a == b.get();
+}
+inline bool operator==(const String& a, const char* b) {
+ return !a.is_null() && a.get() == b;
+}
+inline bool operator!=(const String& a, const String& b) { return !(a == b); }
+inline bool operator!=(const char* a, const String& b) { return !(a == b); }
+inline bool operator!=(const String& a, const char* b) { return !(a == b); }
+
+// TODO(darin): Add similar variants of operator<,<=,>,>=
+
+template <>
+class TypeConverter<String, std::string> {
+ public:
+ static String ConvertFrom(const std::string& input) {
+ return String(input);
+ }
+ static std::string ConvertTo(const String& input) {
+ return input;
+ }
+};
+
+template <size_t N>
+class TypeConverter<String, char[N]> {
+ public:
+ static String ConvertFrom(const char input[N]) {
+ assert(input);
+ return String(input, N-1);
+ }
+};
+
+// Appease MSVC.
+template <size_t N>
+class TypeConverter<String, const char[N]> {
+ public:
+ static String ConvertFrom(const char input[N]) {
+ assert(input);
+ return String(input, N-1);
+ }
+};
+
+template <>
+class TypeConverter<String, const char*> {
+ public:
+ // |input| may be null, in which case a null String will be returned.
+ static String ConvertFrom(const char* input) {
+ return String(input);
+ }
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
diff --git a/chromium/mojo/public/cpp/bindings/struct_ptr.h b/chromium/mojo/public/cpp/bindings/struct_ptr.h
new file mode 100644
index 00000000000..a4e55e758f4
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/struct_ptr.h
@@ -0,0 +1,154 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
+
+#include <assert.h>
+
+#include <new>
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename Struct>
+class StructHelper {
+ public:
+ template <typename Ptr>
+ static void Initialize(Ptr* ptr) { ptr->Initialize(); }
+};
+
+} // namespace internal
+
+template <typename Struct>
+class StructPtr {
+ MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(StructPtr, RValue);
+ public:
+ typedef typename Struct::Data_ Data_;
+
+ StructPtr() : ptr_(NULL) {}
+ ~StructPtr() {
+ delete ptr_;
+ }
+
+ StructPtr(RValue other) : ptr_(NULL) { Take(other.object); }
+ StructPtr& operator=(RValue other) {
+ Take(other.object);
+ return *this;
+ }
+
+ template <typename U>
+ U To() const {
+ return TypeConverter<StructPtr, U>::ConvertTo(*this);
+ }
+
+ void reset() {
+ if (ptr_) {
+ delete ptr_;
+ ptr_ = NULL;
+ }
+ }
+
+ bool is_null() const { return ptr_ == NULL; }
+
+ Struct& operator*() const {
+ assert(ptr_);
+ return *ptr_;
+ }
+ Struct* operator->() const {
+ assert(ptr_);
+ return ptr_;
+ }
+ Struct* get() const { return ptr_; }
+
+ void Swap(StructPtr* other) {
+ std::swap(ptr_, other->ptr_);
+ }
+
+ private:
+ typedef Struct* StructPtr::*Testable;
+
+ public:
+ operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; }
+
+ private:
+ friend class internal::StructHelper<Struct>;
+ void Initialize() { assert(!ptr_); ptr_ = new Struct(); }
+
+ void Take(StructPtr* other) {
+ reset();
+ Swap(other);
+ }
+
+ Struct* ptr_;
+};
+
+// Designed to be used when Struct is small and copyable.
+template <typename Struct>
+class InlinedStructPtr {
+ MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InlinedStructPtr, RValue);
+ public:
+ typedef typename Struct::Data_ Data_;
+
+ InlinedStructPtr() : is_null_(true) {}
+ ~InlinedStructPtr() {}
+
+ InlinedStructPtr(RValue other) : is_null_(true) { Take(other.object); }
+ InlinedStructPtr& operator=(RValue other) {
+ Take(other.object);
+ return *this;
+ }
+
+ template <typename U>
+ U To() const {
+ return TypeConverter<InlinedStructPtr, U>::ConvertTo(*this);
+ }
+
+ void reset() {
+ is_null_ = true;
+ value_.~Struct();
+ new (&value_) Struct();
+ }
+
+ bool is_null() const { return is_null_; }
+
+ Struct& operator*() const {
+ assert(!is_null_);
+ return value_;
+ }
+ Struct* operator->() const {
+ assert(!is_null_);
+ return &value_;
+ }
+ Struct* get() const { return &value_; }
+
+ void Swap(InlinedStructPtr* other) {
+ std::swap(value_, other->value_);
+ std::swap(is_null_, other->is_null_);
+ }
+
+ private:
+ typedef Struct InlinedStructPtr::*Testable;
+
+ public:
+ operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; }
+
+ private:
+ friend class internal::StructHelper<Struct>;
+ void Initialize() { is_null_ = false; }
+
+ void Take(InlinedStructPtr* other) {
+ reset();
+ Swap(other);
+ }
+
+ mutable Struct value_;
+ bool is_null_;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
diff --git a/chromium/mojo/public/cpp/bindings/sync_dispatcher.h b/chromium/mojo/public/cpp/bindings/sync_dispatcher.h
new file mode 100644
index 00000000000..9f825bf8a6a
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/sync_dispatcher.h
@@ -0,0 +1,47 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_SYNC_DISPATCHER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_SYNC_DISPATCHER_H_
+
+#include "mojo/public/cpp/bindings/lib/filter_chain.h"
+#include "mojo/public/cpp/bindings/lib/message_header_validator.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+class MessageReceiver;
+
+// Waits for one message to arrive on the message pipe, and dispatch it to the
+// receiver. Returns true on success, false on failure.
+//
+// NOTE: The message hasn't been validated and may be malformed!
+bool WaitForMessageAndDispatch(MessagePipeHandle handle,
+ mojo::MessageReceiver* receiver);
+
+template<typename Interface> class SyncDispatcher {
+ public:
+ SyncDispatcher(ScopedMessagePipeHandle message_pipe, Interface* sink)
+ : message_pipe_(message_pipe.Pass()) {
+ stub_.set_sink(sink);
+
+ filters_.Append<internal::MessageHeaderValidator>();
+ filters_.Append<typename Interface::RequestValidator_>();
+ filters_.SetSink(&stub_);
+ }
+
+ bool WaitAndDispatchOneMessage() {
+ return WaitForMessageAndDispatch(message_pipe_.get(),
+ filters_.GetHead());
+ }
+
+ private:
+ ScopedMessagePipeHandle message_pipe_;
+ typename Interface::Stub_ stub_;
+ internal::FilterChain filters_;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_SYNC_DISPATCHER_H_
diff --git a/chromium/mojo/public/cpp/bindings/type_converter.h b/chromium/mojo/public/cpp/bindings/type_converter.h
new file mode 100644
index 00000000000..0ac5f6d4760
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/type_converter.h
@@ -0,0 +1,82 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_TYPE_CONVERTER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_TYPE_CONVERTER_H_
+
+namespace mojo {
+
+// Specialize the following class:
+// template <typename T, typename U> class TypeConverter;
+// to perform type conversion for Mojom-defined structs and arrays. Here, T is
+// the Mojom-defined struct or array, and U is some other non-Mojom
+// struct or array type.
+//
+// Specializations should implement the following interface:
+// namespace mojo {
+// template <>
+// class TypeConverter<T, U> {
+// public:
+// static T ConvertFrom(const U& input);
+// static U ConvertTo(const T& input);
+// };
+// }
+//
+// EXAMPLE:
+//
+// Suppose you have the following Mojom-defined struct:
+//
+// module geometry {
+// struct Point {
+// int32 x;
+// int32 y;
+// };
+// }
+//
+// Now, imagine you wanted to write a TypeConverter specialization for
+// gfx::Point. It might look like this:
+//
+// namespace mojo {
+// template <>
+// class TypeConverter<geometry::PointPtr, gfx::Point> {
+// public:
+// static geometry::PointPtr ConvertFrom(const gfx::Point& input) {
+// geometry::PointPtr result;
+// result->x = input.x();
+// result->y = input.y();
+// return result.Pass();
+// }
+// static gfx::Point ConvertTo(const geometry::PointPtr& input) {
+// return input ? gfx::Point(input->x, input->y) : gfx::Point();
+// }
+// };
+// }
+//
+// With the above TypeConverter defined, it is possible to write code like this:
+//
+// void AcceptPoint(const geometry::PointPtr& input) {
+// // With an explicit cast using the .To<> method.
+// gfx::Point pt = input.To<gfx::Point>();
+//
+// // With an explicit cast using the static From() method.
+// geometry::PointPtr output = geometry::Point::From(pt);
+// }
+//
+template <typename T, typename U> class TypeConverter;
+
+// The following specialization is useful when you are converting between
+// Array<POD> and std::vector<POD>.
+template <typename T> class TypeConverter<T, T> {
+ public:
+ static T ConvertFrom(const T& obj) {
+ return obj;
+ }
+ static T ConvertTo(const T& obj) {
+ return obj;
+ }
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_TYPE_CONVERTER_H_
diff --git a/chromium/mojo/public/cpp/environment/environment.h b/chromium/mojo/public/cpp/environment/environment.h
new file mode 100644
index 00000000000..48f4c26eb72
--- /dev/null
+++ b/chromium/mojo/public/cpp/environment/environment.h
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
+
+#include "mojo/public/cpp/system/macros.h"
+
+struct MojoAsyncWaiter;
+struct MojoLogger;
+
+namespace mojo {
+
+// Other parts of the Mojo C++ APIs use the *static* methods of this class.
+//
+// The "standalone" implementation of this class requires that this class (in
+// the lib/ subdirectory) be instantiated (and remain so) while using the Mojo
+// C++ APIs. I.e., the static methods depend on things set up by the constructor
+// and torn down by the destructor.
+//
+// Other implementations may not have this requirement.
+class Environment {
+ public:
+ Environment();
+ // This constructor allows the standard implementations to be overridden (set
+ // a parameter to null to get the standard implementation).
+ Environment(const MojoAsyncWaiter* default_async_waiter,
+ const MojoLogger* default_logger);
+ ~Environment();
+
+ static const MojoAsyncWaiter* GetDefaultAsyncWaiter();
+ static const MojoLogger* GetDefaultLogger();
+
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Environment);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
diff --git a/chromium/mojo/public/cpp/environment/lib/DEPS b/chromium/mojo/public/cpp/environment/lib/DEPS
new file mode 100644
index 00000000000..1889e1fb75f
--- /dev/null
+++ b/chromium/mojo/public/cpp/environment/lib/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+mojo/public/cpp/environment",
+ "+mojo/public/cpp/utility",
+]
diff --git a/chromium/mojo/public/cpp/environment/lib/default_async_waiter.cc b/chromium/mojo/public/cpp/environment/lib/default_async_waiter.cc
new file mode 100644
index 00000000000..257f1c8d797
--- /dev/null
+++ b/chromium/mojo/public/cpp/environment/lib/default_async_waiter.cc
@@ -0,0 +1,94 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/environment/lib/default_async_waiter.h"
+
+#include <assert.h>
+
+#include "mojo/public/c/environment/async_waiter.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+#include "mojo/public/cpp/utility/run_loop_handler.h"
+
+namespace mojo {
+
+namespace {
+
+// RunLoopHandler implementation used for a request to AsyncWait(). There are
+// two ways RunLoopHandlerImpl is deleted:
+// . when the handle is ready (or errored).
+// . when CancelWait() is invoked.
+class RunLoopHandlerImpl : public RunLoopHandler {
+ public:
+ RunLoopHandlerImpl(const Handle& handle,
+ MojoAsyncWaitCallback callback,
+ void* closure)
+ : handle_(handle),
+ callback_(callback),
+ closure_(closure) {
+ }
+
+ virtual ~RunLoopHandlerImpl() {
+ RunLoop::current()->RemoveHandler(handle_);
+ }
+
+ // RunLoopHandler:
+ virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
+ NotifyCallback(MOJO_RESULT_OK);
+ }
+
+ virtual void OnHandleError(const Handle& handle,
+ MojoResult result) MOJO_OVERRIDE {
+ NotifyCallback(result);
+ }
+
+ private:
+ void NotifyCallback(MojoResult result) {
+ // Delete this to unregister the handle. That way if the callback
+ // reregisters everything is ok.
+ MojoAsyncWaitCallback callback = callback_;
+ void* closure = closure_;
+ delete this;
+
+ callback(closure, result);
+ }
+
+ const Handle handle_;
+ MojoAsyncWaitCallback callback_;
+ void* closure_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoopHandlerImpl);
+};
+
+MojoAsyncWaitID AsyncWait(MojoHandle handle,
+ MojoHandleSignals signals,
+ MojoDeadline deadline,
+ MojoAsyncWaitCallback callback,
+ void* closure) {
+ RunLoop* run_loop = RunLoop::current();
+ assert(run_loop);
+
+ // |run_loop_handler| is destroyed either when the handle is ready or if
+ // CancelWait is invoked.
+ RunLoopHandlerImpl* run_loop_handler =
+ new RunLoopHandlerImpl(Handle(handle), callback, closure);
+ run_loop->AddHandler(run_loop_handler, Handle(handle), signals, deadline);
+ return reinterpret_cast<MojoAsyncWaitID>(run_loop_handler);
+}
+
+void CancelWait(MojoAsyncWaitID wait_id) {
+ delete reinterpret_cast<RunLoopHandlerImpl*>(wait_id);
+}
+
+} // namespace
+
+namespace internal {
+
+const MojoAsyncWaiter kDefaultAsyncWaiter = {
+ AsyncWait,
+ CancelWait
+};
+
+} // namespace internal
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/environment/lib/default_async_waiter.h b/chromium/mojo/public/cpp/environment/lib/default_async_waiter.h
new file mode 100644
index 00000000000..49ce233490c
--- /dev/null
+++ b/chromium/mojo/public/cpp/environment/lib/default_async_waiter.h
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_ASYNC_WAITER_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_ASYNC_WAITER_H_
+
+struct MojoAsyncWaiter;
+
+namespace mojo {
+namespace internal {
+
+extern const MojoAsyncWaiter kDefaultAsyncWaiter;
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_ASYNC_WAITER_H_
diff --git a/chromium/mojo/public/cpp/environment/lib/default_logger.cc b/chromium/mojo/public/cpp/environment/lib/default_logger.cc
new file mode 100644
index 00000000000..af4a62866b0
--- /dev/null
+++ b/chromium/mojo/public/cpp/environment/lib/default_logger.cc
@@ -0,0 +1,71 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/environment/lib/default_logger.h"
+
+#include <stdio.h>
+#include <stdlib.h> // For |abort()|.
+
+#include <algorithm>
+
+#include "mojo/public/c/environment/logger.h"
+
+namespace mojo {
+
+namespace {
+
+MojoLogLevel g_minimum_log_level = MOJO_LOG_LEVEL_INFO;
+
+const char* GetLogLevelString(MojoLogLevel log_level) {
+ if (log_level <= MOJO_LOG_LEVEL_VERBOSE-3)
+ return "VERBOSE4+";
+ switch (log_level) {
+ case MOJO_LOG_LEVEL_VERBOSE-2:
+ return "VERBOSE3";
+ case MOJO_LOG_LEVEL_VERBOSE-1:
+ return "VERBOSE2";
+ case MOJO_LOG_LEVEL_VERBOSE:
+ return "VERBOSE1";
+ case MOJO_LOG_LEVEL_INFO:
+ return "INFO";
+ case MOJO_LOG_LEVEL_WARNING:
+ return "WARNING";
+ case MOJO_LOG_LEVEL_ERROR:
+ return "ERROR";
+ }
+ // Consider everything higher to be fatal.
+ return "FATAL";
+}
+
+void LogMessage(MojoLogLevel log_level, const char* message) {
+ if (log_level < g_minimum_log_level)
+ return;
+
+ // TODO(vtl): Add timestamp also?
+ fprintf(stderr, "%s: %s\n", GetLogLevelString(log_level), message);
+ if (log_level >= MOJO_LOG_LEVEL_FATAL)
+ abort();
+}
+
+MojoLogLevel GetMinimumLogLevel() {
+ return g_minimum_log_level;
+}
+
+void SetMinimumLogLevel(MojoLogLevel minimum_log_level) {
+ g_minimum_log_level = std::min(minimum_log_level, MOJO_LOG_LEVEL_FATAL);
+}
+
+} // namespace
+
+namespace internal {
+
+const MojoLogger kDefaultLogger = {
+ LogMessage,
+ GetMinimumLogLevel,
+ SetMinimumLogLevel
+};
+
+} // namespace internal
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/environment/lib/default_logger.h b/chromium/mojo/public/cpp/environment/lib/default_logger.h
new file mode 100644
index 00000000000..4db32336811
--- /dev/null
+++ b/chromium/mojo/public/cpp/environment/lib/default_logger.h
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_LOGGER_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_LOGGER_H_
+
+struct MojoLogger;
+
+namespace mojo {
+namespace internal {
+
+extern const MojoLogger kDefaultLogger;
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_LOGGER_H_
diff --git a/chromium/mojo/public/cpp/environment/lib/environment.cc b/chromium/mojo/public/cpp/environment/lib/environment.cc
new file mode 100644
index 00000000000..58e270e9ae4
--- /dev/null
+++ b/chromium/mojo/public/cpp/environment/lib/environment.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/environment/environment.h"
+
+#include <stddef.h>
+
+#include "mojo/public/c/environment/logger.h"
+#include "mojo/public/cpp/environment/lib/default_async_waiter.h"
+#include "mojo/public/cpp/environment/lib/default_logger.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+
+namespace mojo {
+
+namespace {
+
+const MojoAsyncWaiter* g_default_async_waiter = NULL;
+const MojoLogger* g_default_logger = NULL;
+
+void Init(const MojoAsyncWaiter* default_async_waiter,
+ const MojoLogger* default_logger) {
+ g_default_async_waiter =
+ default_async_waiter ? default_async_waiter :
+ &internal::kDefaultAsyncWaiter;
+ g_default_logger = default_logger ? default_logger :
+ &internal::kDefaultLogger;
+
+ RunLoop::SetUp();
+}
+
+} // namespace
+
+Environment::Environment() {
+ Init(NULL, NULL);
+}
+
+Environment::Environment(const MojoAsyncWaiter* default_async_waiter,
+ const MojoLogger* default_logger) {
+ Init(default_async_waiter, default_logger);
+}
+
+Environment::~Environment() {
+ RunLoop::TearDown();
+
+ // TODO(vtl): Maybe we should allow nesting, and restore previous default
+ // async waiters and loggers?
+}
+
+// static
+const MojoAsyncWaiter* Environment::GetDefaultAsyncWaiter() {
+ return g_default_async_waiter;
+}
+
+// static
+const MojoLogger* Environment::GetDefaultLogger() {
+ return g_default_logger;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/environment/lib/logging.cc b/chromium/mojo/public/cpp/environment/lib/logging.cc
new file mode 100644
index 00000000000..990626df736
--- /dev/null
+++ b/chromium/mojo/public/cpp/environment/lib/logging.cc
@@ -0,0 +1,45 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/environment/logging.h"
+
+#include "mojo/public/cpp/environment/environment.h"
+
+namespace mojo {
+namespace internal {
+
+namespace {
+
+// Gets a pointer to the filename portion of |s|. Assumes that the filename
+// follows the last slash or backslash in |s|, or is |s| if no slash or
+// backslash is present.
+//
+// E.g., a pointer to "foo.cc" is returned for the following inputs: "foo.cc",
+// "./foo.cc", ".\foo.cc", "/absolute/path/to/foo.cc",
+// "relative/path/to/foo.cc", "C:\absolute\path\to\foo.cc", etc.
+const char* GetFilename(const char* s) {
+ const char* rv = s;
+ while (*s) {
+ if (*s == '/' || *s == '\\')
+ rv = s + 1;
+ s++;
+ }
+ return rv;
+}
+
+} // namespace
+
+LogMessage::LogMessage(const char* file, int line, MojoLogLevel log_level)
+ : log_level_(log_level) {
+ // Note: Don't include the log level in the message, since that's passed on.
+ stream_ << GetFilename(file) << '(' << line << "): ";
+}
+
+LogMessage::~LogMessage() {
+ Environment::GetDefaultLogger()->LogMessage(log_level_,
+ stream_.str().c_str());
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/environment/logging.h b/chromium/mojo/public/cpp/environment/logging.h
new file mode 100644
index 00000000000..a3e2cef4293
--- /dev/null
+++ b/chromium/mojo/public/cpp/environment/logging.h
@@ -0,0 +1,87 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Logging macros, similar to Chromium's base/logging.h, except with |MOJO_|
+// prefixes and missing some features (notably |CHECK_EQ()|, etc.).
+
+// TODO(vtl): It's weird that this is in the environment directory, since its
+// implementation (in environment/lib) is meant to be used by any implementation
+// of the environment.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_LOGGING_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_LOGGING_H_
+
+#include <sstream>
+
+#include "mojo/public/c/environment/logger.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/macros.h"
+
+#define MOJO_LOG_STREAM(level) \
+ ::mojo::internal::LogMessage(__FILE__, __LINE__, \
+ MOJO_LOG_LEVEL_ ## level).stream()
+
+#define MOJO_LAZY_LOG_STREAM(level, condition) \
+ !(condition) ? \
+ (void) 0 : \
+ ::mojo::internal::VoidifyOstream() & MOJO_LOG_STREAM(level)
+
+#define MOJO_SHOULD_LOG(level) \
+ (MOJO_LOG_LEVEL_ ## level >= \
+ ::mojo::Environment::GetDefaultLogger()->GetMinimumLogLevel())
+
+#define MOJO_LOG(level) \
+ MOJO_LAZY_LOG_STREAM(level, MOJO_SHOULD_LOG(level))
+
+#define MOJO_LOG_IF(level, condition) \
+ MOJO_LAZY_LOG_STREAM(level, MOJO_SHOULD_LOG(level) && (condition))
+
+#define MOJO_CHECK(condition) \
+ MOJO_LAZY_LOG_STREAM(FATAL, !(condition)) \
+ << "Check failed: " #condition ". "
+
+// Note: For non-debug builds, |MOJO_DLOG_IF()| *eliminates* (i.e., doesn't
+// compile) the condition, whereas |MOJO_DCHECK()| "neuters" the condition
+// (i.e., compiles, but doesn't evaluate).
+#ifdef NDEBUG
+
+#define MOJO_DLOG(level) MOJO_LAZY_LOG_STREAM(level, false)
+#define MOJO_DLOG_IF(level, condition) MOJO_LAZY_LOG_STREAM(level, false)
+#define MOJO_DCHECK(condition) MOJO_LAZY_LOG_STREAM(FATAL, false && (condition))
+
+#else
+
+#define MOJO_DLOG(level) MOJO_LOG(level)
+#define MOJO_DLOG_IF(level, condition) MOJO_LOG_IF(level, condition)
+#define MOJO_DCHECK(condition) MOJO_CHECK(condition)
+
+#endif // NDEBUG
+
+namespace mojo {
+namespace internal {
+
+class LogMessage {
+ public:
+ LogMessage(const char* file, int line, MojoLogLevel log_level);
+ ~LogMessage();
+
+ std::ostream& stream() { return stream_; }
+
+ private:
+ const MojoLogLevel log_level_;
+ std::ostringstream stream_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(LogMessage);
+};
+
+// Used to ignore a stream.
+struct VoidifyOstream {
+ // Use & since it has precedence lower than << but higher than ?:.
+ void operator&(std::ostream&) {}
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_LOGGING_H_
diff --git a/chromium/mojo/public/cpp/gles2/DEPS b/chromium/mojo/public/cpp/gles2/DEPS
new file mode 100644
index 00000000000..3c48be99eb8
--- /dev/null
+++ b/chromium/mojo/public/cpp/gles2/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+mojo/public/c/gles2",
+ "+mojo/public/cpp/environment",
+]
diff --git a/chromium/mojo/public/cpp/gles2/gles2.h b/chromium/mojo/public/cpp/gles2/gles2.h
new file mode 100644
index 00000000000..a408fc701eb
--- /dev/null
+++ b/chromium/mojo/public/cpp/gles2/gles2.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_GLES2_GLES2_H_
+#define MOJO_PUBLIC_CPP_GLES2_GLES2_H_
+
+#include "mojo/public/c/gles2/gles2.h"
+#include "mojo/public/cpp/environment/environment.h"
+
+namespace mojo {
+
+class GLES2Initializer {
+ public:
+ explicit GLES2Initializer(const MojoAsyncWaiter* async_waiter =
+ Environment::GetDefaultAsyncWaiter()) {
+ MojoGLES2Initialize(async_waiter);
+ }
+ ~GLES2Initializer() { MojoGLES2Terminate(); }
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_GLES2_GLES2_H_
diff --git a/chromium/mojo/public/cpp/system/core.h b/chromium/mojo/public/cpp/system/core.h
new file mode 100644
index 00000000000..d73bb296514
--- /dev/null
+++ b/chromium/mojo/public/cpp/system/core.h
@@ -0,0 +1,555 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
+#define MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
+
+#include <assert.h>
+#include <stddef.h>
+
+#include <limits>
+
+#include "mojo/public/c/system/core.h"
+#include "mojo/public/c/system/system_export.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+// OVERVIEW
+//
+// |Handle| and |...Handle|:
+//
+// |Handle| is a simple, copyable wrapper for the C type |MojoHandle| (which is
+// just an integer). Its purpose is to increase type-safety, not provide
+// lifetime management. For the same purpose, we have trivial *subclasses* of
+// |Handle|, e.g., |MessagePipeHandle| and |DataPipeProducerHandle|. |Handle|
+// and its subclasses impose *no* extra overhead over using |MojoHandle|s
+// directly.
+//
+// Note that though we provide constructors for |Handle|/|...Handle| from a
+// |MojoHandle|, we do not provide, e.g., a constructor for |MessagePipeHandle|
+// from a |Handle|. This is for type safety: If we did, you'd then be able to
+// construct a |MessagePipeHandle| from, e.g., a |DataPipeProducerHandle| (since
+// it's a |Handle|).
+//
+// |ScopedHandleBase| and |Scoped...Handle|:
+//
+// |ScopedHandleBase<HandleType>| is a templated scoped wrapper, for the handle
+// types above (in the same sense that a C++11 |unique_ptr<T>| is a scoped
+// wrapper for a |T*|). It provides lifetime management, closing its owned
+// handle on destruction. It also provides (emulated) move semantics, again
+// along the lines of C++11's |unique_ptr| (and exactly like Chromium's
+// |scoped_ptr|).
+//
+// |ScopedHandle| is just (a typedef of) a |ScopedHandleBase<Handle>|.
+// Similarly, |ScopedMessagePipeHandle| is just a
+// |ScopedHandleBase<MessagePipeHandle>|. Etc. Note that a
+// |ScopedMessagePipeHandle| is *not* a (subclass of) |ScopedHandle|.
+//
+// Wrapper functions:
+//
+// We provide simple wrappers for the |Mojo...()| functions (in
+// mojo/public/c/system/core.h -- see that file for details on individual
+// functions).
+//
+// The general guideline is functions that imply ownership transfer of a handle
+// should take (or produce) an appropriate |Scoped...Handle|, while those that
+// don't take a |...Handle|. For example, |CreateMessagePipe()| has two
+// |ScopedMessagePipe| "out" parameters, whereas |Wait()| and |WaitMany()| take
+// |Handle| parameters. Some, have both: e.g., |DuplicatedBuffer()| takes a
+// suitable (unscoped) handle (e.g., |SharedBufferHandle|) "in" parameter and
+// produces a suitable scoped handle (e.g., |ScopedSharedBufferHandle| a.k.a.
+// |ScopedHandleBase<SharedBufferHandle>|) as an "out" parameter.
+//
+// An exception are some of the |...Raw()| functions. E.g., |CloseRaw()| takes a
+// |Handle|, leaving the user to discard the handle.
+//
+// More significantly, |WriteMessageRaw()| exposes the full API complexity of
+// |MojoWriteMessage()| (but doesn't require any extra overhead). It takes a raw
+// array of |Handle|s as input, and takes ownership of them (i.e., invalidates
+// them) on *success* (but not on failure). There are a number of reasons for
+// this. First, C++03 |std::vector|s cannot contain the move-only
+// |Scoped...Handle|s. Second, |std::vector|s impose extra overhead
+// (necessitating heap-allocation of the buffer). Third, |std::vector|s wouldn't
+// provide the desired level of flexibility/safety: a vector of handles would
+// have to be all of the same type (probably |Handle|/|ScopedHandle|). Fourth,
+// it's expected to not be used directly, but instead be used by generated
+// bindings.
+//
+// Other |...Raw()| functions expose similar rough edges, e.g., dealing with raw
+// pointers (and lengths) instead of taking |std::vector|s or similar.
+
+// Standalone functions --------------------------------------------------------
+
+inline MojoTimeTicks GetTimeTicksNow() {
+ return MojoGetTimeTicksNow();
+}
+
+// ScopedHandleBase ------------------------------------------------------------
+
+// Scoper for the actual handle types defined further below. It's move-only,
+// like the C++11 |unique_ptr|.
+template <class HandleType>
+class ScopedHandleBase {
+ MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue)
+
+ public:
+ ScopedHandleBase() {}
+ explicit ScopedHandleBase(HandleType handle) : handle_(handle) {}
+ ~ScopedHandleBase() { CloseIfNecessary(); }
+
+ template <class CompatibleHandleType>
+ explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other)
+ : handle_(other.release()) {
+ }
+
+ // Move-only constructor and operator=.
+ ScopedHandleBase(RValue other) : handle_(other.object->release()) {}
+ ScopedHandleBase& operator=(RValue other) {
+ if (other.object != this) {
+ CloseIfNecessary();
+ handle_ = other.object->release();
+ }
+ return *this;
+ }
+
+ const HandleType& get() const { return handle_; }
+
+ template <typename PassedHandleType>
+ static ScopedHandleBase<HandleType> From(
+ ScopedHandleBase<PassedHandleType> other) {
+ MOJO_COMPILE_ASSERT(
+ sizeof(static_cast<PassedHandleType*>(static_cast<HandleType*>(0))),
+ HandleType_is_not_a_subtype_of_PassedHandleType);
+ return ScopedHandleBase<HandleType>(
+ static_cast<HandleType>(other.release().value()));
+ }
+
+ void swap(ScopedHandleBase& other) {
+ handle_.swap(other.handle_);
+ }
+
+ HandleType release() MOJO_WARN_UNUSED_RESULT {
+ HandleType rv;
+ rv.swap(handle_);
+ return rv;
+ }
+
+ void reset(HandleType handle = HandleType()) {
+ CloseIfNecessary();
+ handle_ = handle;
+ }
+
+ bool is_valid() const {
+ return handle_.is_valid();
+ }
+
+ private:
+ void CloseIfNecessary() {
+ if (!handle_.is_valid())
+ return;
+ MojoResult result MOJO_ALLOW_UNUSED = MojoClose(handle_.value());
+ assert(result == MOJO_RESULT_OK);
+ }
+
+ HandleType handle_;
+};
+
+template <typename HandleType>
+inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) {
+ return ScopedHandleBase<HandleType>(handle);
+}
+
+// Handle ----------------------------------------------------------------------
+
+const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID;
+
+// Wrapper base class for |MojoHandle|.
+class Handle {
+ public:
+ Handle() : value_(kInvalidHandleValue) {}
+ explicit Handle(MojoHandle value) : value_(value) {}
+ ~Handle() {}
+
+ void swap(Handle& other) {
+ MojoHandle temp = value_;
+ value_ = other.value_;
+ other.value_ = temp;
+ }
+
+ bool is_valid() const {
+ return value_ != kInvalidHandleValue;
+ }
+
+ MojoHandle value() const { return value_; }
+ MojoHandle* mutable_value() { return &value_; }
+ void set_value(MojoHandle value) { value_ = value; }
+
+ private:
+ MojoHandle value_;
+
+ // Copying and assignment allowed.
+};
+
+// Should have zero overhead.
+MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle),
+ bad_size_for_cpp_Handle);
+
+// The scoper should also impose no more overhead.
+typedef ScopedHandleBase<Handle> ScopedHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle),
+ bad_size_for_cpp_ScopedHandle);
+
+inline MojoResult Wait(const Handle& handle,
+ MojoHandleSignals signals,
+ MojoDeadline deadline) {
+ return MojoWait(handle.value(), signals, deadline);
+}
+
+// |HandleVectorType| and |FlagsVectorType| should be similar enough to
+// |std::vector<Handle>| and |std::vector<MojoHandleSignals>|, respectively:
+// - They should have a (const) |size()| method that returns an unsigned type.
+// - They must provide contiguous storage, with access via (const) reference to
+// that storage provided by a (const) |operator[]()| (by reference).
+template <class HandleVectorType, class FlagsVectorType>
+inline MojoResult WaitMany(const HandleVectorType& handles,
+ const FlagsVectorType& signals,
+ MojoDeadline deadline) {
+ if (signals.size() != handles.size())
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (handles.size() > std::numeric_limits<uint32_t>::max())
+ return MOJO_RESULT_OUT_OF_RANGE;
+
+ if (handles.size() == 0)
+ return MojoWaitMany(NULL, NULL, 0, deadline);
+
+ const Handle& first_handle = handles[0];
+ const MojoHandleSignals& first_signals = signals[0];
+ return MojoWaitMany(
+ reinterpret_cast<const MojoHandle*>(&first_handle),
+ reinterpret_cast<const MojoHandleSignals*>(&first_signals),
+ static_cast<uint32_t>(handles.size()),
+ deadline);
+}
+
+// |Close()| takes ownership of the handle, since it'll invalidate it.
+// Note: There's nothing to do, since the argument will be destroyed when it
+// goes out of scope.
+template <class HandleType>
+inline void Close(ScopedHandleBase<HandleType> /*handle*/) {}
+
+// Most users should typically use |Close()| (above) instead.
+inline MojoResult CloseRaw(Handle handle) {
+ return MojoClose(handle.value());
+}
+
+// Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s,
+// etc.
+inline bool operator<(const Handle& a, const Handle& b) {
+ return a.value() < b.value();
+}
+
+// MessagePipeHandle -----------------------------------------------------------
+
+class MessagePipeHandle : public Handle {
+ public:
+ MessagePipeHandle() {}
+ explicit MessagePipeHandle(MojoHandle value) : Handle(value) {}
+
+ // Copying and assignment allowed.
+};
+
+MOJO_COMPILE_ASSERT(sizeof(MessagePipeHandle) == sizeof(Handle),
+ bad_size_for_cpp_MessagePipeHandle);
+
+typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedMessagePipeHandle) ==
+ sizeof(MessagePipeHandle),
+ bad_size_for_cpp_ScopedMessagePipeHandle);
+
+inline MojoResult CreateMessagePipe(const MojoCreateMessagePipeOptions* options,
+ ScopedMessagePipeHandle* message_pipe0,
+ ScopedMessagePipeHandle* message_pipe1) {
+ assert(message_pipe0);
+ assert(message_pipe1);
+ MessagePipeHandle handle0;
+ MessagePipeHandle handle1;
+ MojoResult rv = MojoCreateMessagePipe(options,
+ handle0.mutable_value(),
+ handle1.mutable_value());
+ // Reset even on failure (reduces the chances that a "stale"/incorrect handle
+ // will be used).
+ message_pipe0->reset(handle0);
+ message_pipe1->reset(handle1);
+ return rv;
+}
+
+// These "raw" versions fully expose the underlying API, but don't help with
+// ownership of handles (especially when writing messages).
+// TODO(vtl): Write "baked" versions.
+inline MojoResult WriteMessageRaw(MessagePipeHandle message_pipe,
+ const void* bytes,
+ uint32_t num_bytes,
+ const MojoHandle* handles,
+ uint32_t num_handles,
+ MojoWriteMessageFlags flags) {
+ return MojoWriteMessage(message_pipe.value(), bytes, num_bytes, handles,
+ num_handles, flags);
+}
+
+inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe,
+ void* bytes,
+ uint32_t* num_bytes,
+ MojoHandle* handles,
+ uint32_t* num_handles,
+ MojoReadMessageFlags flags) {
+ return MojoReadMessage(message_pipe.value(), bytes, num_bytes, handles,
+ num_handles, flags);
+}
+
+// A wrapper class that automatically creates a message pipe and owns both
+// handles.
+class MessagePipe {
+ public:
+ MessagePipe();
+ explicit MessagePipe(const MojoCreateMessagePipeOptions& options);
+ ~MessagePipe();
+
+ ScopedMessagePipeHandle handle0;
+ ScopedMessagePipeHandle handle1;
+};
+
+inline MessagePipe::MessagePipe() {
+ MojoResult result MOJO_ALLOW_UNUSED =
+ CreateMessagePipe(NULL, &handle0, &handle1);
+ assert(result == MOJO_RESULT_OK);
+}
+
+inline MessagePipe::MessagePipe(const MojoCreateMessagePipeOptions& options) {
+ MojoResult result MOJO_ALLOW_UNUSED =
+ CreateMessagePipe(&options, &handle0, &handle1);
+ assert(result == MOJO_RESULT_OK);
+}
+
+inline MessagePipe::~MessagePipe() {
+}
+
+// DataPipeProducerHandle and DataPipeConsumerHandle ---------------------------
+
+class DataPipeProducerHandle : public Handle {
+ public:
+ DataPipeProducerHandle() {}
+ explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {}
+
+ // Copying and assignment allowed.
+};
+
+MOJO_COMPILE_ASSERT(sizeof(DataPipeProducerHandle) == sizeof(Handle),
+ bad_size_for_cpp_DataPipeProducerHandle);
+
+typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeProducerHandle) ==
+ sizeof(DataPipeProducerHandle),
+ bad_size_for_cpp_ScopedDataPipeProducerHandle);
+
+class DataPipeConsumerHandle : public Handle {
+ public:
+ DataPipeConsumerHandle() {}
+ explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {}
+
+ // Copying and assignment allowed.
+};
+
+MOJO_COMPILE_ASSERT(sizeof(DataPipeConsumerHandle) == sizeof(Handle),
+ bad_size_for_cpp_DataPipeConsumerHandle);
+
+typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeConsumerHandle) ==
+ sizeof(DataPipeConsumerHandle),
+ bad_size_for_cpp_ScopedDataPipeConsumerHandle);
+
+inline MojoResult CreateDataPipe(
+ const MojoCreateDataPipeOptions* options,
+ ScopedDataPipeProducerHandle* data_pipe_producer,
+ ScopedDataPipeConsumerHandle* data_pipe_consumer) {
+ assert(data_pipe_producer);
+ assert(data_pipe_consumer);
+ DataPipeProducerHandle producer_handle;
+ DataPipeConsumerHandle consumer_handle;
+ MojoResult rv = MojoCreateDataPipe(options, producer_handle.mutable_value(),
+ consumer_handle.mutable_value());
+ // Reset even on failure (reduces the chances that a "stale"/incorrect handle
+ // will be used).
+ data_pipe_producer->reset(producer_handle);
+ data_pipe_consumer->reset(consumer_handle);
+ return rv;
+}
+
+inline MojoResult WriteDataRaw(DataPipeProducerHandle data_pipe_producer,
+ const void* elements,
+ uint32_t* num_bytes,
+ MojoWriteDataFlags flags) {
+ return MojoWriteData(data_pipe_producer.value(), elements, num_bytes, flags);
+}
+
+inline MojoResult BeginWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
+ void** buffer,
+ uint32_t* buffer_num_bytes,
+ MojoWriteDataFlags flags) {
+ return MojoBeginWriteData(data_pipe_producer.value(), buffer,
+ buffer_num_bytes, flags);
+}
+
+inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
+ uint32_t num_bytes_written) {
+ return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written);
+}
+
+inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
+ void* elements,
+ uint32_t* num_bytes,
+ MojoReadDataFlags flags) {
+ return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags);
+}
+
+inline MojoResult BeginReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
+ const void** buffer,
+ uint32_t* buffer_num_bytes,
+ MojoReadDataFlags flags) {
+ return MojoBeginReadData(data_pipe_consumer.value(), buffer, buffer_num_bytes,
+ flags);
+}
+
+inline MojoResult EndReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
+ uint32_t num_bytes_read) {
+ return MojoEndReadData(data_pipe_consumer.value(), num_bytes_read);
+}
+
+// A wrapper class that automatically creates a data pipe and owns both handles.
+// TODO(vtl): Make an even more friendly version? (Maybe templatized for a
+// particular type instead of some "element"? Maybe functions that take
+// vectors?)
+class DataPipe {
+ public:
+ DataPipe();
+ explicit DataPipe(const MojoCreateDataPipeOptions& options);
+ ~DataPipe();
+
+ ScopedDataPipeProducerHandle producer_handle;
+ ScopedDataPipeConsumerHandle consumer_handle;
+};
+
+inline DataPipe::DataPipe() {
+ MojoResult result MOJO_ALLOW_UNUSED =
+ CreateDataPipe(NULL, &producer_handle, &consumer_handle);
+ assert(result == MOJO_RESULT_OK);
+}
+
+inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) {
+ MojoResult result MOJO_ALLOW_UNUSED =
+ CreateDataPipe(&options, &producer_handle, &consumer_handle);
+ assert(result == MOJO_RESULT_OK);
+}
+
+inline DataPipe::~DataPipe() {
+}
+
+// SharedBufferHandle ----------------------------------------------------------
+
+class SharedBufferHandle : public Handle {
+ public:
+ SharedBufferHandle() {}
+ explicit SharedBufferHandle(MojoHandle value) : Handle(value) {}
+
+ // Copying and assignment allowed.
+};
+
+MOJO_COMPILE_ASSERT(sizeof(SharedBufferHandle) == sizeof(Handle),
+ bad_size_for_cpp_SharedBufferHandle);
+
+typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedSharedBufferHandle) ==
+ sizeof(SharedBufferHandle),
+ bad_size_for_cpp_ScopedSharedBufferHandle);
+
+inline MojoResult CreateSharedBuffer(
+ const MojoCreateSharedBufferOptions* options,
+ uint64_t num_bytes,
+ ScopedSharedBufferHandle* shared_buffer) {
+ assert(shared_buffer);
+ SharedBufferHandle handle;
+ MojoResult rv = MojoCreateSharedBuffer(options, num_bytes,
+ handle.mutable_value());
+ // Reset even on failure (reduces the chances that a "stale"/incorrect handle
+ // will be used).
+ shared_buffer->reset(handle);
+ return rv;
+}
+
+// TODO(vtl): This (and also the functions below) are templatized to allow for
+// future/other buffer types. A bit "safer" would be to overload this function
+// manually. (The template enforces that the in and out handles to be of the
+// same type.)
+template <class BufferHandleType>
+inline MojoResult DuplicateBuffer(
+ BufferHandleType buffer,
+ const MojoDuplicateBufferHandleOptions* options,
+ ScopedHandleBase<BufferHandleType>* new_buffer) {
+ assert(new_buffer);
+ BufferHandleType handle;
+ MojoResult rv = MojoDuplicateBufferHandle(
+ buffer.value(), options, handle.mutable_value());
+ // Reset even on failure (reduces the chances that a "stale"/incorrect handle
+ // will be used).
+ new_buffer->reset(handle);
+ return rv;
+}
+
+template <class BufferHandleType>
+inline MojoResult MapBuffer(BufferHandleType buffer,
+ uint64_t offset,
+ uint64_t num_bytes,
+ void** pointer,
+ MojoMapBufferFlags flags) {
+ assert(buffer.is_valid());
+ return MojoMapBuffer(buffer.value(), offset, num_bytes, pointer, flags);
+}
+
+inline MojoResult UnmapBuffer(void* pointer) {
+ assert(pointer);
+ return MojoUnmapBuffer(pointer);
+}
+
+// A wrapper class that automatically creates a shared buffer and owns the
+// handle.
+class SharedBuffer {
+ public:
+ explicit SharedBuffer(uint64_t num_bytes);
+ SharedBuffer(uint64_t num_bytes,
+ const MojoCreateSharedBufferOptions& options);
+ ~SharedBuffer();
+
+ ScopedSharedBufferHandle handle;
+};
+
+inline SharedBuffer::SharedBuffer(uint64_t num_bytes) {
+ MojoResult result MOJO_ALLOW_UNUSED =
+ CreateSharedBuffer(NULL, num_bytes, &handle);
+ assert(result == MOJO_RESULT_OK);
+}
+
+inline SharedBuffer::SharedBuffer(
+ uint64_t num_bytes,
+ const MojoCreateSharedBufferOptions& options) {
+ MojoResult result MOJO_ALLOW_UNUSED =
+ CreateSharedBuffer(&options, num_bytes, &handle);
+ assert(result == MOJO_RESULT_OK);
+}
+
+inline SharedBuffer::~SharedBuffer() {
+}
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
diff --git a/chromium/mojo/public/cpp/system/macros.h b/chromium/mojo/public/cpp/system/macros.h
new file mode 100644
index 00000000000..ac4f3dbc84c
--- /dev/null
+++ b/chromium/mojo/public/cpp/system/macros.h
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_SYSTEM_MACROS_H_
+#define MOJO_PUBLIC_CPP_SYSTEM_MACROS_H_
+
+#include "mojo/public/c/system/macros.h"
+
+// Annotate a virtual method indicating it must be overriding a virtual method
+// in the parent class. Use like:
+// virtual void foo() OVERRIDE;
+#if defined(_MSC_VER) || defined(__clang__)
+#define MOJO_OVERRIDE override
+#else
+#define MOJO_OVERRIDE
+#endif
+
+// A macro to disallow the copy constructor and operator= functions.
+// This should be used in the private: declarations for a class.
+#define MOJO_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+// Used to calculate the number of elements in an array.
+// (See |arraysize()| in Chromium's base/basictypes.h for more details.)
+namespace mojo {
+template <typename T, size_t N>
+char (&ArraySizeHelper(T (&array)[N]))[N];
+#if !defined(_MSC_VER)
+template <typename T, size_t N>
+char (&ArraySizeHelper(const T (&array)[N]))[N];
+#endif
+} // namespace mojo
+#define MOJO_ARRAYSIZE(array) (sizeof(::mojo::ArraySizeHelper(array)))
+
+// Used to make a type move-only in C++03. See Chromium's base/move.h for more
+// details.
+#define MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \
+ private: \
+ struct rvalue_type { \
+ explicit rvalue_type(type* object) : object(object) {} \
+ type* object; \
+ }; \
+ type(type&); \
+ void operator=(type&); \
+ public: \
+ operator rvalue_type() { return rvalue_type(this); } \
+ type Pass() { return type(rvalue_type(this)); } \
+ typedef void MoveOnlyTypeForCPP03; \
+ private:
+
+#endif // MOJO_PUBLIC_CPP_SYSTEM_MACROS_H_
diff --git a/chromium/mojo/public/cpp/test_support/DEPS b/chromium/mojo/public/cpp/test_support/DEPS
new file mode 100644
index 00000000000..6dc53942e16
--- /dev/null
+++ b/chromium/mojo/public/cpp/test_support/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+mojo/public/c/test_support",
+]
diff --git a/chromium/mojo/public/cpp/test_support/lib/test_support.cc b/chromium/mojo/public/cpp/test_support/lib/test_support.cc
new file mode 100644
index 00000000000..55a3dcc7024
--- /dev/null
+++ b/chromium/mojo/public/cpp/test_support/lib/test_support.cc
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/test_support/test_support.h"
+
+#include <stdlib.h>
+
+namespace mojo {
+namespace test {
+
+std::vector<std::string> EnumerateSourceRootRelativeDirectory(
+ const std::string& relative_path) {
+ char** names = MojoTestSupportEnumerateSourceRootRelativeDirectory(
+ relative_path.c_str());
+ std::vector<std::string> results;
+ for (char** ptr = names; *ptr != NULL; ++ptr) {
+ results.push_back(*ptr);
+ free(*ptr);
+ }
+ free(names);
+ return results;
+}
+
+} // namespace test
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/test_support/lib/test_utils.cc b/chromium/mojo/public/cpp/test_support/lib/test_utils.cc
new file mode 100644
index 00000000000..b47ea209020
--- /dev/null
+++ b/chromium/mojo/public/cpp/test_support/lib/test_utils.cc
@@ -0,0 +1,91 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/test_support/test_utils.h"
+
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/test_support/test_support.h"
+
+namespace mojo {
+namespace test {
+
+bool WriteTextMessage(const MessagePipeHandle& handle,
+ const std::string& text) {
+ MojoResult rv = WriteMessageRaw(handle,
+ text.data(),
+ static_cast<uint32_t>(text.size()),
+ NULL,
+ 0,
+ MOJO_WRITE_MESSAGE_FLAG_NONE);
+ return rv == MOJO_RESULT_OK;
+}
+
+bool ReadTextMessage(const MessagePipeHandle& handle, std::string* text) {
+ MojoResult rv;
+ bool did_wait = false;
+
+ uint32_t num_bytes = 0, num_handles = 0;
+ for (;;) {
+ rv = ReadMessageRaw(handle,
+ NULL,
+ &num_bytes,
+ NULL,
+ &num_handles,
+ MOJO_READ_MESSAGE_FLAG_NONE);
+ if (rv == MOJO_RESULT_SHOULD_WAIT) {
+ if (did_wait) {
+ assert(false); // Looping endlessly!?
+ return false;
+ }
+ rv = Wait(handle, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE);
+ if (rv != MOJO_RESULT_OK)
+ return false;
+ did_wait = true;
+ } else {
+ assert(!num_handles);
+ break;
+ }
+ }
+
+ text->resize(num_bytes);
+ rv = ReadMessageRaw(handle,
+ &text->at(0),
+ &num_bytes,
+ NULL,
+ &num_handles,
+ MOJO_READ_MESSAGE_FLAG_NONE);
+ return rv == MOJO_RESULT_OK;
+}
+
+bool DiscardMessage(const MessagePipeHandle& handle) {
+ MojoResult rv = ReadMessageRaw(handle, NULL, NULL, NULL, NULL,
+ MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
+ return rv == MOJO_RESULT_OK;
+}
+
+void IterateAndReportPerf(const char* test_name,
+ PerfTestSingleIteration single_iteration,
+ void* closure) {
+ // TODO(vtl): These should be specifiable using command-line flags.
+ static const size_t kGranularity = 100;
+ static const MojoTimeTicks kPerftestTimeMicroseconds = 3 * 1000000;
+
+ const MojoTimeTicks start_time = GetTimeTicksNow();
+ MojoTimeTicks end_time;
+ size_t iterations = 0;
+ do {
+ for (size_t i = 0; i < kGranularity; i++)
+ (*single_iteration)(closure);
+ iterations += kGranularity;
+
+ end_time = GetTimeTicksNow();
+ } while (end_time - start_time < kPerftestTimeMicroseconds);
+
+ MojoTestSupportLogPerfResult(test_name,
+ 1000000.0 * iterations / (end_time - start_time),
+ "iterations/second");
+}
+
+} // namespace test
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/test_support/test_support.h b/chromium/mojo/public/cpp/test_support/test_support.h
new file mode 100644
index 00000000000..eb4d4be7116
--- /dev/null
+++ b/chromium/mojo/public/cpp/test_support/test_support.h
@@ -0,0 +1,34 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_SUPPORT_H_
+#define MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_SUPPORT_H_
+
+#include <string>
+#include <vector>
+
+#include "mojo/public/c/test_support/test_support.h"
+
+namespace mojo {
+namespace test {
+
+inline void LogPerfResult(const char* test_name,
+ double value,
+ const char* units) {
+ MojoTestSupportLogPerfResult(test_name, value, units);
+}
+
+// Opens text file relative to the source root for reading.
+inline FILE* OpenSourceRootRelativeFile(const std::string& relative_path) {
+ return MojoTestSupportOpenSourceRootRelativeFile(relative_path.c_str());
+}
+
+// Returns the list of regular files in a directory relative to the source root.
+std::vector<std::string> EnumerateSourceRootRelativeDirectory(
+ const std::string& relative_path);
+
+} // namespace test
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_SUPPORT_H_
diff --git a/chromium/mojo/public/cpp/test_support/test_utils.h b/chromium/mojo/public/cpp/test_support/test_utils.h
new file mode 100644
index 00000000000..43a3ea99821
--- /dev/null
+++ b/chromium/mojo/public/cpp/test_support/test_utils.h
@@ -0,0 +1,39 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_UTILS_H_
+#define MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_UTILS_H_
+
+#include <string>
+
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+namespace test {
+
+// Writes a message to |handle| with message data |text|. Returns true on
+// success.
+bool WriteTextMessage(const MessagePipeHandle& handle, const std::string& text);
+
+// Reads a message from |handle|, putting its contents into |*text|. Returns
+// true on success. (This blocks if necessary and will call |MojoReadMessage()|
+// multiple times, e.g., to query the size of the message.)
+bool ReadTextMessage(const MessagePipeHandle& handle, std::string* text);
+
+// Discards a message from |handle|. Returns true on success. (This does not
+// block. It will fail if no message is available to discard.)
+bool DiscardMessage(const MessagePipeHandle& handle);
+
+// Run |single_iteration| an appropriate number of times and report its
+// performance appropriately. (This actually runs |single_iteration| for a fixed
+// amount of time and reports the number of iterations per unit time.)
+typedef void (*PerfTestSingleIteration)(void* closure);
+void IterateAndReportPerf(const char* test_name,
+ PerfTestSingleIteration single_iteration,
+ void* closure);
+
+} // namespace test
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_TEST_SUPPORT_TEST_UTILS_H_
diff --git a/chromium/mojo/public/cpp/utility/lib/mutex.cc b/chromium/mojo/public/cpp/utility/lib/mutex.cc
new file mode 100644
index 00000000000..23370e1c023
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/lib/mutex.cc
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/mutex.h"
+
+#include <assert.h>
+#include <errno.h>
+
+namespace mojo {
+
+// Release builds have inlined (non-error-checking) definitions in the header.
+#if !defined(NDEBUG)
+Mutex::Mutex() {
+ pthread_mutexattr_t mutexattr;
+ int rv = pthread_mutexattr_init(&mutexattr);
+ assert(rv == 0);
+ rv = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
+ assert(rv == 0);
+ rv = pthread_mutex_init(&mutex_, &mutexattr);
+ assert(rv == 0);
+ rv = pthread_mutexattr_destroy(&mutexattr);
+ assert(rv == 0);
+}
+
+Mutex::~Mutex() {
+ int rv = pthread_mutex_destroy(&mutex_);
+ assert(rv == 0);
+}
+
+void Mutex::Lock() {
+ int rv = pthread_mutex_lock(&mutex_);
+ assert(rv == 0);
+}
+
+void Mutex::Unlock() {
+ int rv = pthread_mutex_unlock(&mutex_);
+ assert(rv == 0);
+}
+
+bool Mutex::TryLock() {
+ int rv = pthread_mutex_trylock(&mutex_);
+ assert(rv == 0 || rv == EBUSY);
+ return rv == 0;
+}
+
+void Mutex::AssertHeld() {
+ assert(pthread_mutex_lock(&mutex_) == EDEADLK);
+}
+#endif // !defined(NDEBUG)
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/utility/lib/run_loop.cc b/chromium/mojo/public/cpp/utility/lib/run_loop.cc
new file mode 100644
index 00000000000..f523eaeaead
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/lib/run_loop.cc
@@ -0,0 +1,221 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/run_loop.h"
+
+#include <assert.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "mojo/public/cpp/utility/lib/thread_local.h"
+#include "mojo/public/cpp/utility/run_loop_handler.h"
+
+namespace mojo {
+namespace {
+
+internal::ThreadLocalPointer<RunLoop> current_run_loop;
+
+const MojoTimeTicks kInvalidTimeTicks = static_cast<MojoTimeTicks>(0);
+
+} // namespace
+
+// State needed for one iteration of WaitMany().
+struct RunLoop::WaitState {
+ WaitState() : deadline(MOJO_DEADLINE_INDEFINITE) {}
+
+ std::vector<Handle> handles;
+ std::vector<MojoHandleSignals> handle_signals;
+ MojoDeadline deadline;
+};
+
+struct RunLoop::RunState {
+ RunState() : should_quit(false) {}
+
+ bool should_quit;
+};
+
+RunLoop::RunLoop() : run_state_(NULL), next_handler_id_(0) {
+ assert(!current());
+ current_run_loop.Set(this);
+}
+
+RunLoop::~RunLoop() {
+ assert(current() == this);
+ current_run_loop.Set(NULL);
+}
+
+// static
+void RunLoop::SetUp() {
+ current_run_loop.Allocate();
+}
+
+// static
+void RunLoop::TearDown() {
+ assert(!current());
+ current_run_loop.Free();
+}
+
+// static
+RunLoop* RunLoop::current() {
+ return current_run_loop.Get();
+}
+
+void RunLoop::AddHandler(RunLoopHandler* handler,
+ const Handle& handle,
+ MojoHandleSignals handle_signals,
+ MojoDeadline deadline) {
+ assert(current() == this);
+ assert(handler);
+ assert(handle.is_valid());
+ // Assume it's an error if someone tries to reregister an existing handle.
+ assert(0u == handler_data_.count(handle));
+ HandlerData handler_data;
+ handler_data.handler = handler;
+ handler_data.handle_signals = handle_signals;
+ handler_data.deadline = (deadline == MOJO_DEADLINE_INDEFINITE) ?
+ kInvalidTimeTicks :
+ GetTimeTicksNow() + static_cast<MojoTimeTicks>(deadline);
+ handler_data.id = next_handler_id_++;
+ handler_data_[handle] = handler_data;
+}
+
+void RunLoop::RemoveHandler(const Handle& handle) {
+ assert(current() == this);
+ handler_data_.erase(handle);
+}
+
+bool RunLoop::HasHandler(const Handle& handle) const {
+ return handler_data_.find(handle) != handler_data_.end();
+}
+
+void RunLoop::Run() {
+ assert(current() == this);
+ RunState* old_state = run_state_;
+ RunState run_state;
+ run_state_ = &run_state;
+ while (!run_state.should_quit)
+ Wait(false);
+ run_state_ = old_state;
+}
+
+void RunLoop::RunUntilIdle() {
+ assert(current() == this);
+ RunState* old_state = run_state_;
+ RunState run_state;
+ run_state_ = &run_state;
+ while (!run_state.should_quit) {
+ if (!Wait(true))
+ break;
+ }
+ run_state_ = old_state;
+}
+
+void RunLoop::Quit() {
+ assert(current() == this);
+ if (run_state_)
+ run_state_->should_quit = true;
+}
+
+bool RunLoop::Wait(bool non_blocking) {
+ const WaitState wait_state = GetWaitState(non_blocking);
+ if (wait_state.handles.empty()) {
+ Quit();
+ return false;
+ }
+
+ const MojoResult result = WaitMany(wait_state.handles,
+ wait_state.handle_signals,
+ wait_state.deadline);
+ if (result >= 0) {
+ const size_t index = static_cast<size_t>(result);
+ assert(handler_data_.find(wait_state.handles[index]) !=
+ handler_data_.end());
+ handler_data_[wait_state.handles[index]].handler->OnHandleReady(
+ wait_state.handles[index]);
+ return true;
+ }
+
+ switch (result) {
+ case MOJO_RESULT_INVALID_ARGUMENT:
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ return RemoveFirstInvalidHandle(wait_state);
+ case MOJO_RESULT_DEADLINE_EXCEEDED:
+ return NotifyDeadlineExceeded();
+ }
+
+ assert(false);
+ return false;
+}
+
+bool RunLoop::NotifyDeadlineExceeded() {
+ bool notified = false;
+
+ // Make a copy in case someone tries to add/remove new handlers as part of
+ // notifying.
+ const HandleToHandlerData cloned_handlers(handler_data_);
+ const MojoTimeTicks now(GetTimeTicksNow());
+ for (HandleToHandlerData::const_iterator i = cloned_handlers.begin();
+ i != cloned_handlers.end(); ++i) {
+ // Since we're iterating over a clone of the handlers, verify the handler is
+ // still valid before notifying.
+ if (i->second.deadline != kInvalidTimeTicks &&
+ i->second.deadline < now &&
+ handler_data_.find(i->first) != handler_data_.end() &&
+ handler_data_[i->first].id == i->second.id) {
+ handler_data_.erase(i->first);
+ i->second.handler->OnHandleError(i->first, MOJO_RESULT_DEADLINE_EXCEEDED);
+ notified = true;
+ }
+ }
+
+ return notified;
+}
+
+bool RunLoop::RemoveFirstInvalidHandle(const WaitState& wait_state) {
+ for (size_t i = 0; i < wait_state.handles.size(); ++i) {
+ const MojoResult result =
+ mojo::Wait(wait_state.handles[i], wait_state.handle_signals[i],
+ static_cast<MojoDeadline>(0));
+ if (result == MOJO_RESULT_INVALID_ARGUMENT ||
+ result == MOJO_RESULT_FAILED_PRECONDITION) {
+ // Remove the handle first, this way if OnHandleError() tries to remove
+ // the handle our iterator isn't invalidated.
+ assert(handler_data_.find(wait_state.handles[i]) != handler_data_.end());
+ RunLoopHandler* handler =
+ handler_data_[wait_state.handles[i]].handler;
+ handler_data_.erase(wait_state.handles[i]);
+ handler->OnHandleError(wait_state.handles[i], result);
+ return true;
+ }
+ assert(MOJO_RESULT_DEADLINE_EXCEEDED == result);
+ }
+ return false;
+}
+
+RunLoop::WaitState RunLoop::GetWaitState(bool non_blocking) const {
+ WaitState wait_state;
+ MojoTimeTicks min_time = kInvalidTimeTicks;
+ for (HandleToHandlerData::const_iterator i = handler_data_.begin();
+ i != handler_data_.end(); ++i) {
+ wait_state.handles.push_back(i->first);
+ wait_state.handle_signals.push_back(i->second.handle_signals);
+ if (!non_blocking && i->second.deadline != kInvalidTimeTicks &&
+ (min_time == kInvalidTimeTicks || i->second.deadline < min_time)) {
+ min_time = i->second.deadline;
+ }
+ }
+ if (non_blocking) {
+ wait_state.deadline = static_cast<MojoDeadline>(0);
+ } else if (min_time != kInvalidTimeTicks) {
+ const MojoTimeTicks now = GetTimeTicksNow();
+ if (min_time < now)
+ wait_state.deadline = static_cast<MojoDeadline>(0);
+ else
+ wait_state.deadline = static_cast<MojoDeadline>(min_time - now);
+ }
+ return wait_state;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/utility/lib/thread.cc b/chromium/mojo/public/cpp/utility/lib/thread.cc
new file mode 100644
index 00000000000..da33497df42
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/lib/thread.cc
@@ -0,0 +1,69 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/thread.h"
+
+#include <assert.h>
+
+namespace mojo {
+
+Thread::Thread()
+ : options_(),
+ thread_(),
+ started_(false),
+ joined_(false) {
+}
+
+Thread::Thread(const Options& options)
+ : options_(options),
+ thread_(),
+ started_(false),
+ joined_(false) {
+}
+
+Thread::~Thread() {
+ // If it was started, it must have been joined.
+ assert(!started_ || joined_);
+}
+
+void Thread::Start() {
+ assert(!started_);
+ assert(!joined_);
+
+ pthread_attr_t attr;
+ int rv MOJO_ALLOW_UNUSED = pthread_attr_init(&attr);
+ assert(rv == 0);
+
+ // Non-default stack size?
+ if (options_.stack_size() != 0) {
+ rv = pthread_attr_setstacksize(&attr, options_.stack_size());
+ assert(rv == 0);
+ }
+
+ started_ = true;
+ rv = pthread_create(&thread_, &attr, &ThreadRunTrampoline, this);
+ assert(rv == 0);
+
+ rv = pthread_attr_destroy(&attr);
+ assert(rv == 0);
+}
+
+void Thread::Join() {
+ // Must have been started but not yet joined.
+ assert(started_);
+ assert(!joined_);
+
+ joined_ = true;
+ int rv MOJO_ALLOW_UNUSED = pthread_join(thread_, NULL);
+ assert(rv == 0);
+}
+
+// static
+void* Thread::ThreadRunTrampoline(void* arg) {
+ Thread* self = static_cast<Thread*>(arg);
+ self->Run();
+ return NULL;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/utility/lib/thread_local.h b/chromium/mojo/public/cpp/utility/lib/thread_local.h
new file mode 100644
index 00000000000..4c3625d00d8
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/lib/thread_local.h
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_LIB_THREAD_LOCAL_H_
+#define MOJO_PUBLIC_CPP_UTILITY_LIB_THREAD_LOCAL_H_
+
+#ifndef _WIN32
+#include <pthread.h>
+#endif
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+// Helper functions that abstract the cross-platform APIs.
+struct ThreadLocalPlatform {
+#ifdef _WIN32
+ typedef unsigned long SlotType;
+#else
+ typedef pthread_key_t SlotType;
+#endif
+
+ static void AllocateSlot(SlotType* slot);
+ static void FreeSlot(SlotType slot);
+ static void* GetValueFromSlot(SlotType slot);
+ static void SetValueInSlot(SlotType slot, void* value);
+};
+
+// This class is intended to be statically allocated.
+template <typename P>
+class ThreadLocalPointer {
+ public:
+ ThreadLocalPointer() : slot_() {
+ }
+
+ void Allocate() {
+ ThreadLocalPlatform::AllocateSlot(&slot_);
+ }
+
+ void Free() {
+ ThreadLocalPlatform::FreeSlot(slot_);
+ }
+
+ P* Get() {
+ return static_cast<P*>(ThreadLocalPlatform::GetValueFromSlot(slot_));
+ }
+
+ void Set(P* value) {
+ ThreadLocalPlatform::SetValueInSlot(slot_, value);
+ }
+
+ private:
+ ThreadLocalPlatform::SlotType slot_;
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_UTILITY_LIB_THREAD_LOCAL_H_
diff --git a/chromium/mojo/public/cpp/utility/lib/thread_local_posix.cc b/chromium/mojo/public/cpp/utility/lib/thread_local_posix.cc
new file mode 100644
index 00000000000..b33dfc61297
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/lib/thread_local_posix.cc
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/lib/thread_local.h"
+
+#include <assert.h>
+
+namespace mojo {
+namespace internal {
+
+// static
+void ThreadLocalPlatform::AllocateSlot(SlotType* slot) {
+ if (pthread_key_create(slot, NULL) != 0) {
+ assert(false);
+ }
+}
+
+// static
+void ThreadLocalPlatform::FreeSlot(SlotType slot) {
+ if (pthread_key_delete(slot) != 0) {
+ assert(false);
+ }
+}
+
+// static
+void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) {
+ return pthread_getspecific(slot);
+}
+
+// static
+void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) {
+ if (pthread_setspecific(slot, value) != 0) {
+ assert(false);
+ }
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/utility/lib/thread_local_win.cc b/chromium/mojo/public/cpp/utility/lib/thread_local_win.cc
new file mode 100644
index 00000000000..98841f7273a
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/lib/thread_local_win.cc
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/lib/thread_local.h"
+
+#include <assert.h>
+#include <windows.h>
+
+namespace mojo {
+namespace internal {
+
+// static
+void ThreadLocalPlatform::AllocateSlot(SlotType* slot) {
+ *slot = TlsAlloc();
+ assert(*slot != TLS_OUT_OF_INDEXES);
+}
+
+// static
+void ThreadLocalPlatform::FreeSlot(SlotType slot) {
+ if (!TlsFree(slot)) {
+ assert(false);
+ }
+}
+
+// static
+void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) {
+ return TlsGetValue(slot);
+}
+
+// static
+void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) {
+ if (!TlsSetValue(slot, value)) {
+ assert(false);
+ }
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/utility/mutex.h b/chromium/mojo/public/cpp/utility/mutex.h
new file mode 100644
index 00000000000..35611c2ba9a
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/mutex.h
@@ -0,0 +1,70 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_MUTEX_H_
+#define MOJO_PUBLIC_CPP_UTILITY_MUTEX_H_
+
+#ifdef _WIN32
+#error "Not implemented: See crbug.com/342893."
+#endif
+
+#include <pthread.h>
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+#ifdef NDEBUG
+// Note: Make a C++ constant for |PTHREAD_MUTEX_INITIALIZER|. (We can't directly
+// use the C macro in an initializer list, since it might expand to |{ ... }|.)
+namespace internal {
+const pthread_mutex_t kPthreadMutexInitializer = PTHREAD_MUTEX_INITIALIZER;
+}
+#endif
+
+class Mutex {
+ public:
+#ifdef NDEBUG
+ Mutex() : mutex_(internal::kPthreadMutexInitializer) {}
+ ~Mutex() { pthread_mutex_destroy(&mutex_); }
+
+ void Lock() { pthread_mutex_lock(&mutex_); }
+ void Unlock() { pthread_mutex_unlock(&mutex_); }
+ bool TryLock() { return pthread_mutex_trylock(&mutex_) == 0; }
+
+ void AssertHeld() {}
+#else
+ Mutex();
+ ~Mutex();
+
+ void Lock();
+ void Unlock();
+ bool TryLock();
+
+ void AssertHeld();
+#endif
+
+ private:
+ pthread_mutex_t mutex_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Mutex);
+};
+
+class MutexLock {
+ public:
+ explicit MutexLock(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
+ ~MutexLock() { mutex_->Unlock(); }
+
+ private:
+ Mutex* const mutex_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(MutexLock);
+};
+
+// Catch bug where variable name is omitted (e.g., |MutexLock (&mu)|).
+#define MutexLock(x) MOJO_COMPILE_ASSERT(0, mutex_lock_missing_variable_name);
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_UTILITY_MUTEX_H_
diff --git a/chromium/mojo/public/cpp/utility/run_loop.h b/chromium/mojo/public/cpp/utility/run_loop.h
new file mode 100644
index 00000000000..74f870abc57
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/run_loop.h
@@ -0,0 +1,108 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
+#define MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
+
+#include <map>
+
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+class RunLoopHandler;
+
+class RunLoop {
+ public:
+ RunLoop();
+ ~RunLoop();
+
+ // Sets up state needed for RunLoop. This must be invoked before creating a
+ // RunLoop.
+ static void SetUp();
+
+ // Cleans state created by Setup().
+ static void TearDown();
+
+ // Returns the RunLoop for the current thread. Returns NULL if not yet
+ // created.
+ static RunLoop* current();
+
+ // Registers a RunLoopHandler for the specified handle. Only one handler can
+ // be registered for a specified handle.
+ void AddHandler(RunLoopHandler* handler,
+ const Handle& handle,
+ MojoHandleSignals handle_signals,
+ MojoDeadline deadline);
+ void RemoveHandler(const Handle& handle);
+ bool HasHandler(const Handle& handle) const;
+
+ // Runs the loop servicing handles as they are ready. This returns when Quit()
+ // is invoked, or there no more handles.
+ void Run();
+
+ // Runs the loop servicing any handles that are ready. Does not wait for
+ // handles to become ready before returning. Returns early if Quit() is
+ // invoked.
+ void RunUntilIdle();
+
+ void Quit();
+
+ private:
+ struct RunState;
+ struct WaitState;
+
+ // Contains the data needed to track a request to AddHandler().
+ struct HandlerData {
+ HandlerData()
+ : handler(NULL),
+ handle_signals(MOJO_HANDLE_SIGNAL_NONE),
+ deadline(0),
+ id(0) {}
+
+ RunLoopHandler* handler;
+ MojoHandleSignals handle_signals;
+ MojoTimeTicks deadline;
+ // See description of |RunLoop::next_handler_id_| for details.
+ int id;
+ };
+
+ typedef std::map<Handle, HandlerData> HandleToHandlerData;
+
+ // Waits for a handle to be ready. Returns after servicing at least one
+ // handle (or there are no more handles) unless |non_blocking| is true,
+ // in which case it will also return if servicing at least one handle
+ // would require blocking. Returns true if a RunLoopHandler was notified.
+ bool Wait(bool non_blocking);
+
+ // Notifies any handlers whose deadline has expired. Returns true if a
+ // RunLoopHandler was notified.
+ bool NotifyDeadlineExceeded();
+
+ // Removes the first invalid handle. This is called if MojoWaitMany() finds an
+ // invalid handle. Returns true if a RunLoopHandler was notified.
+ bool RemoveFirstInvalidHandle(const WaitState& wait_state);
+
+ // Returns the state needed to pass to WaitMany().
+ WaitState GetWaitState(bool non_blocking) const;
+
+ HandleToHandlerData handler_data_;
+
+ // If non-NULL we're running (inside Run()). Member references a value on the
+ // stack.
+ RunState* run_state_;
+
+ // An ever increasing value assigned to each HandlerData::id. Used to detect
+ // uniqueness while notifying. That is, while notifying expired timers we copy
+ // |handler_data_| and only notify handlers whose id match. If the id does not
+ // match it means the handler was removed then added so that we shouldn't
+ // notify it.
+ int next_handler_id_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoop);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
diff --git a/chromium/mojo/public/cpp/utility/run_loop_handler.h b/chromium/mojo/public/cpp/utility/run_loop_handler.h
new file mode 100644
index 00000000000..69838d5e57c
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/run_loop_handler.h
@@ -0,0 +1,25 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_HANDLER_H_
+#define MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_HANDLER_H_
+
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+// Used by RunLoop to notify when a handle is either ready or has become
+// invalid.
+class RunLoopHandler {
+ public:
+ virtual void OnHandleReady(const Handle& handle) = 0;
+ virtual void OnHandleError(const Handle& handle, MojoResult result) = 0;
+
+ protected:
+ virtual ~RunLoopHandler() {}
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_HANDLER_H_
diff --git a/chromium/mojo/public/cpp/utility/thread.h b/chromium/mojo/public/cpp/utility/thread.h
new file mode 100644
index 00000000000..b7d10ee7037
--- /dev/null
+++ b/chromium/mojo/public/cpp/utility/thread.h
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_THREAD_H_
+#define MOJO_PUBLIC_CPP_UTILITY_THREAD_H_
+
+#ifdef _WIN32
+#error "Not implemented: See crbug.com/342893."
+#endif
+
+#include <pthread.h>
+#include <stddef.h>
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+// This class is thread-friendly, not thread-safe (e.g., you mustn't call
+// |Join()| from multiple threads and/or simultaneously try to destroy the
+// object).
+class Thread {
+ public:
+ // TODO(vtl): Support non-joinable? priority?
+ class Options {
+ public:
+ Options() : stack_size_(0) {}
+
+ // A stack size of 0 means the default.
+ size_t stack_size() const { return stack_size_; }
+ void set_stack_size(size_t stack_size) { stack_size_ = stack_size; }
+
+ private:
+ size_t stack_size_;
+
+ // Copy and assign allowed.
+ };
+
+ // TODO(vtl): Add name or name prefix?
+ Thread();
+ explicit Thread(const Options& options);
+ virtual ~Thread();
+
+ void Start();
+ void Join();
+
+ virtual void Run() = 0;
+
+ private:
+ static void* ThreadRunTrampoline(void* arg);
+
+ const Options options_;
+ pthread_t thread_;
+ bool started_;
+ bool joined_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(Thread);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_UTILITY_THREAD_H_
diff --git a/chromium/mojo/public/gles2/gles2_interface.h b/chromium/mojo/public/gles2/gles2_interface.h
new file mode 100644
index 00000000000..19b958ec112
--- /dev/null
+++ b/chromium/mojo/public/gles2/gles2_interface.h
@@ -0,0 +1,23 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_GLES2_GLES2_INTERFACE_H_
+#define MOJO_PUBLIC_GLES2_GLES2_INTERFACE_H_
+
+#include <GLES2/gl2.h>
+
+namespace mojo {
+
+class GLES2Interface {
+ public:
+ virtual ~GLES2Interface() {}
+#define VISIT_GL_CALL(Function, ReturnType, PARAMETERS, ARGUMENTS) \
+ virtual ReturnType Function PARAMETERS = 0;
+#include "mojo/public/c/gles2/gles2_call_visitor_autogen.h"
+#undef VISIT_GL_CALL
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_GLES2_GLES2_INTERFACE_H_
diff --git a/chromium/mojo/public/gles2/gles2_private.cc b/chromium/mojo/public/gles2/gles2_private.cc
new file mode 100644
index 00000000000..52b47d36c3f
--- /dev/null
+++ b/chromium/mojo/public/gles2/gles2_private.cc
@@ -0,0 +1,92 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/gles2/gles2_private.h"
+
+#include <assert.h>
+#include <stddef.h>
+
+#include "mojo/public/c/gles2/gles2.h"
+#include "mojo/public/gles2/gles2_interface.h"
+
+static mojo::GLES2Support* g_gles2_support = NULL;
+static mojo::GLES2Interface* g_gles2_interface = NULL;
+
+extern "C" {
+
+void MojoGLES2Initialize(const MojoAsyncWaiter* async_waiter) {
+ assert(g_gles2_support);
+ return g_gles2_support->Initialize(async_waiter);
+}
+
+void MojoGLES2Terminate() {
+ assert(g_gles2_support);
+ return g_gles2_support->Terminate();
+}
+
+MojoGLES2Context MojoGLES2CreateContext(
+ MojoHandle handle,
+ MojoGLES2ContextLost lost_callback,
+ MojoGLES2DrawAnimationFrame animation_callback,
+ void* closure) {
+ return g_gles2_support->CreateContext(mojo::MessagePipeHandle(handle),
+ lost_callback,
+ animation_callback,
+ closure);
+}
+
+void MojoGLES2DestroyContext(MojoGLES2Context context) {
+ return g_gles2_support->DestroyContext(context);
+}
+
+void MojoGLES2MakeCurrent(MojoGLES2Context context) {
+ assert(g_gles2_support);
+ g_gles2_support->MakeCurrent(context);
+ g_gles2_interface = g_gles2_support->GetGLES2InterfaceForCurrentContext();
+}
+
+void MojoGLES2SwapBuffers() {
+ assert(g_gles2_support);
+ return g_gles2_support->SwapBuffers();
+}
+
+void MojoGLES2RequestAnimationFrames(MojoGLES2Context context) {
+ assert(g_gles2_support);
+ return g_gles2_support->RequestAnimationFrames(context);
+}
+
+void MojoGLES2CancelAnimationFrames(MojoGLES2Context context) {
+ assert(g_gles2_support);
+ return g_gles2_support->CancelAnimationFrames(context);
+}
+
+void* MojoGLES2GetGLES2Interface(MojoGLES2Context context) {
+ assert(g_gles2_support);
+ return g_gles2_support->GetGLES2Interface(context);
+}
+
+void* MojoGLES2GetContextSupport(MojoGLES2Context context) {
+ assert(g_gles2_support);
+ return g_gles2_support->GetContextSupport(context);
+}
+
+#define VISIT_GL_CALL(Function, ReturnType, PARAMETERS, ARGUMENTS) \
+ ReturnType gl##Function PARAMETERS { \
+ return g_gles2_interface->Function ARGUMENTS; \
+ }
+#include "mojo/public/c/gles2/gles2_call_visitor_autogen.h"
+#undef VISIT_GL_CALL
+
+} // extern "C"
+
+namespace mojo {
+
+GLES2Support::~GLES2Support() {}
+
+void GLES2Support::Init(GLES2Support* gles2_support) {
+ assert(!g_gles2_support);
+ g_gles2_support = gles2_support;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/gles2/gles2_private.h b/chromium/mojo/public/gles2/gles2_private.h
new file mode 100644
index 00000000000..f0a336d60e6
--- /dev/null
+++ b/chromium/mojo/public/gles2/gles2_private.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_GLES2_GLES2_PRIVATE_H_
+#define MOJO_PUBLIC_GLES2_GLES2_PRIVATE_H_
+
+#include <stdint.h>
+
+#include "mojo/public/c/environment/async_waiter.h"
+#include "mojo/public/c/gles2/gles2_export.h"
+#include "mojo/public/c/gles2/gles2_types.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+class GLES2Interface;
+
+// Implementors of the GLES2 APIs can use this interface to install their
+// implementation into the mojo_gles2 dynamic library. Mojo clients should not
+// call these functions directly.
+class MOJO_GLES2_EXPORT GLES2Support {
+ public:
+ virtual ~GLES2Support();
+
+ static void Init(GLES2Support* gles2_support);
+
+ virtual void Initialize(const MojoAsyncWaiter* async_waiter) = 0;
+ virtual void Terminate() = 0;
+ virtual MojoGLES2Context CreateContext(
+ MessagePipeHandle handle,
+ MojoGLES2ContextLost lost_callback,
+ MojoGLES2DrawAnimationFrame animation_callback,
+ void* closure) = 0;
+ virtual void DestroyContext(MojoGLES2Context context) = 0;
+ virtual void MakeCurrent(MojoGLES2Context context) = 0;
+ virtual void SwapBuffers() = 0;
+ virtual void RequestAnimationFrames(MojoGLES2Context context) = 0;
+ virtual void CancelAnimationFrames(MojoGLES2Context context) = 0;
+ virtual void* GetGLES2Interface(MojoGLES2Context context) = 0;
+ virtual void* GetContextSupport(MojoGLES2Context context) = 0;
+ virtual GLES2Interface* GetGLES2InterfaceForCurrentContext() = 0;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_GLES2_GLES2_PRIVATE_H_
diff --git a/chromium/mojo/public/interfaces/interface_provider/BUILD.gn b/chromium/mojo/public/interfaces/interface_provider/BUILD.gn
new file mode 100644
index 00000000000..55d5b0a37da
--- /dev/null
+++ b/chromium/mojo/public/interfaces/interface_provider/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("interface_provider") {
+ sources = [
+ "interface_provider.mojom",
+ ]
+}
diff --git a/chromium/mojo/public/interfaces/interface_provider/interface_provider.mojom b/chromium/mojo/public/interfaces/interface_provider/interface_provider.mojom
new file mode 100644
index 00000000000..91e32813da6
--- /dev/null
+++ b/chromium/mojo/public/interfaces/interface_provider/interface_provider.mojom
@@ -0,0 +1,12 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mojo {
+
+[Client=IInterfaceProvider]
+interface IInterfaceProvider {
+ GetInterface(string name, handle<message_pipe> client_handle);
+};
+
+}
diff --git a/chromium/mojo/public/interfaces/service_provider/BUILD.gn b/chromium/mojo/public/interfaces/service_provider/BUILD.gn
new file mode 100644
index 00000000000..990d3e9b626
--- /dev/null
+++ b/chromium/mojo/public/interfaces/service_provider/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("service_provider") {
+ sources = [
+ "service_provider.mojom",
+ ]
+}
diff --git a/chromium/mojo/public/interfaces/service_provider/service_provider.mojom b/chromium/mojo/public/interfaces/service_provider/service_provider.mojom
new file mode 100644
index 00000000000..190c85c2d78
--- /dev/null
+++ b/chromium/mojo/public/interfaces/service_provider/service_provider.mojom
@@ -0,0 +1,19 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mojo {
+
+[Client=ServiceProvider]
+interface ServiceProvider {
+ // Loads url. mojo:{service} will result in the user of the value of the
+ // --origin flag to the shell being used.
+ ConnectToService(string service_url,
+ string service_name,
+ handle<message_pipe> client_handle,
+ // ignored for client making request, filled in by system for
+ // implementor.
+ string requestor_url);
+};
+
+}
diff --git a/chromium/mojo/public/interfaces/shell/BUILD.gn b/chromium/mojo/public/interfaces/shell/BUILD.gn
new file mode 100644
index 00000000000..c11ae70a311
--- /dev/null
+++ b/chromium/mojo/public/interfaces/shell/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("shell") {
+ sources = [
+ "shell.mojom",
+ ]
+}
diff --git a/chromium/mojo/public/js/bindings/BUILD.gn b/chromium/mojo/public/js/bindings/BUILD.gn
new file mode 100644
index 00000000000..0f305e924ec
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/BUILD.gn
@@ -0,0 +1,10 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("bindings") {
+ sources = [
+ "constants.cc",
+ "constants.h",
+ ]
+}
diff --git a/chromium/mojo/public/js/bindings/codec.js b/chromium/mojo/public/js/bindings/codec.js
new file mode 100644
index 00000000000..84c86c12991
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/codec.js
@@ -0,0 +1,739 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+define("mojo/public/js/bindings/codec", [
+ "mojo/public/js/bindings/unicode"
+], function(unicode) {
+
+ var kErrorUnsigned = "Passing negative value to unsigned";
+
+ // Memory -------------------------------------------------------------------
+
+ var kAlignment = 8;
+ var kHighWordMultiplier = 0x100000000;
+ var kHostIsLittleEndian = (function () {
+ var endianArrayBuffer = new ArrayBuffer(2);
+ var endianUint8Array = new Uint8Array(endianArrayBuffer);
+ var endianUint16Array = new Uint16Array(endianArrayBuffer);
+ endianUint16Array[0] = 1;
+ return endianUint8Array[0] == 1;
+ })();
+
+ function align(size) {
+ return size + (kAlignment - (size % kAlignment)) % kAlignment;
+ }
+
+ function getInt64(dataView, byteOffset, value) {
+ var lo, hi;
+ if (kHostIsLittleEndian) {
+ lo = dataView.getUint32(byteOffset, kHostIsLittleEndian);
+ hi = dataView.getInt32(byteOffset + 4, kHostIsLittleEndian);
+ } else {
+ hi = dataView.getInt32(byteOffset, kHostIsLittleEndian);
+ lo = dataView.getUint32(byteOffset + 4, kHostIsLittleEndian);
+ }
+ return lo + hi * kHighWordMultiplier;
+ }
+
+ function getUint64(dataView, byteOffset, value) {
+ var lo, hi;
+ if (kHostIsLittleEndian) {
+ lo = dataView.getUint32(byteOffset, kHostIsLittleEndian);
+ hi = dataView.getUint32(byteOffset + 4, kHostIsLittleEndian);
+ } else {
+ hi = dataView.getUint32(byteOffset, kHostIsLittleEndian);
+ lo = dataView.getUint32(byteOffset + 4, kHostIsLittleEndian);
+ }
+ return lo + hi * kHighWordMultiplier;
+ }
+
+ function setInt64(dataView, byteOffset, value) {
+ var hi = Math.floor(value / kHighWordMultiplier);
+ if (kHostIsLittleEndian) {
+ dataView.setInt32(byteOffset, value, kHostIsLittleEndian);
+ dataView.setInt32(byteOffset + 4, hi, kHostIsLittleEndian);
+ } else {
+ dataView.setInt32(byteOffset, hi, kHostIsLittleEndian);
+ dataView.setInt32(byteOffset + 4, value, kHostIsLittleEndian);
+ }
+ }
+
+ function setUint64(dataView, byteOffset, value) {
+ var hi = (value / kHighWordMultiplier) | 0;
+ if (kHostIsLittleEndian) {
+ dataView.setInt32(byteOffset, value, kHostIsLittleEndian);
+ dataView.setInt32(byteOffset + 4, hi, kHostIsLittleEndian);
+ } else {
+ dataView.setInt32(byteOffset, hi, kHostIsLittleEndian);
+ dataView.setInt32(byteOffset + 4, value, kHostIsLittleEndian);
+ }
+ }
+
+ function copyArrayBuffer(dstArrayBuffer, srcArrayBuffer) {
+ (new Uint8Array(dstArrayBuffer)).set(new Uint8Array(srcArrayBuffer));
+ }
+
+ // Buffer -------------------------------------------------------------------
+
+ function Buffer(sizeOrArrayBuffer) {
+ if (sizeOrArrayBuffer instanceof ArrayBuffer) {
+ this.arrayBuffer = sizeOrArrayBuffer;
+ } else {
+ this.arrayBuffer = new ArrayBuffer(sizeOrArrayBuffer);
+ };
+
+ this.dataView = new DataView(this.arrayBuffer);
+ this.next = 0;
+ }
+
+ Buffer.prototype.alloc = function(size) {
+ var pointer = this.next;
+ this.next += size;
+ if (this.next > this.arrayBuffer.byteLength) {
+ var newSize = (1.5 * (this.arrayBuffer.byteLength + size)) | 0;
+ this.grow(newSize);
+ }
+ return pointer;
+ };
+
+ Buffer.prototype.grow = function(size) {
+ var newArrayBuffer = new ArrayBuffer(size);
+ copyArrayBuffer(newArrayBuffer, this.arrayBuffer);
+ this.arrayBuffer = newArrayBuffer;
+ this.dataView = new DataView(this.arrayBuffer);
+ };
+
+ Buffer.prototype.trim = function() {
+ this.arrayBuffer = this.arrayBuffer.slice(0, this.next);
+ this.dataView = new DataView(this.arrayBuffer);
+ };
+
+ // Constants ----------------------------------------------------------------
+
+ var kArrayHeaderSize = 8;
+ var kStructHeaderSize = 8;
+ var kMessageHeaderSize = 16;
+ var kMessageWithRequestIDHeaderSize = 24;
+
+ // Decoder ------------------------------------------------------------------
+
+ function Decoder(buffer, handles, base) {
+ this.buffer = buffer;
+ this.handles = handles;
+ this.base = base;
+ this.next = base;
+ }
+
+ Decoder.prototype.skip = function(offset) {
+ this.next += offset;
+ };
+
+ Decoder.prototype.readInt8 = function() {
+ var result = this.buffer.dataView.getInt8(this.next, kHostIsLittleEndian);
+ this.next += 1;
+ return result;
+ };
+
+ Decoder.prototype.readUint8 = function() {
+ var result = this.buffer.dataView.getUint8(this.next, kHostIsLittleEndian);
+ this.next += 1;
+ return result;
+ };
+
+ Decoder.prototype.readInt16 = function() {
+ var result = this.buffer.dataView.getInt16(this.next, kHostIsLittleEndian);
+ this.next += 2;
+ return result;
+ };
+
+ Decoder.prototype.readUint16 = function() {
+ var result = this.buffer.dataView.getUint16(this.next, kHostIsLittleEndian);
+ this.next += 2;
+ return result;
+ };
+
+ Decoder.prototype.readInt32 = function() {
+ var result = this.buffer.dataView.getInt32(this.next, kHostIsLittleEndian);
+ this.next += 4;
+ return result;
+ };
+
+ Decoder.prototype.readUint32 = function() {
+ var result = this.buffer.dataView.getUint32(this.next, kHostIsLittleEndian);
+ this.next += 4;
+ return result;
+ };
+
+ Decoder.prototype.readInt64 = function() {
+ var result = getInt64(this.buffer.dataView, this.next, kHostIsLittleEndian);
+ this.next += 8;
+ return result;
+ };
+
+ Decoder.prototype.readUint64 = function() {
+ var result = getUint64(
+ this.buffer.dataView, this.next, kHostIsLittleEndian);
+ this.next += 8;
+ return result;
+ };
+
+ Decoder.prototype.readFloat = function() {
+ var result = this.buffer.dataView.getFloat32(
+ this.next, kHostIsLittleEndian);
+ this.next += 4;
+ return result;
+ };
+
+ Decoder.prototype.readDouble = function() {
+ var result = this.buffer.dataView.getFloat64(
+ this.next, kHostIsLittleEndian);
+ this.next += 8;
+ return result;
+ };
+
+ Decoder.prototype.decodePointer = function() {
+ // TODO(abarth): To correctly decode a pointer, we need to know the real
+ // base address of the array buffer.
+ var offsetPointer = this.next;
+ var offset = this.readUint64();
+ if (!offset)
+ return 0;
+ return offsetPointer + offset;
+ };
+
+ Decoder.prototype.decodeAndCreateDecoder = function(pointer) {
+ return new Decoder(this.buffer, this.handles, pointer);
+ };
+
+ Decoder.prototype.decodeHandle = function() {
+ return this.handles[this.readUint32()];
+ };
+
+ Decoder.prototype.decodeString = function() {
+ var numberOfBytes = this.readUint32();
+ var numberOfElements = this.readUint32();
+ var base = this.next;
+ this.next += numberOfElements;
+ return unicode.decodeUtf8String(
+ new Uint8Array(this.buffer.arrayBuffer, base, numberOfElements));
+ };
+
+ Decoder.prototype.decodeArray = function(cls) {
+ var numberOfBytes = this.readUint32();
+ var numberOfElements = this.readUint32();
+ var val = new Array(numberOfElements);
+ for (var i = 0; i < numberOfElements; ++i) {
+ val[i] = cls.decode(this);
+ }
+ return val;
+ };
+
+ Decoder.prototype.decodeStruct = function(cls) {
+ return cls.decode(this);
+ };
+
+ Decoder.prototype.decodeStructPointer = function(cls) {
+ var pointer = this.decodePointer();
+ if (!pointer) {
+ return null;
+ }
+ return cls.decode(this.decodeAndCreateDecoder(pointer));
+ };
+
+ Decoder.prototype.decodeArrayPointer = function(cls) {
+ var pointer = this.decodePointer();
+ if (!pointer) {
+ return null;
+ }
+ return this.decodeAndCreateDecoder(pointer).decodeArray(cls);
+ };
+
+ Decoder.prototype.decodeStringPointer = function() {
+ var pointer = this.decodePointer();
+ if (!pointer) {
+ return null;
+ }
+ return this.decodeAndCreateDecoder(pointer).decodeString();
+ };
+
+ // Encoder ------------------------------------------------------------------
+
+ function Encoder(buffer, handles, base) {
+ this.buffer = buffer;
+ this.handles = handles;
+ this.base = base;
+ this.next = base;
+ }
+
+ Encoder.prototype.skip = function(offset) {
+ this.next += offset;
+ };
+
+ Encoder.prototype.writeInt8 = function(val) {
+ // NOTE: Endianness doesn't come into play for single bytes.
+ this.buffer.dataView.setInt8(this.next, val);
+ this.next += 1;
+ };
+
+ Encoder.prototype.writeUint8 = function(val) {
+ if (val < 0) {
+ throw new Error(kErrorUnsigned);
+ }
+ // NOTE: Endianness doesn't come into play for single bytes.
+ this.buffer.dataView.setUint8(this.next, val);
+ this.next += 1;
+ };
+
+ Encoder.prototype.writeInt16 = function(val) {
+ this.buffer.dataView.setInt16(this.next, val, kHostIsLittleEndian);
+ this.next += 2;
+ };
+
+ Encoder.prototype.writeUint16 = function(val) {
+ if (val < 0) {
+ throw new Error(kErrorUnsigned);
+ }
+ this.buffer.dataView.setUint16(this.next, val, kHostIsLittleEndian);
+ this.next += 2;
+ };
+
+ Encoder.prototype.writeInt32 = function(val) {
+ this.buffer.dataView.setInt32(this.next, val, kHostIsLittleEndian);
+ this.next += 4;
+ };
+
+ Encoder.prototype.writeUint32 = function(val) {
+ if (val < 0) {
+ throw new Error(kErrorUnsigned);
+ }
+ this.buffer.dataView.setUint32(this.next, val, kHostIsLittleEndian);
+ this.next += 4;
+ };
+
+ Encoder.prototype.writeInt64 = function(val) {
+ setInt64(this.buffer.dataView, this.next, val);
+ this.next += 8;
+ };
+
+ Encoder.prototype.writeUint64 = function(val) {
+ if (val < 0) {
+ throw new Error(kErrorUnsigned);
+ }
+ setUint64(this.buffer.dataView, this.next, val);
+ this.next += 8;
+ };
+
+ Encoder.prototype.writeFloat = function(val) {
+ this.buffer.dataView.setFloat32(this.next, val, kHostIsLittleEndian);
+ this.next += 4;
+ };
+
+ Encoder.prototype.writeDouble = function(val) {
+ this.buffer.dataView.setFloat64(this.next, val, kHostIsLittleEndian);
+ this.next += 8;
+ };
+
+ Encoder.prototype.encodePointer = function(pointer) {
+ if (!pointer)
+ return this.writeUint64(0);
+ // TODO(abarth): To correctly encode a pointer, we need to know the real
+ // base address of the array buffer.
+ var offset = pointer - this.next;
+ this.writeUint64(offset);
+ };
+
+ Encoder.prototype.createAndEncodeEncoder = function(size) {
+ var pointer = this.buffer.alloc(align(size));
+ this.encodePointer(pointer);
+ return new Encoder(this.buffer, this.handles, pointer);
+ };
+
+ Encoder.prototype.encodeHandle = function(handle) {
+ this.handles.push(handle);
+ this.writeUint32(this.handles.length - 1);
+ };
+
+ Encoder.prototype.encodeString = function(val) {
+ var base = this.next + kArrayHeaderSize;
+ var numberOfElements = unicode.encodeUtf8String(
+ val, new Uint8Array(this.buffer.arrayBuffer, base));
+ var numberOfBytes = kArrayHeaderSize + numberOfElements;
+ this.writeUint32(numberOfBytes);
+ this.writeUint32(numberOfElements);
+ this.next += numberOfElements;
+ };
+
+ Encoder.prototype.encodeArray = function(cls, val) {
+ var numberOfElements = val.length;
+ var numberOfBytes = kArrayHeaderSize + cls.encodedSize * numberOfElements;
+ this.writeUint32(numberOfBytes);
+ this.writeUint32(numberOfElements);
+ for (var i = 0; i < numberOfElements; ++i) {
+ cls.encode(this, val[i]);
+ }
+ };
+
+ Encoder.prototype.encodeStruct = function(cls, val) {
+ return cls.encode(this, val);
+ };
+
+ Encoder.prototype.encodeStructPointer = function(cls, val) {
+ if (!val) {
+ this.encodePointer(val);
+ return;
+ }
+ var encoder = this.createAndEncodeEncoder(cls.encodedSize);
+ cls.encode(encoder, val);
+ };
+
+ Encoder.prototype.encodeArrayPointer = function(cls, val) {
+ if (!val) {
+ this.encodePointer(val);
+ return;
+ }
+ var encodedSize = kArrayHeaderSize + cls.encodedSize * val.length;
+ var encoder = this.createAndEncodeEncoder(encodedSize);
+ encoder.encodeArray(cls, val);
+ };
+
+ Encoder.prototype.encodeStringPointer = function(val) {
+ if (!val) {
+ this.encodePointer(val);
+ return;
+ }
+ var encodedSize = kArrayHeaderSize + unicode.utf8Length(val);
+ var encoder = this.createAndEncodeEncoder(encodedSize);
+ encoder.encodeString(val);
+ };
+
+ // Message ------------------------------------------------------------------
+
+ var kMessageExpectsResponse = 1 << 0;
+ var kMessageIsResponse = 1 << 1;
+
+ // Skip over num_bytes, num_fields, and message_name.
+ var kFlagsOffset = 4 + 4 + 4;
+
+ // Skip over num_bytes, num_fields, message_name, and flags.
+ var kRequestIDOffset = 4 + 4 + 4 + 4;
+
+ function Message(buffer, handles) {
+ this.buffer = buffer;
+ this.handles = handles;
+ }
+
+ Message.prototype.setRequestID = function(requestID) {
+ // TODO(darin): Verify that space was reserved for this field!
+ setUint64(this.buffer.dataView, kRequestIDOffset, requestID);
+ };
+
+ Message.prototype.getFlags = function() {
+ return this.buffer.dataView.getUint32(kFlagsOffset, kHostIsLittleEndian);
+ };
+
+ // MessageBuilder -----------------------------------------------------------
+
+ function MessageBuilder(messageName, payloadSize) {
+ // Currently, we don't compute the payload size correctly ahead of time.
+ // Instead, we resize the buffer at the end.
+ var numberOfBytes = kMessageHeaderSize + payloadSize;
+ this.buffer = new Buffer(numberOfBytes);
+ this.handles = [];
+ var encoder = this.createEncoder(kMessageHeaderSize);
+ encoder.writeUint32(kMessageHeaderSize);
+ encoder.writeUint32(2); // num_fields.
+ encoder.writeUint32(messageName);
+ encoder.writeUint32(0); // flags.
+ }
+
+ MessageBuilder.prototype.createEncoder = function(size) {
+ var pointer = this.buffer.alloc(size);
+ return new Encoder(this.buffer, this.handles, pointer);
+ };
+
+ MessageBuilder.prototype.encodeStruct = function(cls, val) {
+ cls.encode(this.createEncoder(cls.encodedSize), val);
+ };
+
+ MessageBuilder.prototype.finish = function() {
+ // TODO(abarth): Rather than resizing the buffer at the end, we could
+ // compute the size we need ahead of time, like we do in C++.
+ this.buffer.trim();
+ var message = new Message(this.buffer, this.handles);
+ this.buffer = null;
+ this.handles = null;
+ this.encoder = null;
+ return message;
+ };
+
+ // MessageWithRequestIDBuilder -----------------------------------------------
+
+ function MessageWithRequestIDBuilder(messageName, payloadSize, flags,
+ requestID) {
+ // Currently, we don't compute the payload size correctly ahead of time.
+ // Instead, we resize the buffer at the end.
+ var numberOfBytes = kMessageWithRequestIDHeaderSize + payloadSize;
+ this.buffer = new Buffer(numberOfBytes);
+ this.handles = [];
+ var encoder = this.createEncoder(kMessageWithRequestIDHeaderSize);
+ encoder.writeUint32(kMessageWithRequestIDHeaderSize);
+ encoder.writeUint32(3); // num_fields.
+ encoder.writeUint32(messageName);
+ encoder.writeUint32(flags);
+ encoder.writeUint64(requestID);
+ }
+
+ MessageWithRequestIDBuilder.prototype =
+ Object.create(MessageBuilder.prototype);
+
+ MessageWithRequestIDBuilder.prototype.constructor =
+ MessageWithRequestIDBuilder;
+
+ // MessageReader ------------------------------------------------------------
+
+ function MessageReader(message) {
+ this.decoder = new Decoder(message.buffer, message.handles, 0);
+ var messageHeaderSize = this.decoder.readUint32();
+ this.payloadSize =
+ message.buffer.arrayBuffer.byteLength - messageHeaderSize;
+ var numFields = this.decoder.readUint32();
+ this.messageName = this.decoder.readUint32();
+ this.flags = this.decoder.readUint32();
+ if (numFields >= 3)
+ this.requestID = this.decoder.readUint64();
+ this.decoder.skip(messageHeaderSize - this.decoder.next);
+ }
+
+ MessageReader.prototype.decodeStruct = function(cls) {
+ return cls.decode(this.decoder);
+ };
+
+ // Built-in types -----------------------------------------------------------
+
+ function Int8() {
+ }
+
+ Int8.encodedSize = 1;
+
+ Int8.decode = function(decoder) {
+ return decoder.readInt8();
+ };
+
+ Int8.encode = function(encoder, val) {
+ encoder.writeInt8(val);
+ };
+
+ Uint8.encode = function(encoder, val) {
+ encoder.writeUint8(val);
+ };
+
+ function Uint8() {
+ }
+
+ Uint8.encodedSize = 1;
+
+ Uint8.decode = function(decoder) {
+ return decoder.readUint8();
+ };
+
+ Uint8.encode = function(encoder, val) {
+ encoder.writeUint8(val);
+ };
+
+ function Int16() {
+ }
+
+ Int16.encodedSize = 2;
+
+ Int16.decode = function(decoder) {
+ return decoder.readInt16();
+ };
+
+ Int16.encode = function(encoder, val) {
+ encoder.writeInt16(val);
+ };
+
+ function Uint16() {
+ }
+
+ Uint16.encodedSize = 2;
+
+ Uint16.decode = function(decoder) {
+ return decoder.readUint16();
+ };
+
+ Uint16.encode = function(encoder, val) {
+ encoder.writeUint16(val);
+ };
+
+ function Int32() {
+ }
+
+ Int32.encodedSize = 4;
+
+ Int32.decode = function(decoder) {
+ return decoder.readInt32();
+ };
+
+ Int32.encode = function(encoder, val) {
+ encoder.writeInt32(val);
+ };
+
+ function Uint32() {
+ }
+
+ Uint32.encodedSize = 4;
+
+ Uint32.decode = function(decoder) {
+ return decoder.readUint32();
+ };
+
+ Uint32.encode = function(encoder, val) {
+ encoder.writeUint32(val);
+ };
+
+ function Int64() {
+ }
+
+ Int64.encodedSize = 8;
+
+ Int64.decode = function(decoder) {
+ return decoder.readInt64();
+ };
+
+ Int64.encode = function(encoder, val) {
+ encoder.writeInt64(val);
+ };
+
+ function Uint64() {
+ }
+
+ Uint64.encodedSize = 8;
+
+ Uint64.decode = function(decoder) {
+ return decoder.readUint64();
+ };
+
+ Uint64.encode = function(encoder, val) {
+ encoder.writeUint64(val);
+ };
+
+ function String() {
+ };
+
+ String.encodedSize = 8;
+
+ String.decode = function(decoder) {
+ return decoder.decodeStringPointer();
+ };
+
+ String.encode = function(encoder, val) {
+ encoder.encodeStringPointer(val);
+ };
+
+
+ function Float() {
+ }
+
+ Float.encodedSize = 4;
+
+ Float.decode = function(decoder) {
+ return decoder.readFloat();
+ };
+
+ Float.encode = function(encoder, val) {
+ encoder.writeFloat(val);
+ };
+
+ function Double() {
+ }
+
+ Double.encodedSize = 8;
+
+ Double.decode = function(decoder) {
+ return decoder.readDouble();
+ };
+
+ Double.encode = function(encoder, val) {
+ encoder.writeDouble(val);
+ };
+
+ function PointerTo(cls) {
+ this.cls = cls;
+ }
+
+ PointerTo.prototype.encodedSize = 8;
+
+ PointerTo.prototype.decode = function(decoder) {
+ var pointer = decoder.decodePointer();
+ if (!pointer) {
+ return null;
+ }
+ return this.cls.decode(decoder.decodeAndCreateDecoder(pointer));
+ };
+
+ PointerTo.prototype.encode = function(encoder, val) {
+ if (!val) {
+ encoder.encodePointer(val);
+ return;
+ }
+ var objectEncoder = encoder.createAndEncodeEncoder(this.cls.encodedSize);
+ this.cls.encode(objectEncoder, val);
+ };
+
+ function ArrayOf(cls) {
+ this.cls = cls;
+ }
+
+ ArrayOf.prototype.encodedSize = 8;
+
+ ArrayOf.prototype.decode = function(decoder) {
+ return decoder.decodeArrayPointer(this.cls);
+ };
+
+ ArrayOf.prototype.encode = function(encoder, val) {
+ encoder.encodeArrayPointer(this.cls, val);
+ };
+
+ function Handle() {
+ }
+
+ Handle.encodedSize = 4;
+
+ Handle.decode = function(decoder) {
+ return decoder.decodeHandle();
+ };
+
+ Handle.encode = function(encoder, val) {
+ encoder.encodeHandle(val);
+ };
+
+ var exports = {};
+ exports.align = align;
+ exports.Buffer = Buffer;
+ exports.Message = Message;
+ exports.MessageBuilder = MessageBuilder;
+ exports.MessageWithRequestIDBuilder = MessageWithRequestIDBuilder;
+ exports.MessageReader = MessageReader;
+ exports.kArrayHeaderSize = kArrayHeaderSize;
+ exports.kStructHeaderSize = kStructHeaderSize;
+ exports.kMessageHeaderSize = kMessageHeaderSize;
+ exports.kMessageExpectsResponse = kMessageExpectsResponse;
+ exports.kMessageIsResponse = kMessageIsResponse;
+ exports.Int8 = Int8;
+ exports.Uint8 = Uint8;
+ exports.Int16 = Int16;
+ exports.Uint16 = Uint16;
+ exports.Int32 = Int32;
+ exports.Uint32 = Uint32;
+ exports.Int64 = Int64;
+ exports.Uint64 = Uint64;
+ exports.Float = Float;
+ exports.Double = Double;
+ exports.String = String;
+ exports.PointerTo = PointerTo;
+ exports.ArrayOf = ArrayOf;
+ exports.Handle = Handle;
+ return exports;
+});
diff --git a/chromium/mojo/public/js/bindings/connection.js b/chromium/mojo/public/js/bindings/connection.js
new file mode 100644
index 00000000000..ebf60adb7f8
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/connection.js
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+define("mojo/public/js/bindings/connection", [
+ "mojo/public/js/bindings/router",
+], function(router) {
+
+ function Connection(handle, localFactory, remoteFactory) {
+ this.router_ = new router.Router(handle);
+ this.remote = new remoteFactory(this.router_);
+ this.local = new localFactory(this.remote);
+ this.router_.setIncomingReceiver(this.local);
+ }
+
+ Connection.prototype.close = function() {
+ this.router_.close();
+ this.router_ = null;
+ this.local = null;
+ this.remote = null;
+ };
+
+ Connection.prototype.encounteredError = function() {
+ return this.router_.encounteredError();
+ };
+
+ var exports = {};
+ exports.Connection = Connection;
+ return exports;
+});
diff --git a/chromium/mojo/public/js/bindings/connector.js b/chromium/mojo/public/js/bindings/connector.js
new file mode 100644
index 00000000000..51022b0e45f
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/connector.js
@@ -0,0 +1,109 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+define("mojo/public/js/bindings/connector", [
+ "mojo/public/js/bindings/codec",
+ "mojo/public/js/bindings/core",
+ "mojo/public/js/bindings/support",
+], function(codec, core, support) {
+
+ function Connector(handle) {
+ this.handle_ = handle;
+ this.dropWrites_ = false;
+ this.error_ = false;
+ this.incomingReceiver_ = null;
+ this.readWaitCookie_ = null;
+ this.errorHandler_ = null;
+
+ this.waitToReadMore_();
+ }
+
+ Connector.prototype.close = function() {
+ if (this.readWaitCookie_) {
+ support.cancelWait(this.readWaitCookie_);
+ this.readWaitCookie_ = null;
+ }
+ if (this.handle_ != null) {
+ core.close(this.handle_);
+ this.handle_ = null;
+ }
+ };
+
+ Connector.prototype.accept = function(message) {
+ if (this.error_)
+ return false;
+
+ if (this.dropWrites_)
+ return true;
+
+ var result = core.writeMessage(this.handle_,
+ new Uint8Array(message.buffer.arrayBuffer),
+ message.handles,
+ core.WRITE_MESSAGE_FLAG_NONE);
+ switch (result) {
+ case core.RESULT_OK:
+ // The handles were successfully transferred, so we don't own them
+ // anymore.
+ message.handles = [];
+ break;
+ case core.RESULT_FAILED_PRECONDITION:
+ // There's no point in continuing to write to this pipe since the other
+ // end is gone. Avoid writing any future messages. Hide write failures
+ // from the caller since we'd like them to continue consuming any
+ // backlog of incoming messages before regarding the message pipe as
+ // closed.
+ this.dropWrites_ = true;
+ break;
+ default:
+ // This particular write was rejected, presumably because of bad input.
+ // The pipe is not necessarily in a bad state.
+ return false;
+ }
+ return true;
+ };
+
+ Connector.prototype.setIncomingReceiver = function(receiver) {
+ this.incomingReceiver_ = receiver;
+ };
+
+ Connector.prototype.setErrorHandler = function(handler) {
+ this.errorHandler_ = handler;
+ };
+
+ Connector.prototype.encounteredError = function() {
+ return this.error_;
+ };
+
+ Connector.prototype.waitToReadMore_ = function() {
+ this.readWaitCookie_ = support.asyncWait(this.handle_,
+ core.HANDLE_SIGNAL_READABLE,
+ this.readMore_.bind(this));
+ };
+
+ Connector.prototype.readMore_ = function(result) {
+ for (;;) {
+ var read = core.readMessage(this.handle_,
+ core.READ_MESSAGE_FLAG_NONE);
+ if (read.result == core.RESULT_SHOULD_WAIT) {
+ this.waitToReadMore_();
+ return;
+ }
+ if (read.result != core.RESULT_OK) {
+ this.error_ = true;
+ if (this.errorHandler_)
+ this.errorHandler_.onError(read.result);
+ return;
+ }
+ var buffer = new codec.Buffer(read.buffer);
+ var message = new codec.Message(buffer, read.handles);
+ if (this.incomingReceiver_) {
+ this.incomingReceiver_.accept(message);
+ }
+ }
+ };
+
+ var exports = {};
+ exports.Connector = Connector;
+ return exports;
+});
diff --git a/chromium/mojo/public/js/bindings/constants.cc b/chromium/mojo/public/js/bindings/constants.cc
new file mode 100644
index 00000000000..239b67d4139
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/constants.cc
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/js/bindings/constants.h"
+
+namespace mojo {
+
+const char kCodecModuleName[] = "mojo/public/js/bindings/codec";
+const char kConnectionModuleName[] = "mojo/public/js/bindings/connection";
+const char kConnectorModuleName[] = "mojo/public/js/bindings/connector";
+const char kUnicodeModuleName[] = "mojo/public/js/bindings/unicode";
+const char kRouterModuleName[] = "mojo/public/js/bindings/router";
+
+} // namespace mojo
diff --git a/chromium/mojo/public/js/bindings/constants.h b/chromium/mojo/public/js/bindings/constants.h
new file mode 100644
index 00000000000..50e5d7c0248
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/constants.h
@@ -0,0 +1,19 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_JS_BINDINGS_CONSTANTS_H_
+#define MOJO_PUBLIC_JS_BINDINGS_CONSTANTS_H_
+
+namespace mojo {
+
+// JavaScript module names:
+extern const char kCodecModuleName[];
+extern const char kConnectionModuleName[];
+extern const char kConnectorModuleName[];
+extern const char kUnicodeModuleName[];
+extern const char kRouterModuleName[];
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_JS_BINDINGS_CONSTANTS_H_
diff --git a/chromium/mojo/public/js/bindings/core.js b/chromium/mojo/public/js/bindings/core.js
new file mode 100644
index 00000000000..0aff5310833
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/core.js
@@ -0,0 +1,215 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Module "mojo/public/js/bindings/core"
+//
+// Note: This file is for documentation purposes only. The code here is not
+// actually executed. The real module is implemented natively in Mojo.
+//
+// This module provides the JavaScript bindings for mojo/public/c/system/core.h.
+// Refer to that file for more detailed documentation for equivalent methods.
+
+while (1);
+
+/**
+ * MojoHandle: An opaque handles to a Mojo object (e.g. a message pipe).
+ */
+var kInvalidHandle;
+
+/**
+ * MojoResult {number}: Result codes for Mojo operations.
+ * See core.h for more information.
+ */
+var RESULT_OK;
+var RESULT_CANCELLED;
+var RESULT_UNKNOWN;
+var RESULT_INVALID_ARGUMENT;
+var RESULT_DEADLINE_EXCEEDED;
+var RESULT_NOT_FOUND;
+var RESULT_ALREADY_EXISTS;
+var RESULT_PERMISSION_DENIED;
+var RESULT_RESOURCE_EXHAUSTED;
+var RESULT_FAILED_PRECONDITION;
+var RESULT_ABORTED;
+var RESULT_OUT_OF_RANGE;
+var RESULT_UNIMPLEMENTED;
+var RESULT_INTERNAL;
+var RESULT_UNAVAILABLE;
+var RESULT_DATA_LOSS;
+var RESULT_BUSY;
+var RESULT_SHOULD_WAIT;
+
+/**
+ * MojoDeadline {number}: Used to specify deadlines (timeouts), in microseconds.
+ * See core.h for more information.
+ */
+var DEADLINE_INDEFINITE;
+
+/**
+ * MojoHandleSignals: Used to specify signals that can be waited on for a handle
+ *(and which can be triggered), e.g., the ability to read or write to
+ * the handle.
+ * See core.h for more information.
+ */
+var HANDLE_SIGNAL_NONE;
+var HANDLE_SIGNAL_READABLE;
+var HANDLE_SIGNAL_WRITABLE;
+
+/*
+ * MojoWriteMessageFlags: Used to specify different modes to |writeMessage()|.
+ * See core.h for more information.
+ */
+var WRITE_MESSAGE_FLAG_NONE;
+
+/**
+ * MojoReadMessageFlags: Used to specify different modes to |readMessage()|.
+ * See core.h for more information.
+ */
+var READ_MESSAGE_FLAG_NONE;
+var READ_MESSAGE_FLAG_MAY_DISCARD;
+
+/**
+ * MojoCreateDataPipeOptions: Used to specify creation parameters for a data
+ * pipe to |createDataPipe()|.
+ * See core.h for more information.
+ */
+dictionary MojoCreateDataPipeOptions {
+ MojoCreateDataPipeOptionsFlags flags; // See below.
+ int32 elementNumBytes; // The size of an element, in bytes.
+ int32 capacityNumBytes; // The capacity of the data pipe, in bytes.
+};
+
+// MojoCreateDataPipeOptionsFlags
+var CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
+var CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD;
+
+/*
+ * MojoWriteDataFlags: Used to specify different modes to |writeData()|.
+ * See core.h for more information.
+ */
+var WRITE_DATA_FLAG_NONE;
+var WRITE_DATA_FLAG_ALL_OR_NONE;
+
+/**
+ * MojoReadDataFlags: Used to specify different modes to |readData()|.
+ * See core.h for more information.
+ */
+var READ_DATA_FLAG_NONE;
+var READ_DATA_FLAG_ALL_OR_NONE;
+var READ_DATA_FLAG_DISCARD;
+var READ_DATA_FLAG_QUERY;
+
+/**
+ * Closes the given |handle|. See MojoClose for more info.
+ * @param {MojoHandle} Handle to close.
+ * @return {MojoResult} Result code.
+ */
+function close(handle) { [native code] }
+
+/**
+ * Waits on the given handle until a signal indicated by |signals| is
+ * satisfied or until |deadline| is passed. See MojoWait for more information.
+ *
+ * @param {MojoHandle} handle Handle to wait on.
+ * @param {MojoHandleSignals} signals Specifies the condition to wait for.
+ * @param {MojoDeadline} deadline Stops waiting if this is reached.
+ * @return {MojoResult} Result code.
+ */
+function wait(handle, signals, deadline) { [native code] }
+
+/**
+ * Waits on |handles[0]|, ..., |handles[handles.length-1]| for at least one of
+ * them to satisfy the state indicated by |flags[0]|, ...,
+ * |flags[handles.length-1]|, respectively, or until |deadline| has passed.
+ * See MojoWaitMany for more information.
+ *
+ * @param {Array.MojoHandle} handles Handles to wait on.
+ * @param {Array.MojoHandleSignals} signals Specifies the condition to wait for,
+ * for each corresponding handle. Must be the same length as |handles|.
+ * @param {MojoDeadline} deadline Stops waiting if this is reached.
+ * @return {MojoResult} Result code.
+ */
+function waitMany(handles, signals, deadline) { [native code] }
+
+/**
+ * Creates a message pipe. This function always succeeds.
+ * See MojoCreateMessagePipe for more information on message pipes.
+ *
+ * @return {MessagePipe} An object of the form {
+ * handle0,
+ * handle1,
+ * }
+ * where |handle0| and |handle1| are MojoHandles to each end of the channel.
+ */
+function createMessagePipe() { [native code] }
+
+/**
+ * Writes a message to the message pipe endpoint given by |handle|. See
+ * MojoWriteMessage for more information, including return codes.
+ *
+ * @param {MojoHandle} handle The endpoint to write to.
+ * @param {ArrayBufferView} buffer The message data. May be empty.
+ * @param {Array.MojoHandle} handlesArray Any handles to attach. Handles are
+ * transferred on success and will no longer be valid. May be empty.
+ * @param {MojoWriteMessageFlags} flags Flags.
+ * @return {MojoResult} Result code.
+ */
+function writeMessage(handle, buffer, handlesArray, flags) { [native code] }
+
+/**
+ * Reads a message from the message pipe endpoint given by |handle|. See
+ * MojoReadMessage for more information, including return codes.
+ *
+ * @param {MojoHandle} handle The endpoint to read from.
+ * @param {MojoReadMessageFlags} flags Flags.
+ * @return {object} An object of the form {
+ * result, // |RESULT_OK| on success, error code otherwise.
+ * buffer, // An ArrayBufferView of the message data (only on success).
+ * handles // An array of MojoHandles transferred, if any.
+ * }
+ */
+function readMessage(handle, flags) { [native code] }
+
+/**
+ * Creates a data pipe, which is a unidirectional communication channel for
+ * unframed data, with the given options. See MojoCreateDataPipe for more
+ * more information, including return codes.
+ *
+ * @param {MojoCreateDataPipeOptions} optionsDict Options to control the data
+ * pipe parameters. May be null.
+ * @return {object} An object of the form {
+ * result, // |RESULT_OK| on success, error code otherwise.
+ * producerHandle, // MojoHandle to use with writeData (only on success).
+ * consumerHandle, // MojoHandle to use with readData (only on success).
+ * }
+ */
+function createDataPipe(optionsDict) { [native code] }
+
+/**
+ * Writes the given data to the data pipe producer given by |handle|. See
+ * MojoWriteData for more information, including return codes.
+ *
+ * @param {MojoHandle} handle A producerHandle returned by createDataPipe.
+ * @param {ArrayBufferView} buffer The data to write.
+ * @param {MojoWriteDataFlags} flags Flags.
+ * @return {object} An object of the form {
+ * result, // |RESULT_OK| on success, error code otherwise.
+ * numBytes, // The number of bytes written.
+ * }
+ */
+function writeData(handle, buffer, flags) { [native code] }
+
+/**
+ * Reads data from the data pipe consumer given by |handle|. May also
+ * be used to discard data. See MojoReadData for more information, including
+ * return codes.
+ *
+ * @param {MojoHandle} handle A consumerHandle returned by createDataPipe.
+ * @param {MojoReadDataFlags} flags Flags.
+ * @return {object} An object of the form {
+ * result, // |RESULT_OK| on success, error code otherwise.
+ * buffer, // An ArrayBufferView of the data read (only on success).
+ * }
+ */
+function readData(handle, flags) { [native code] }
diff --git a/chromium/mojo/public/js/bindings/router.js b/chromium/mojo/public/js/bindings/router.js
new file mode 100644
index 00000000000..2718e8b0b78
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/router.js
@@ -0,0 +1,93 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+define("mojo/public/js/bindings/router", [
+ "mojo/public/js/bindings/codec",
+ "mojo/public/js/bindings/connector",
+], function(codec, connector) {
+
+ function Router(handle) {
+ this.connector_ = new connector.Connector(handle);
+ this.incomingReceiver_ = null;
+ this.nextRequestID_ = 0;
+ this.responders_ = {};
+
+ this.connector_.setIncomingReceiver({
+ accept: this.handleIncomingMessage_.bind(this),
+ });
+ this.connector_.setErrorHandler({
+ onError: this.handleConnectionError_.bind(this),
+ });
+ }
+
+ Router.prototype.close = function() {
+ this.responders_ = {}; // Drop any responders.
+ this.connector_.close();
+ };
+
+ Router.prototype.accept = function(message) {
+ this.connector_.accept(message);
+ };
+
+ Router.prototype.reject = function(message) {
+ // TODO(mpcomplete): no way to trasmit errors over a Connection.
+ };
+
+ Router.prototype.acceptWithResponder = function(message, responder) {
+ // Reserve 0 in case we want it to convey special meaning in the future.
+ var requestID = this.nextRequestID_++;
+ if (requestID == 0)
+ requestID = this.nextRequestID_++;
+
+ message.setRequestID(requestID);
+ var result = this.connector_.accept(message);
+
+ this.responders_[requestID] = responder;
+
+ // TODO(mpcomplete): accept should return a Promise too, maybe?
+ if (result)
+ return Promise.resolve();
+ return Promise.reject(Error("Connection error"));
+ };
+
+ Router.prototype.setIncomingReceiver = function(receiver) {
+ this.incomingReceiver_ = receiver;
+ };
+
+ Router.prototype.encounteredError = function() {
+ return this.connector_.encounteredError();
+ };
+
+ Router.prototype.handleIncomingMessage_ = function(message) {
+ var flags = message.getFlags();
+ if (flags & codec.kMessageExpectsResponse) {
+ if (this.incomingReceiver_) {
+ this.incomingReceiver_.acceptWithResponder(message, this);
+ } else {
+ // If we receive a request expecting a response when the client is not
+ // listening, then we have no choice but to tear down the pipe.
+ this.close();
+ }
+ } else if (flags & codec.kMessageIsResponse) {
+ var reader = new codec.MessageReader(message);
+ var requestID = reader.requestID;
+ var responder = this.responders_[requestID];
+ delete this.responders_[requestID];
+ responder.accept(message);
+ } else {
+ if (this.incomingReceiver_)
+ this.incomingReceiver_.accept(message);
+ }
+ };
+
+ Router.prototype.handleConnectionError_ = function(result) {
+ for (var each in this.responders_)
+ this.responders_[each].reject(result);
+ this.close();
+ };
+
+ var exports = {};
+ exports.Router = Router;
+ return exports;
+});
diff --git a/chromium/mojo/public/js/bindings/support.js b/chromium/mojo/public/js/bindings/support.js
new file mode 100644
index 00000000000..58df6bd4d02
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/support.js
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Module "mojo/public/js/bindings/support"
+//
+// Note: This file is for documentation purposes only. The code here is not
+// actually executed. The real module is implemented natively in Mojo.
+
+while (1);
+
+/*
+ * Waits on the given handle until the state indicated by |signals| is
+ * satisfied.
+ *
+ * @param {MojoHandle} handle The handle to wait on.
+ * @param {MojoHandleSignals} signals Specifies the condition to wait for.
+ * @param {function (mojoResult)} callback Called with the result the wait is
+ * complete. See MojoWait for possible result codes.
+ *
+ * @return {MojoWaitId} A waitId that can be passed to cancelWait to cancel the
+ * wait.
+ */
+function asyncWait(handle, signals, callback) { [native code] }
+
+/*
+ * Cancels the asyncWait operation specified by the given |waitId|.
+ * @param {MojoWaitId} waitId The waitId returned by asyncWait.
+ */
+function cancelWait(waitId) { [native code] }
diff --git a/chromium/mojo/public/js/bindings/unicode.js b/chromium/mojo/public/js/bindings/unicode.js
new file mode 100644
index 00000000000..ba0f00f95ba
--- /dev/null
+++ b/chromium/mojo/public/js/bindings/unicode.js
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Defines functions for translating between JavaScript strings and UTF8 strings
+ * stored in ArrayBuffers. There is much room for optimization in this code if
+ * it proves necessary.
+ */
+define("mojo/public/js/bindings/unicode", function() {
+ /**
+ * Decodes the UTF8 string from the given buffer.
+ * @param {ArrayBufferView} buffer The buffer containing UTF8 string data.
+ * @return {string} The corresponding JavaScript string.
+ */
+ function decodeUtf8String(buffer) {
+ return decodeURIComponent(escape(String.fromCharCode.apply(null, buffer)));
+ }
+
+ /**
+ * Encodes the given JavaScript string into UTF8.
+ * @param {string} str The string to encode.
+ * @param {ArrayBufferView} outputBuffer The buffer to contain the result.
+ * Should be pre-allocated to hold enough space. Use |utf8Length| to determine
+ * how much space is required.
+ * @return {number} The number of bytes written to |outputBuffer|.
+ */
+ function encodeUtf8String(str, outputBuffer) {
+ var utf8String = unescape(encodeURIComponent(str));
+ if (outputBuffer.length < utf8String.length)
+ throw new Error("Buffer too small for encodeUtf8String");
+ for (var i = 0; i < outputBuffer.length && i < utf8String.length; i++)
+ outputBuffer[i] = utf8String.charCodeAt(i);
+ return i;
+ }
+
+ /**
+ * Returns the number of bytes that a UTF8 encoding of the JavaScript string
+ * |str| would occupy.
+ */
+ function utf8Length(str) {
+ var utf8String = unescape(encodeURIComponent(str));
+ return utf8String.length;
+ }
+
+ var exports = {};
+ exports.decodeUtf8String = decodeUtf8String;
+ exports.encodeUtf8String = encodeUtf8String;
+ exports.utf8Length = utf8Length;
+ return exports;
+});
diff --git a/chromium/mojo/public/platform/native/system_thunks.cc b/chromium/mojo/public/platform/native/system_thunks.cc
new file mode 100644
index 00000000000..6fdc4f4530f
--- /dev/null
+++ b/chromium/mojo/public/platform/native/system_thunks.cc
@@ -0,0 +1,170 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/platform/native/system_thunks.h"
+
+#include <assert.h>
+
+extern "C" {
+
+static MojoSystemThunks g_thunks = {0};
+
+MojoTimeTicks MojoGetTimeTicksNow() {
+ assert(g_thunks.GetTimeTicksNow);
+ return g_thunks.GetTimeTicksNow();
+}
+
+MojoResult MojoClose(MojoHandle handle) {
+ assert(g_thunks.Close);
+ return g_thunks.Close(handle);
+}
+
+MojoResult MojoWait(MojoHandle handle,
+ MojoHandleSignals signals,
+ MojoDeadline deadline) {
+ assert(g_thunks.Wait);
+ return g_thunks.Wait(handle, signals, deadline);
+}
+
+MojoResult MojoWaitMany(const MojoHandle* handles,
+ const MojoHandleSignals* signals,
+ uint32_t num_handles,
+ MojoDeadline deadline) {
+ assert(g_thunks.WaitMany);
+ return g_thunks.WaitMany(handles, signals, num_handles, deadline);
+}
+
+MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options,
+ MojoHandle* message_pipe_handle0,
+ MojoHandle* message_pipe_handle1) {
+ assert(g_thunks.CreateMessagePipe);
+ return g_thunks.CreateMessagePipe(options, message_pipe_handle0,
+ message_pipe_handle1);
+}
+
+MojoResult MojoWriteMessage(MojoHandle message_pipe_handle,
+ const void* bytes,
+ uint32_t num_bytes,
+ const MojoHandle* handles,
+ uint32_t num_handles,
+ MojoWriteMessageFlags flags) {
+ assert(g_thunks.WriteMessage);
+ return g_thunks.WriteMessage(message_pipe_handle, bytes, num_bytes, handles,
+ num_handles, flags);
+}
+
+MojoResult MojoReadMessage(MojoHandle message_pipe_handle,
+ void* bytes,
+ uint32_t* num_bytes,
+ MojoHandle* handles,
+ uint32_t* num_handles,
+ MojoReadMessageFlags flags) {
+ assert(g_thunks.ReadMessage);
+ return g_thunks.ReadMessage(message_pipe_handle, bytes, num_bytes, handles,
+ num_handles, flags);
+}
+
+MojoResult MojoCreateDataPipe(const MojoCreateDataPipeOptions* options,
+ MojoHandle* data_pipe_producer_handle,
+ MojoHandle* data_pipe_consumer_handle) {
+ assert(g_thunks.CreateDataPipe);
+ return g_thunks.CreateDataPipe(options, data_pipe_producer_handle,
+ data_pipe_consumer_handle);
+}
+
+MojoResult MojoWriteData(MojoHandle data_pipe_producer_handle,
+ const void* elements,
+ uint32_t* num_elements,
+ MojoWriteDataFlags flags) {
+ assert(g_thunks.WriteData);
+ return g_thunks.WriteData(data_pipe_producer_handle, elements, num_elements,
+ flags);
+}
+
+MojoResult MojoBeginWriteData(MojoHandle data_pipe_producer_handle,
+ void** buffer,
+ uint32_t* buffer_num_elements,
+ MojoWriteDataFlags flags) {
+ assert(g_thunks.BeginWriteData);
+ return g_thunks.BeginWriteData(data_pipe_producer_handle, buffer,
+ buffer_num_elements, flags);
+}
+
+MojoResult MojoEndWriteData(MojoHandle data_pipe_producer_handle,
+ uint32_t num_elements_written) {
+ assert(g_thunks.EndWriteData);
+ return g_thunks.EndWriteData(data_pipe_producer_handle, num_elements_written);
+}
+
+MojoResult MojoReadData(MojoHandle data_pipe_consumer_handle,
+ void* elements,
+ uint32_t* num_elements,
+ MojoReadDataFlags flags) {
+ assert(g_thunks.ReadData);
+ return g_thunks.ReadData(data_pipe_consumer_handle, elements, num_elements,
+ flags);
+}
+
+MojoResult MojoBeginReadData(MojoHandle data_pipe_consumer_handle,
+ const void** buffer,
+ uint32_t* buffer_num_elements,
+ MojoReadDataFlags flags) {
+ assert(g_thunks.BeginReadData);
+ return g_thunks.BeginReadData(data_pipe_consumer_handle, buffer,
+ buffer_num_elements, flags);
+}
+
+MojoResult MojoEndReadData(MojoHandle data_pipe_consumer_handle,
+ uint32_t num_elements_read) {
+ assert(g_thunks.EndReadData);
+ return g_thunks.EndReadData(data_pipe_consumer_handle, num_elements_read);
+}
+
+MojoResult MojoCreateSharedBuffer(
+ const struct MojoCreateSharedBufferOptions* options,
+ uint64_t num_bytes,
+ MojoHandle* shared_buffer_handle) {
+ assert(g_thunks.CreateSharedBuffer);
+ return g_thunks.CreateSharedBuffer(options, num_bytes, shared_buffer_handle);
+}
+
+MojoResult MojoDuplicateBufferHandle(
+ MojoHandle buffer_handle,
+ const struct MojoDuplicateBufferHandleOptions* options,
+ MojoHandle* new_buffer_handle) {
+ assert(g_thunks.DuplicateBufferHandle);
+ return g_thunks.DuplicateBufferHandle(buffer_handle, options,
+ new_buffer_handle);
+}
+
+MojoResult MojoMapBuffer(MojoHandle buffer_handle,
+ uint64_t offset,
+ uint64_t num_bytes,
+ void** buffer,
+ MojoMapBufferFlags flags) {
+ assert(g_thunks.MapBuffer);
+ return g_thunks.MapBuffer(buffer_handle, offset, num_bytes, buffer, flags);
+}
+
+MojoResult MojoUnmapBuffer(void* buffer) {
+ assert(g_thunks.UnmapBuffer);
+ return g_thunks.UnmapBuffer(buffer);
+}
+
+// Call this function by looking
+// Always export this api.
+#if defined(WIN32)
+#define THUNK_EXPORT __declspec(dllexport)
+#else
+#define THUNK_EXPORT __attribute__((visibility("default")))
+#endif
+
+extern "C" THUNK_EXPORT size_t MojoSetSystemThunks(
+ const MojoSystemThunks* system_thunks) {
+ if (system_thunks->size >= sizeof(g_thunks))
+ g_thunks = *system_thunks;
+ return sizeof(g_thunks);
+}
+
+} // extern "C"
diff --git a/chromium/mojo/public/platform/native/system_thunks.h b/chromium/mojo/public/platform/native/system_thunks.h
new file mode 100644
index 00000000000..de82eba1bfc
--- /dev/null
+++ b/chromium/mojo/public/platform/native/system_thunks.h
@@ -0,0 +1,137 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_PLATFORM_NATIVE_SYSTEM_THUNKS_H_
+#define MOJO_PUBLIC_PLATFORM_NATIVE_SYSTEM_THUNKS_H_
+
+#include <stddef.h>
+
+#include "mojo/public/c/system/core.h"
+
+// The embedder needs to bind the basic Mojo Core functions of a DSO to those of
+// the embedder when loading a DSO that is dependent on mojo_system.
+// The typical usage would look like:
+// base::ScopedNativeLibrary app_library(
+// base::LoadNativeLibrary(app_path_, &error));
+// typedef MojoResult (*MojoSetSystemThunksFn)(MojoSystemThunks*);
+// MojoSetSystemThunksFn mojo_set_system_thunks_fn =
+// reinterpret_cast<MojoSetSystemThunksFn>(app_library.GetFunctionPointer(
+// "MojoSetSystemThunks"));
+// MojoSystemThunks system_thunks = MojoMakeSystemThunks();
+// size_t expected_size = mojo_set_system_thunks_fn(&system_thunks);
+// if (expected_size > sizeof(MojoSystemThunks)) {
+// LOG(ERROR)
+// << "Invalid DSO. Expected MojoSystemThunks size: "
+// << expected_size;
+// break;
+// }
+
+// Structure used to bind the basic Mojo Core functions of a DSO to those of
+// the embedder.
+// This is the ABI between the embedder and the DSO. It can only have new
+// functions added to the end. No other changes are supported.
+#pragma pack(push, 8)
+struct MojoSystemThunks {
+ size_t size; // Should be set to sizeof(MojoSystemThunks).
+ MojoTimeTicks (*GetTimeTicksNow)();
+ MojoResult (*Close)(MojoHandle handle);
+ MojoResult (*Wait)(MojoHandle handle,
+ MojoHandleSignals signals,
+ MojoDeadline deadline);
+ MojoResult (*WaitMany)(const MojoHandle* handles,
+ const MojoHandleSignals* signals,
+ uint32_t num_handles,
+ MojoDeadline deadline);
+ MojoResult (*CreateMessagePipe)(const MojoCreateMessagePipeOptions* options,
+ MojoHandle* message_pipe_handle0,
+ MojoHandle* message_pipe_handle1);
+ MojoResult (*WriteMessage)(MojoHandle message_pipe_handle,
+ const void* bytes,
+ uint32_t num_bytes,
+ const MojoHandle* handles,
+ uint32_t num_handles,
+ MojoWriteMessageFlags flags);
+ MojoResult (*ReadMessage)(MojoHandle message_pipe_handle,
+ void* bytes,
+ uint32_t* num_bytes,
+ MojoHandle* handles,
+ uint32_t* num_handles,
+ MojoReadMessageFlags flags);
+ MojoResult (*CreateDataPipe)(const MojoCreateDataPipeOptions* options,
+ MojoHandle* data_pipe_producer_handle,
+ MojoHandle* data_pipe_consumer_handle);
+ MojoResult (*WriteData)(MojoHandle data_pipe_producer_handle,
+ const void* elements,
+ uint32_t* num_elements,
+ MojoWriteDataFlags flags);
+ MojoResult (*BeginWriteData)(MojoHandle data_pipe_producer_handle,
+ void** buffer,
+ uint32_t* buffer_num_elements,
+ MojoWriteDataFlags flags);
+ MojoResult (*EndWriteData)(MojoHandle data_pipe_producer_handle,
+ uint32_t num_elements_written);
+ MojoResult (*ReadData)(MojoHandle data_pipe_consumer_handle,
+ void* elements,
+ uint32_t* num_elements,
+ MojoReadDataFlags flags);
+ MojoResult (*BeginReadData)(MojoHandle data_pipe_consumer_handle,
+ const void** buffer,
+ uint32_t* buffer_num_elements,
+ MojoReadDataFlags flags);
+ MojoResult (*EndReadData)(MojoHandle data_pipe_consumer_handle,
+ uint32_t num_elements_read);
+ MojoResult (*CreateSharedBuffer)(
+ const MojoCreateSharedBufferOptions* options,
+ uint64_t num_bytes,
+ MojoHandle* shared_buffer_handle);
+ MojoResult (*DuplicateBufferHandle)(
+ MojoHandle buffer_handle,
+ const MojoDuplicateBufferHandleOptions* options,
+ MojoHandle* new_buffer_handle);
+ MojoResult (*MapBuffer)(MojoHandle buffer_handle,
+ uint64_t offset,
+ uint64_t num_bytes,
+ void** buffer,
+ MojoMapBufferFlags flags);
+ MojoResult (*UnmapBuffer)(void* buffer);
+};
+#pragma pack(pop)
+
+// Intended to be called from the embedder. Returns a |MojoCore| initialized
+// to contain pointers to each of the embedder's MojoCore functions.
+inline MojoSystemThunks MojoMakeSystemThunks() {
+ MojoSystemThunks system_thunks = {
+ sizeof(MojoSystemThunks),
+ MojoGetTimeTicksNow,
+ MojoClose,
+ MojoWait,
+ MojoWaitMany,
+ MojoCreateMessagePipe,
+ MojoWriteMessage,
+ MojoReadMessage,
+ MojoCreateDataPipe,
+ MojoWriteData,
+ MojoBeginWriteData,
+ MojoEndWriteData,
+ MojoReadData,
+ MojoBeginReadData,
+ MojoEndReadData,
+ MojoCreateSharedBuffer,
+ MojoDuplicateBufferHandle,
+ MojoMapBuffer,
+ MojoUnmapBuffer
+ };
+ return system_thunks;
+}
+
+// Use this type for the function found by dynamically discovering it in
+// a DSO linked with mojo_system. For example:
+// MojoSetSystemThunksFn mojo_set_system_thunks_fn =
+// reinterpret_cast<MojoSetSystemThunksFn>(app_library.GetFunctionPointer(
+// "MojoSetSystemThunks"));
+// The expected size of |system_thunks} is returned.
+// The contents of |system_thunks| are copied.
+typedef size_t (*MojoSetSystemThunksFn)(const MojoSystemThunks* system_thunks);
+
+#endif // MOJO_PUBLIC_PLATFORM_NATIVE_SYSTEM_THUNKS_H_
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl
new file mode 100644
index 00000000000..bc2a097b098
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl
@@ -0,0 +1,9 @@
+enum {{enum.name}} {
+{%- for field in enum.fields %}
+{%- if field.value %}
+ {{field.name}} = {{field.value|expression_to_text}},
+{%- else %}
+ {{field.name}},
+{%- endif %}
+{%- endfor %}
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
new file mode 100644
index 00000000000..30d20d8993e
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
@@ -0,0 +1,49 @@
+{%- import "interface_macros.tmpl" as interface_macros %}
+class {{interface.name}}Proxy;
+class {{interface.name}}Stub;
+
+class {{interface.name}}RequestValidator;
+{%- if interface|has_callbacks %}
+class {{interface.name}}ResponseValidator;
+{%- endif %}
+{% if interface.client %}
+class {{interface.client}};
+{% endif %}
+
+class {{interface.name}} {
+ public:
+ static const char* Name_;
+
+ typedef {{interface.name}}Proxy Proxy_;
+ typedef {{interface.name}}Stub Stub_;
+
+ typedef {{interface.name}}RequestValidator RequestValidator_;
+{%- if interface|has_callbacks %}
+ typedef {{interface.name}}ResponseValidator ResponseValidator_;
+{%- else %}
+ typedef mojo::PassThroughFilter ResponseValidator_;
+{%- endif %}
+{% if interface.client %}
+ typedef {{interface.client}} Client;
+{% else %}
+ typedef mojo::NoInterface Client;
+{% endif %}
+
+{#--- Constants #}
+{%- for constant in interface.constants %}
+ static const {{constant.kind|cpp_pod_type}} {{constant.name}};
+{%- endfor %}
+
+{#--- Enums #}
+{%- for enum in interface.enums %}
+{% macro enum_def() %}{% include "enum_declaration.tmpl" %}{% endmacro %}
+ {{enum_def()|indent(2)}}
+{%- endfor %}
+
+{#--- Methods #}
+ virtual ~{{interface.name}}() {}
+
+{%- for method in interface.methods %}
+ virtual void {{method.name}}({{interface_macros.declare_request_params("", method)}}) = 0;
+{%- endfor %}
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
new file mode 100644
index 00000000000..9b6a3249e55
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -0,0 +1,315 @@
+{%- import "interface_macros.tmpl" as interface_macros %}
+{%- set class_name = interface.name %}
+{%- set proxy_name = interface.name ~ "Proxy" %}
+{%- set namespace_as_string = "%s"|format(namespace|replace(".","::")) %}
+
+{%- macro alloc_params(parameters) %}
+{%- for param in parameters %}
+{%- if param.kind|is_object_kind %}
+{{param.kind|cpp_result_type}} p{{loop.index}};
+Deserialize_(params->{{param.name}}.ptr, &p{{loop.index}});
+{% endif -%}
+{%- endfor %}
+{%- endmacro %}
+
+{%- macro pass_params(parameters) %}
+{%- for param in parameters %}
+{%- if param.kind|is_string_kind -%}
+p{{loop.index}}
+{%- elif param.kind|is_object_kind -%}
+p{{loop.index}}.Pass()
+{%- elif param.kind|is_interface_kind -%}
+mojo::MakeProxy<{{param.kind|get_name_for_kind}}>(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&params->{{param.name}})))
+{%- elif param.kind|is_interface_request_kind -%}
+mojo::MakeRequest<{{param.kind.kind|get_name_for_kind}}>(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&params->{{param.name}})))
+{%- elif param.kind|is_handle_kind -%}
+mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&params->{{param.name}}))
+{%- elif param.kind|is_enum_kind -%}
+static_cast<{{param.kind|cpp_wrapper_type}}>(params->{{param.name}})
+{%- else -%}
+params->{{param.name}}
+{%- endif -%}
+{%- if not loop.last %}, {% endif %}
+{%- endfor %}
+{%- endmacro %}
+
+{%- macro compute_payload_size(params_name, parameters) -%}
+ size_t payload_size =
+ mojo::internal::Align(sizeof({{params_name}}));
+{#--- Computes #}
+{%- for param in parameters %}
+{%- if param.kind|is_object_kind %}
+ payload_size += GetSerializedSize_(in_{{param.name}});
+{%- endif %}
+{%- endfor %}
+{%- endmacro %}
+
+{%- macro build_message(params_name, parameters) -%}
+ {{params_name}}* params =
+ {{params_name}}::New(builder.buffer());
+{#--- Sets #}
+{% for param in parameters %}
+{%- if param.kind|is_object_kind %}
+ Serialize_(mojo::internal::Forward(in_{{param.name}}), builder.buffer(), &params->{{param.name}}.ptr);
+{%- elif param.kind|is_interface_kind %}
+ if (!in_{{param.name}}.get()) {
+ params->{{param.name}} = mojo::MessagePipeHandle();
+ } else {
+ // Delegate handle.
+ params->{{param.name}} = in_{{param.name}}.PassMessagePipe().release();
+ }
+{%- elif param.kind|is_interface_request_kind %}
+ // Delegate handle.
+ params->{{param.name}} = in_{{param.name}}.PassMessagePipe().release();
+{%- elif param.kind|is_handle_kind %}
+ params->{{param.name}} = in_{{param.name}}.release();
+{%- else %}
+ params->{{param.name}} = in_{{param.name}};
+{%- endif %}
+{%- endfor %}
+ mojo::Message message;
+ params->EncodePointersAndHandles(message.mutable_handles());
+ builder.Finish(&message);
+{%- endmacro %}
+
+{#--- Begin #}
+const char* {{class_name}}::Name_ = "{{namespace_as_string}}::{{class_name}}";
+{#--- Constants #}
+{% for constant in interface.constants %}
+const {{constant.kind|cpp_pod_type}} {{interface.name}}::{{constant.name}} = {{constant.value|expression_to_text}};
+{%- endfor %}
+
+{#--- ForwardToCallback definition #}
+{%- for method in interface.methods -%}
+{%- if method.response_parameters != None %}
+class {{class_name}}_{{method.name}}_ForwardToCallback
+ : public mojo::MessageReceiver {
+ public:
+ {{class_name}}_{{method.name}}_ForwardToCallback(
+ const {{interface_macros.declare_callback(method)}}& callback)
+ : callback_(callback) {
+ }
+ virtual bool Accept(mojo::Message* message) MOJO_OVERRIDE;
+ private:
+ {{interface_macros.declare_callback(method)}} callback_;
+ MOJO_DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ForwardToCallback);
+};
+bool {{class_name}}_{{method.name}}_ForwardToCallback::Accept(
+ mojo::Message* message) {
+ internal::{{class_name}}_{{method.name}}_ResponseParams_Data* params =
+ reinterpret_cast<internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>(
+ message->mutable_payload());
+
+ params->DecodePointersAndHandles(message->mutable_handles());
+ {{alloc_params(method.response_parameters)|indent(2)}}
+ callback_.Run({{pass_params(method.response_parameters)}});
+ return true;
+}
+{%- endif %}
+{%- endfor %}
+
+{{proxy_name}}::{{proxy_name}}(mojo::MessageReceiverWithResponder* receiver)
+ : receiver_(receiver) {
+}
+
+{#--- Proxy definitions #}
+
+{%- for method in interface.methods %}
+{%- set message_name =
+ "internal::k%s_%s_Name"|format(interface.name, method.name) %}
+{%- set params_name =
+ "internal::%s_%s_Params_Data"|format(interface.name, method.name) %}
+void {{proxy_name}}::{{method.name}}(
+ {{interface_macros.declare_request_params("in_", method)}}) {
+ {{compute_payload_size(params_name, method.parameters)}}
+
+{%- if method.response_parameters != None %}
+ mojo::internal::RequestMessageBuilder builder({{message_name}}, payload_size);
+{%- else %}
+ mojo::internal::MessageBuilder builder({{message_name}}, payload_size);
+{%- endif %}
+
+ {{build_message(params_name, method.parameters)}}
+
+{%- if method.response_parameters != None %}
+ mojo::MessageReceiver* responder =
+ new {{class_name}}_{{method.name}}_ForwardToCallback(callback);
+ if (!receiver_->AcceptWithResponder(&message, responder))
+ delete responder;
+{%- else %}
+ bool ok MOJO_ALLOW_UNUSED = receiver_->Accept(&message);
+ // This return value may be ignored as !ok implies the Connector has
+ // encountered an error, which will be visible through other means.
+{%- endif %}
+}
+{%- endfor %}
+
+{#--- ProxyToResponder definition #}
+{%- for method in interface.methods -%}
+{%- if method.response_parameters != None %}
+{%- set message_name =
+ "internal::k%s_%s_Name"|format(interface.name, method.name) %}
+{%- set params_name =
+ "internal::%s_%s_ResponseParams_Data"|format(interface.name, method.name) %}
+class {{class_name}}_{{method.name}}_ProxyToResponder
+ : public {{interface_macros.declare_callback(method)}}::Runnable {
+ public:
+ virtual ~{{class_name}}_{{method.name}}_ProxyToResponder() {
+ delete responder_;
+ }
+
+ {{class_name}}_{{method.name}}_ProxyToResponder(
+ uint64_t request_id,
+ mojo::MessageReceiver* responder)
+ : request_id_(request_id),
+ responder_(responder) {
+ }
+
+ virtual void Run({{interface_macros.declare_params("in_", method.response_parameters)}}) const;
+
+ private:
+ uint64_t request_id_;
+ mutable mojo::MessageReceiver* responder_;
+ MOJO_DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ProxyToResponder);
+};
+void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
+ {{interface_macros.declare_params("in_", method.response_parameters)}}) const {
+ {{compute_payload_size(params_name, method.response_parameters)}}
+ mojo::internal::ResponseMessageBuilder builder(
+ {{message_name}}, payload_size, request_id_);
+ {{build_message(params_name, method.response_parameters)}}
+ bool ok MOJO_ALLOW_UNUSED = responder_->Accept(&message);
+ // TODO(darin): !ok returned here indicates a malformed message, and that may
+ // be good reason to close the connection. However, we don't have a way to do
+ // that from here. We should add a way.
+ delete responder_;
+ responder_ = NULL;
+}
+{%- endif -%}
+{%- endfor %}
+
+{{class_name}}Stub::{{class_name}}Stub()
+ : sink_(NULL) {
+}
+
+{#--- Stub definition #}
+
+bool {{class_name}}Stub::Accept(mojo::Message* message) {
+{%- if interface.methods %}
+ switch (message->header()->name) {
+{%- for method in interface.methods %}
+ case internal::k{{class_name}}_{{method.name}}_Name: {
+{%- if method.response_parameters == None %}
+ internal::{{class_name}}_{{method.name}}_Params_Data* params =
+ reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
+ message->mutable_payload());
+
+ params->DecodePointersAndHandles(message->mutable_handles());
+ {{alloc_params(method.parameters)|indent(6)}}
+ sink_->{{method.name}}({{pass_params(method.parameters)}});
+ return true;
+{%- else %}
+ break;
+{%- endif %}
+ }
+{%- endfor %}
+ }
+{%- endif %}
+ return false;
+}
+
+bool {{class_name}}Stub::AcceptWithResponder(
+ mojo::Message* message, mojo::MessageReceiver* responder) {
+{%- if interface.methods %}
+ switch (message->header()->name) {
+{%- for method in interface.methods %}
+ case internal::k{{class_name}}_{{method.name}}_Name: {
+{%- if method.response_parameters != None %}
+ internal::{{class_name}}_{{method.name}}_Params_Data* params =
+ reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
+ message->mutable_payload());
+
+ params->DecodePointersAndHandles(message->mutable_handles());
+ {{interface_macros.declare_callback(method)}}::Runnable* runnable =
+ new {{class_name}}_{{method.name}}_ProxyToResponder(
+ message->request_id(), responder);
+ {{interface_macros.declare_callback(method)}} callback(runnable);
+ {{alloc_params(method.parameters)|indent(6)}}
+ sink_->{{method.name}}(
+{%- if method.parameters -%}{{pass_params(method.parameters)}}, {% endif -%}callback);
+ return true;
+{%- else %}
+ break;
+{%- endif %}
+ }
+{%- endfor %}
+ }
+{%- endif %}
+ return false;
+}
+
+{#--- Request validator definitions #}
+
+{{class_name}}RequestValidator::{{class_name}}RequestValidator(
+ mojo::MessageReceiver* sink) : MessageFilter(sink) {
+}
+
+bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
+{%- if interface.methods %}
+ switch (message->header()->name) {
+{%- for method in interface.methods %}
+ case internal::k{{class_name}}_{{method.name}}_Name: {
+{%- if method.response_parameters != None %}
+ if (!message->has_flag(mojo::internal::kMessageExpectsResponse))
+ break;
+{%- else %}
+ if (message->has_flag(mojo::internal::kMessageExpectsResponse) ||
+ message->has_flag(mojo::internal::kMessageIsResponse)) {
+ break;
+ }
+{%- endif %}
+ mojo::internal::BoundsChecker bounds_checker(
+ message->payload(), message->payload_num_bytes(),
+ message->handles()->size());
+ if (!internal::{{class_name}}_{{method.name}}_Params_Data::Validate(
+ message->payload(), &bounds_checker)) {
+ return false;
+ }
+ break;
+ }
+{%- endfor %}
+ }
+{%- endif %}
+
+ return sink_->Accept(message);
+}
+
+{#--- Response validator definitions #}
+{% if interface|has_callbacks %}
+{{class_name}}ResponseValidator::{{class_name}}ResponseValidator(
+ mojo::MessageReceiver* sink) : MessageFilter(sink) {
+}
+
+bool {{class_name}}ResponseValidator::Accept(mojo::Message* message) {
+{%- if interface.methods %}
+ switch (message->header()->name) {
+{%- for method in interface.methods if method.response_parameters != None %}
+ case internal::k{{class_name}}_{{method.name}}_Name: {
+ if (!message->has_flag(mojo::internal::kMessageIsResponse))
+ break;
+ mojo::internal::BoundsChecker bounds_checker(
+ message->payload(), message->payload_num_bytes(),
+ message->handles()->size());
+ if (!internal::{{class_name}}_{{method.name}}_ResponseParams_Data::Validate(
+ message->payload(), &bounds_checker)) {
+ return false;
+ }
+ break;
+ }
+{%- endfor %}
+ }
+{%- endif %}
+
+ return sink_->Accept(message);
+}
+{%- endif -%}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl
new file mode 100644
index 00000000000..fbefce2d397
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl
@@ -0,0 +1,23 @@
+{%- macro declare_params(prefix, parameters) %}
+{%- for param in parameters -%}
+{{param.kind|cpp_const_wrapper_type}} {{prefix}}{{param.name}}
+{%- if not loop.last %}, {% endif %}
+{%- endfor %}
+{%- endmacro %}
+
+{%- macro declare_callback(method) -%}
+mojo::Callback<void(
+{%- for param in method.response_parameters -%}
+{{param.kind|cpp_result_type}}
+{%- if not loop.last %}, {% endif %}
+{%- endfor -%}
+)>
+{%- endmacro -%}
+
+{%- macro declare_request_params(prefix, method) -%}
+{{declare_params(prefix, method.parameters)}}
+{%- if method.response_parameters != None -%}
+{%- if method.parameters %}, {% endif %}
+const {{declare_callback(method)}}& callback
+{%- endif -%}
+{%- endmacro -%}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl
new file mode 100644
index 00000000000..9451118a438
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl
@@ -0,0 +1,14 @@
+{%- import "interface_macros.tmpl" as interface_macros %}
+class {{interface.name}}Proxy : public {{interface.name}} {
+ public:
+ explicit {{interface.name}}Proxy(mojo::MessageReceiverWithResponder* receiver);
+
+{%- for method in interface.methods %}
+ virtual void {{method.name}}(
+ {{interface_macros.declare_request_params("", method)}}
+ ) MOJO_OVERRIDE;
+{%- endfor %}
+
+ private:
+ mojo::MessageReceiverWithResponder* receiver_;
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl
new file mode 100644
index 00000000000..63c60ee2db8
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl
@@ -0,0 +1,6 @@
+class {{interface.name}}RequestValidator : public mojo::MessageFilter {
+ public:
+ explicit {{interface.name}}RequestValidator(mojo::MessageReceiver* sink = NULL);
+
+ virtual bool Accept(mojo::Message* message) MOJO_OVERRIDE;
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl
new file mode 100644
index 00000000000..0719060c155
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl
@@ -0,0 +1,6 @@
+class {{interface.name}}ResponseValidator : public mojo::MessageFilter {
+ public:
+ explicit {{interface.name}}ResponseValidator(mojo::MessageReceiver* sink = NULL);
+
+ virtual bool Accept(mojo::Message* message) MOJO_OVERRIDE;
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl
new file mode 100644
index 00000000000..25b28ec777a
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl
@@ -0,0 +1,14 @@
+class {{interface.name}}Stub : public mojo::MessageReceiverWithResponder {
+ public:
+ {{interface.name}}Stub();
+ void set_sink({{interface.name}}* sink) { sink_ = sink; }
+ {{interface.name}}* sink() { return sink_; }
+
+ virtual bool Accept(mojo::Message* message) MOJO_OVERRIDE;
+ virtual bool AcceptWithResponder(mojo::Message* message,
+ mojo::MessageReceiver* responder)
+ MOJO_OVERRIDE;
+
+ private:
+ {{interface.name}}* sink_;
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
new file mode 100644
index 00000000000..f0cf33b560b
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+{%- set header_guard = "%s_INTERNAL_H_"|
+ format(module.path|upper|replace("/","_")|replace(".","_")) %}
+
+#ifndef {{header_guard}}
+#define {{header_guard}}
+
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/buffer.h"
+
+{%- for import in imports %}
+#include "{{import.module.path}}-internal.h"
+{%- endfor %}
+
+namespace mojo {
+namespace internal {
+class BoundsChecker;
+}
+}
+
+{%- for namespace in namespaces_as_array %}
+namespace {{namespace}} {
+{%- endfor %}
+
+{#--- Wrapper forward declarations #}
+{% for struct in structs %}
+class {{struct.name}};
+{%- endfor %}
+
+namespace internal {
+
+#pragma pack(push, 1)
+
+{#--- Class declarations #}
+{% for struct in structs %}
+{% include "struct_declaration.tmpl" %}
+{%- endfor %}
+
+#pragma pack(pop)
+
+} // namespace internal
+{%- for namespace in namespaces_as_array|reverse %}
+} // namespace {{namespace}}
+{%- endfor %}
+
+#endif // {{header_guard}}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
new file mode 100644
index 00000000000..8cf8e99713c
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
@@ -0,0 +1,86 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-private-field"
+#endif
+
+#include "{{module.path}}.h"
+
+#include "mojo/public/cpp/bindings/lib/array_serialization.h"
+#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
+#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
+#include "mojo/public/cpp/bindings/lib/message_builder.h"
+#include "mojo/public/cpp/bindings/lib/string_serialization.h"
+#include "mojo/public/cpp/bindings/lib/validation_errors.h"
+
+{%- for namespace in namespaces_as_array %}
+namespace {{namespace}} {
+{%- endfor %}
+
+{#--- Constants #}
+{% for constant in module.constants %}
+const {{constant.kind|cpp_pod_type}} {{constant.name}} = {{constant.value|expression_to_text}};
+{%- endfor %}
+
+namespace internal {
+namespace {
+
+#pragma pack(push, 1)
+
+{#--- Interface parameter definitions #}
+{%- for interface in interfaces %}
+{%- for method in interface.methods %}
+{%- set method_name = "k%s_%s_Name"|format(interface.name, method.name) %}
+const uint32_t {{method_name}} = {{method.ordinal}};
+{% set struct = method|struct_from_method %}
+{%- include "params_definition.tmpl" %}
+{%- if method.response_parameters != None %}
+{%- set struct = method|response_struct_from_method %}
+{%- include "params_definition.tmpl" %}
+{%- endif %}
+{%- endfor %}
+{%- endfor %}
+
+#pragma pack(pop)
+
+} // namespace
+
+{#--- Struct definitions #}
+{% for struct in structs %}
+{%- include "struct_definition.tmpl" %}
+{%- endfor %}
+
+} // namespace internal
+
+{#--- Struct Constants #}
+{%- for struct in structs %}
+{% for constant in struct.constants %}
+const {{constant.kind|cpp_pod_type}} {{struct.name}}::{{constant.name}} = {{constant.value|expression_to_text}};
+{%- endfor %}
+{%- endfor %}
+
+{#--- Struct builder definitions #}
+{%- for struct in structs %}
+{%- include "wrapper_class_definition.tmpl" %}
+{%- endfor %}
+
+{#--- Interface definitions #}
+{%- for interface in interfaces %}
+{%- include "interface_definition.tmpl" %}
+{%- endfor %}
+
+{#--- Struct Serialization Helpers #}
+{%- for struct in structs %}
+{%- include "struct_serialization_definition.tmpl" %}
+{%- endfor %}
+
+{%- for namespace in namespaces_as_array|reverse %}
+} // namespace {{namespace}}
+{%- endfor %}
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
new file mode 100644
index 00000000000..4e21d4774bd
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -0,0 +1,108 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+{%- set header_guard = "%s_H_"|
+ format(module.path|upper|replace("/","_")|replace(".","_")) %}
+
+#ifndef {{header_guard}}
+#define {{header_guard}}
+
+#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/callback.h"
+#include "mojo/public/cpp/bindings/interface_impl.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/message_filter.h"
+#include "mojo/public/cpp/bindings/no_interface.h"
+#include "mojo/public/cpp/bindings/string.h"
+#include "mojo/public/cpp/bindings/struct_ptr.h"
+#include "{{module.path}}-internal.h"
+{%- for import in imports %}
+#include "{{import.module.path}}.h"
+{%- endfor %}
+
+{%- for namespace in namespaces_as_array %}
+namespace {{namespace}} {
+{%- endfor %}
+
+{#--- Constants #}
+{% for constant in module.constants %}
+extern const {{constant.kind|cpp_pod_type}} {{constant.name}};
+{%- endfor %}
+
+{#--- Enums #}
+{% for enum in enums %}
+{% include "enum_declaration.tmpl" %}
+{%- endfor %}
+
+{#--- Interface Forward Declarations -#}
+{% for interface in interfaces %}
+class {{interface.name}};
+typedef mojo::InterfacePtr<{{interface.name}}> {{interface.name}}Ptr;
+{% endfor %}
+
+{#--- Struct Forward Declarations -#}
+{% for struct in structs %}
+class {{struct.name}};
+{% if struct|should_inline %}
+typedef mojo::InlinedStructPtr<{{struct.name}}> {{struct.name}}Ptr;
+{% else %}
+typedef mojo::StructPtr<{{struct.name}}> {{struct.name}}Ptr;
+{% endif %}
+{% endfor %}
+
+{#--- NOTE: Non-inlined structs may have pointers to inlined structs, so we #}
+{#--- need to fully define inlined structs ahead of the others. #}
+
+{#--- Inlined structs #}
+{% for struct in structs %}
+{% if struct|should_inline %}
+{% include "wrapper_class_declaration.tmpl" %}
+{% endif %}
+{%- endfor %}
+
+{#--- Non-inlined structs #}
+{% for struct in structs %}
+{% if not struct|should_inline %}
+{% include "wrapper_class_declaration.tmpl" %}
+{% endif %}
+{%- endfor %}
+
+{#--- Interfaces -#}
+{% for interface in interfaces %}
+{% include "interface_declaration.tmpl" %}
+{%- endfor %}
+
+{#--- Interface Proxies -#}
+{% for interface in interfaces %}
+{% include "interface_proxy_declaration.tmpl" %}
+{%- endfor %}
+
+{#--- Interface Stubs -#}
+{% for interface in interfaces %}
+{% include "interface_stub_declaration.tmpl" %}
+{%- endfor %}
+
+{#--- Interface Request Validators -#}
+{% for interface in interfaces %}
+{% include "interface_request_validator_declaration.tmpl" %}
+{%- endfor %}
+
+{#--- Interface Response Validators -#}
+{% for interface in interfaces if interface|has_callbacks %}
+{% include "interface_response_validator_declaration.tmpl" %}
+{%- endfor %}
+
+{#--- Struct Serialization Helpers -#}
+{% if structs %}
+{% for struct in structs %}
+{% include "struct_serialization_declaration.tmpl" %}
+{%- endfor %}
+{%- endif %}
+
+{%- for namespace in namespaces_as_array|reverse %}
+} // namespace {{namespace}}
+{%- endfor %}
+
+#endif // {{header_guard}}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl
new file mode 100644
index 00000000000..0b1104719bb
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl
@@ -0,0 +1,33 @@
+{%- import "struct_macros.tmpl" as struct_macros %}
+{%- set class_name = struct.name ~ "_Data" %}
+class {{class_name}} {
+ public:
+ static {{class_name}}* New(mojo::internal::Buffer* buf) {
+ return new (buf->Allocate(sizeof({{class_name}})))
+ {{class_name}}();
+ }
+
+ static bool Validate(const void* data,
+ mojo::internal::BoundsChecker* bounds_checker) {
+ {{ struct_macros.validate(struct, class_name)|indent(4) }}
+ }
+
+ mojo::internal::StructHeader header_;
+{{struct_macros.fields(struct)}}
+
+ void EncodePointersAndHandles(std::vector<mojo::Handle>* handles) {
+ {{ struct_macros.encodes(struct)|indent(4) }}
+ }
+
+ void DecodePointersAndHandles(std::vector<mojo::Handle>* handles) {
+ {{ struct_macros.decodes(struct)|indent(4) }}
+ }
+
+ private:
+ {{class_name}}() {
+ header_.num_bytes = sizeof(*this);
+ header_.num_fields = {{struct.packed.packed_fields|length}};
+ }
+};
+MOJO_COMPILE_ASSERT(sizeof({{class_name}}) == {{struct.packed|struct_size}},
+ bad_sizeof_{{class_name}});
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
new file mode 100644
index 00000000000..60a6a9e6d3e
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
@@ -0,0 +1,22 @@
+{%- import "struct_macros.tmpl" as struct_macros %}
+{%- set class_name = struct.name ~ "_Data" -%}
+
+class {{class_name}} {
+ public:
+ static {{class_name}}* New(mojo::internal::Buffer* buf);
+
+ static bool Validate(const void* data,
+ mojo::internal::BoundsChecker* bounds_checker);
+
+ mojo::internal::StructHeader header_;
+{{struct_macros.fields(struct)}}
+
+ void EncodePointersAndHandles(std::vector<mojo::Handle>* handles);
+ void DecodePointersAndHandles(std::vector<mojo::Handle>* handles);
+
+ private:
+ {{class_name}}();
+ ~{{class_name}}(); // NOT IMPLEMENTED
+};
+MOJO_COMPILE_ASSERT(sizeof({{class_name}}) == {{struct.packed|struct_size}},
+ bad_sizeof_{{class_name}});
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
new file mode 100644
index 00000000000..461f158602b
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
@@ -0,0 +1,28 @@
+{%- import "struct_macros.tmpl" as struct_macros %}
+{%- set class_name = struct.name ~ "_Data" %}
+
+// static
+{{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) {
+ return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}();
+}
+
+// static
+bool {{class_name}}::Validate(const void* data,
+ mojo::internal::BoundsChecker* bounds_checker) {
+ {{ struct_macros.validate(struct, class_name)|indent(2) }}
+}
+
+{{class_name}}::{{class_name}}() {
+ header_.num_bytes = sizeof(*this);
+ header_.num_fields = {{struct.packed.packed_fields|length}};
+}
+
+void {{class_name}}::EncodePointersAndHandles(
+ std::vector<mojo::Handle>* handles) {
+ {{ struct_macros.encodes(struct)|indent(2) }}
+}
+
+void {{class_name}}::DecodePointersAndHandles(
+ std::vector<mojo::Handle>* handles) {
+ {{ struct_macros.decodes(struct)|indent(2) }}
+}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
new file mode 100644
index 00000000000..bd05a06de72
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
@@ -0,0 +1,91 @@
+{%- macro validate(struct, class_name) %}
+ if (!data)
+ return true;
+
+ if (!ValidateStructHeader(
+ data, sizeof({{class_name}}),
+ {{struct.packed.packed_fields|length}}, bounds_checker)) {
+ return false;
+ }
+
+ const {{class_name}}* MOJO_ALLOW_UNUSED object =
+ static_cast<const {{class_name}}*>(data);
+
+{%- for packed_field in struct.packed.packed_fields %}
+{%- set name = packed_field.field.name %}
+{%- if packed_field.field.kind|is_object_kind %}
+{%- set wrapper_type = packed_field.field.kind|cpp_wrapper_type %}
+ if (!mojo::internal::ValidateEncodedPointer(&object->{{name}}.offset)) {
+ ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_POINTER);
+ return false;
+ }
+ if (!{{wrapper_type}}::Data_::Validate(
+ mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
+ bounds_checker)) {
+ return false;
+ }
+{%- elif packed_field.field.kind|is_handle_kind %}
+ if (!bounds_checker->ClaimHandle(object->{{name}})) {
+ ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_HANDLE);
+ return false;
+ }
+{%- endif %}
+{%- endfor %}
+
+ return true;
+{%- endmacro %}
+
+{%- macro field_line(field) %}
+{%- set type = field.kind|cpp_field_type %}
+{%- set name = field.name -%}
+{%- if field.kind.spec == 'b' -%}
+ uint8_t {{name}} : 1;
+{%- elif field.kind|is_enum_kind -%}
+ int32_t {{name}};
+{%- else -%}
+ {{type}} {{name}};
+{%- endif %}
+{%- endmacro %}
+
+{%- macro fields(struct) %}
+{%- for packed_field in struct.packed.packed_fields %}
+ {{field_line(packed_field.field)}}
+{%- if not loop.last %}
+{%- set next_pf = struct.packed.packed_fields[loop.index0 + 1] %}
+{%- set pad = next_pf.offset - (packed_field.offset + packed_field.size) %}
+{%- if pad > 0 %}
+ uint8_t pad{{loop.index0}}_[{{pad}}];
+{%- endif %}
+{%- endif %}
+{%- endfor -%}
+
+{%- set num_fields = struct.packed.packed_fields|length %}
+{%- if num_fields > 0 %}
+{%- set last_field = struct.packed.packed_fields[num_fields - 1] %}
+{%- set offset = last_field.offset + last_field.size %}
+{%- set pad = offset|get_pad(8) -%}
+{%- if pad > 0 %}
+ uint8_t padfinal_[{{pad}}];
+{%- endif %}
+{%- endif %}
+{%- endmacro %}
+
+{%- macro encodes(struct) -%}
+{%- for pf in struct.packed.packed_fields %}
+{%- if pf.field.kind|is_object_kind %}
+mojo::internal::Encode(&{{pf.field.name}}, handles);
+{%- elif pf.field.kind|is_handle_kind %}
+mojo::internal::EncodeHandle(&{{pf.field.name}}, handles);
+{%- endif %}
+{%- endfor %}
+{%- endmacro -%}
+
+{%- macro decodes(struct) -%}
+{%- for pf in struct.packed.packed_fields %}
+{%- if pf.field.kind|is_object_kind %}
+mojo::internal::Decode(&{{pf.field.name}}, handles);
+{%- elif pf.field.kind|is_handle_kind %}
+mojo::internal::DecodeHandle(&{{pf.field.name}}, handles);
+{%- endif %}
+{%- endfor %}
+{%- endmacro -%}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
new file mode 100644
index 00000000000..604be86c7e2
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
@@ -0,0 +1,5 @@
+size_t GetSerializedSize_(const {{struct.name}}Ptr& input);
+void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buffer,
+ internal::{{struct.name}}_Data** output);
+void Deserialize_(internal::{{struct.name}}_Data* input,
+ {{struct.name}}Ptr* output);
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
new file mode 100644
index 00000000000..aec2afa93e5
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
@@ -0,0 +1,51 @@
+size_t GetSerializedSize_(const {{struct.name}}Ptr& input) {
+ if (!input)
+ return 0;
+ size_t size = sizeof(internal::{{struct.name}}_Data);
+{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %}
+ size += GetSerializedSize_(input->{{pf.field.name}});
+{%- endfor %}
+ return size;
+}
+
+void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buf,
+ internal::{{struct.name}}_Data** output) {
+ if (input) {
+ internal::{{struct.name}}_Data* result =
+ internal::{{struct.name}}_Data::New(buf);
+{%- for pf in struct.packed.packed_fields %}
+{%- if pf.field.kind|is_object_kind %}
+ Serialize_(mojo::internal::Forward(input->{{pf.field.name}}), buf, &result->{{pf.field.name}}.ptr);
+{%- elif pf.field.kind|is_handle_kind %}
+ result->{{pf.field.name}} = input->{{pf.field.name}}.release();
+{%- else %}
+ result->{{pf.field.name}} = input->{{pf.field.name}};
+{%- endif %}
+{%- endfor %}
+ *output = result;
+ } else {
+ *output = NULL;
+ }
+}
+
+void Deserialize_(internal::{{struct.name}}_Data* input,
+ {{struct.name}}Ptr* output) {
+ if (input) {
+ {{struct.name}}Ptr result({{struct.name}}::New());
+{%- for pf in struct.packed.packed_fields %}
+{%- if pf.field.kind|is_object_kind %}
+ Deserialize_(input->{{pf.field.name}}.ptr, &result->{{pf.field.name}});
+{%- elif pf.field.kind|is_handle_kind %}
+ result->{{pf.field.name}}.reset(mojo::internal::FetchAndReset(&input->{{pf.field.name}}));
+{%- elif pf.field.kind|is_enum_kind %}
+ result->{{pf.field.name}} = static_cast<{{pf.field.kind|cpp_wrapper_type}}>(
+ input->{{pf.field.name}});
+{%- else %}
+ result->{{pf.field.name}} = input->{{pf.field.name}};
+{%- endif %}
+{%- endfor %}
+ *output = result.Pass();
+ } else {
+ output->reset();
+ }
+}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
new file mode 100644
index 00000000000..0e01976ce61
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
@@ -0,0 +1,31 @@
+
+class {{struct.name}} {
+ public:
+ typedef internal::{{struct.name}}_Data Data_;
+
+{#--- Constants #}
+{%- for constant in struct.constants %}
+ static const {{constant.kind|cpp_pod_type}} {{constant.name}};
+{%- endfor %}
+{#--- Enums #}
+{%- for enum in struct.enums -%}
+{% macro enum_def() %}{% include "enum_declaration.tmpl" %}{% endmacro %}
+ {{enum_def()|indent(2)}}
+{%- endfor %}
+ static {{struct.name}}Ptr New();
+
+ template <typename U>
+ static {{struct.name}}Ptr From(const U& u) {
+ return mojo::TypeConverter<{{struct.name}}Ptr, U>::ConvertFrom(u);
+ }
+
+ {{struct.name}}();
+ ~{{struct.name}}();
+
+{#--- Getters #}
+{% for field in struct.fields %}
+{%- set type = field.kind|cpp_wrapper_type %}
+{%- set name = field.name %}
+ {{type}} {{name}};
+{%- endfor %}
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl
new file mode 100644
index 00000000000..29bdd8eeb95
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl
@@ -0,0 +1,15 @@
+// static
+{{struct.name}}Ptr {{struct.name}}::New() {
+ {{struct.name}}Ptr rv;
+ mojo::internal::StructHelper<{{struct.name}}>::Initialize(&rv);
+ return rv.Pass();
+}
+
+{{struct.name}}::{{struct.name}}()
+{%-for field in struct.fields %}
+ {% if loop.first %}:{% else %} {% endif %} {{field.name}}({{field|default_value}}){% if not loop.last %},{% endif %}
+{%- endfor %} {
+}
+
+{{struct.name}}::~{{struct.name}}() {
+}
diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/constant_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/constant_definition.tmpl
new file mode 100644
index 00000000000..f69f657d314
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/java_templates/constant_definition.tmpl
@@ -0,0 +1,5 @@
+{% from "java_macros.tmpl" import build_default %}
+
+{% macro constant_def(constant) %}
+public static final {{constant.kind|java_type}} {{constant|name}} = {{build_default(module, constant.kind, constant.value)|indent(4)}};
+{% endmacro %}
diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/constants.java.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/constants.java.tmpl
new file mode 100644
index 00000000000..0a4e29956b6
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/java_templates/constants.java.tmpl
@@ -0,0 +1,12 @@
+{% from "constant_definition.tmpl" import constant_def %}
+{% include "header.java.tmpl" %}
+
+public final class {{main_entity}} {
+{% for constant in constants %}
+
+ {{constant_def(constant)|indent(4)}}
+{% endfor %}
+
+ private {{main_entity}}() {}
+
+}
diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/enum.java.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/enum.java.tmpl
new file mode 100644
index 00000000000..7096a18747f
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/java_templates/enum.java.tmpl
@@ -0,0 +1,4 @@
+{% from "enum_definition.tmpl" import enum_def %}
+{% include "header.java.tmpl" %}
+
+{{enum_def(enum, true)}}
diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl
new file mode 100644
index 00000000000..d72bd7ff4a7
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl
@@ -0,0 +1,21 @@
+{%- macro enum_value(enum, field, index) -%}
+{%- if field.value -%}
+(int) ({{field.value|expression_to_text}})
+{%- elif index == 0 -%}
+0
+{%- else -%}
+{{enum.fields[index - 1].name}} + 1
+{%- endif -%}
+{%- endmacro -%}
+
+{%- macro enum_def(enum, top_level) -%}
+public {{ 'static ' if not top_level }}final class {{enum|name}} {
+
+{% for field in enum.fields %}
+ public static final int {{field.name}} = {{enum_value(enum, field, loop.index0)}};
+{% endfor %}
+
+ private {{enum|name}}() {}
+
+}
+{%- endmacro -%}
diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/header.java.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/header.java.tmpl
new file mode 100644
index 00000000000..ec6a88b1474
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/java_templates/header.java.tmpl
@@ -0,0 +1,11 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by:
+// mojo/public/tools/bindings/mojom_bindings_generator.py
+// For:
+// {{module.path}}
+//
+
+package {{package}};
diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/java_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/java_macros.tmpl
new file mode 100644
index 00000000000..d7339f5a420
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/java_templates/java_macros.tmpl
@@ -0,0 +1,3 @@
+{% macro build_default(module, kind, value) %}
+({{kind|java_type}}) {{value|expression_to_text}}
+{% endmacro %}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl
new file mode 100644
index 00000000000..795116d8dd9
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl
@@ -0,0 +1,14 @@
+{%- macro enum_def(enum_name, enum, module) -%}
+ {{enum_name}} = {};
+
+{%- set prev_enum = 0 %}
+{%- for field in enum.fields %}
+{%- if field.value %}
+ {{enum_name}}.{{field.name}} = {{field.value|expression_to_text}};
+{%- elif loop.first %}
+ {{enum_name}}.{{field.name}} = 0;
+{%- else %}
+ {{enum_name}}.{{field.name}} = {{enum_name}}.{{enum.fields[loop.index0 - 1].name}} + 1;
+{%- endif %}
+{%- endfor %}
+{%- endmacro %}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
new file mode 100644
index 00000000000..d46f8eeac9c
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
@@ -0,0 +1,122 @@
+{%- set namespace_as_string = namespace|replace(".","::") %}
+{%- for method in interface.methods %}
+ var k{{interface.name}}_{{method.name}}_Name = {{method.ordinal}};
+{%- endfor %}
+
+ function {{interface.name}}Proxy(receiver) {
+ this.receiver_ = receiver;
+ }
+
+ {{interface.name}}Proxy.NAME_ = '{{namespace_as_string}}::{{interface.name}}';
+
+{%- for method in interface.methods %}
+ {{interface.name}}Proxy.prototype.{{method.name|stylize_method}} = function(
+{%- for parameter in method.parameters -%}
+{{parameter.name}}{% if not loop.last %}, {% endif %}
+{%- endfor -%}
+) {
+ var params = new {{interface.name}}_{{method.name}}_Params();
+{%- for parameter in method.parameters %}
+ params.{{parameter.name}} = {{parameter.name}};
+{%- endfor %}
+
+{%- if method.response_parameters == None %}
+ var builder = new codec.MessageBuilder(
+ k{{interface.name}}_{{method.name}}_Name,
+ codec.align({{interface.name}}_{{method.name}}_Params.encodedSize));
+ builder.encodeStruct({{interface.name}}_{{method.name}}_Params, params);
+ var message = builder.finish();
+ this.receiver_.accept(message);
+{%- else %}
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageWithRequestIDBuilder(
+ k{{interface.name}}_{{method.name}}_Name,
+ codec.align({{interface.name}}_{{method.name}}_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct({{interface.name}}_{{method.name}}_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptWithResponder(message, {
+ accept: function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct({{interface.name}}_{{method.name}}_ResponseParams);
+ resolve(responseParams);
+ },
+ reject: function(result) {
+ reject(Error("Connection error: " + result));
+ },
+ }).catch(reject);
+ }.bind(this));
+{%- endif %}
+ };
+{%- endfor %}
+
+ function {{interface.name}}Stub() {
+ }
+
+ {{interface.name}}Stub.NAME_ = '{{namespace_as_string}}::{{interface.name}}';
+
+ {{interface.name}}Stub.prototype.accept = function(message) {
+ var reader = new codec.MessageReader(message);
+ switch (reader.messageName) {
+{%- for method in interface.methods %}
+{%- if method.response_parameters == None %}
+ case k{{interface.name}}_{{method.name}}_Name:
+ var params = reader.decodeStruct({{interface.name}}_{{method.name}}_Params);
+ this.{{method.name|stylize_method}}(
+{%- for parameter in method.parameters -%}
+params.{{parameter.name}}{% if not loop.last %}, {% endif %}
+{%- endfor %});
+ return true;
+{%- endif %}
+{%- endfor %}
+ default:
+ return false;
+ }
+ };
+
+ {{interface.name}}Stub.prototype.acceptWithResponder =
+ function(message, responder) {
+ var reader = new codec.MessageReader(message);
+ switch (reader.messageName) {
+{%- for method in interface.methods %}
+{%- if method.response_parameters != None %}
+ case k{{interface.name}}_{{method.name}}_Name:
+ var params = reader.decodeStruct({{interface.name}}_{{method.name}}_Params);
+ return this.{{method.name|stylize_method}}(
+{%- for parameter in method.parameters -%}
+params.{{parameter.name}}{% if not loop.last %}, {% endif -%}
+{%- endfor %}).then(function(response) {
+ var responseParams =
+ new {{interface.name}}_{{method.name}}_ResponseParams();
+{%- for parameter in method.response_parameters %}
+ responseParams.{{parameter.name}} = response.{{parameter.name}};
+{%- endfor %}
+ var builder = new codec.MessageWithRequestIDBuilder(
+ k{{interface.name}}_{{method.name}}_Name,
+ codec.align({{interface.name}}_{{method.name}}_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct({{interface.name}}_{{method.name}}_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+{%- endif %}
+{%- endfor %}
+ default:
+ return Promise.reject(Error("Unhandled message: " + reader.messageName));
+ }
+ };
+
+{#--- Enums #}
+{% from "enum_definition.tmpl" import enum_def -%}
+{% for enum in interface.enums %}
+ {{enum_def("%sProxy.%s"|format(interface.name, enum.name), enum, module)}}
+ {{interface.name}}Stub.{{enum.name}} = {{interface.name}}Proxy.{{enum.name}};
+{%- endfor %}
+
+{#--- Constants. #}
+{% for constant in interface.constants %}
+ {{interface.name}}Proxy.{{constant.name}} = {{constant.value|expression_to_text}};
+ {{interface.name}}Stub.{{constant.name}} = {{interface.name}}Proxy.{{constant.name}};
+{% endfor %}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl
new file mode 100644
index 00000000000..db570cd79df
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl
@@ -0,0 +1,52 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+define("{{module.path}}", [
+ "mojo/public/js/bindings/codec",
+{%- for import in imports %}
+ "{{import.module.path}}",
+{%- endfor %}
+ ], function(codec
+{%- for import in imports -%}
+ , {{import.unique_name}}
+{%- endfor -%}
+) {
+
+{#--- Constants #}
+{% for constant in module.constants %}
+ var {{constant.name}} = {{constant.value|expression_to_text}};
+{%- endfor %}
+
+{#--- Enums #}
+{%- from "enum_definition.tmpl" import enum_def %}
+{%- for enum in enums %}
+ var {{ enum_def(enum.name, enum, module) }}
+{%- endfor %}
+
+{#--- Struct definitions #}
+{% for struct in structs %}
+{%- include "struct_definition.tmpl" %}
+{%- endfor %}
+
+{#--- Interface definitions #}
+{%- for interface in interfaces %}
+{%- include "interface_definition.tmpl" %}
+{%- endfor %}
+
+ var exports = {};
+{% for constant in module.constants %}
+ exports.{{constant.name}} = {{constant.name}};
+{%- endfor %}
+{%- for enum in enums %}
+ exports.{{enum.name}} = {{enum.name}};
+{%- endfor %}
+{%- for struct in structs if struct.exported %}
+ exports.{{struct.name}} = {{struct.name}};
+{%- endfor %}
+{%- for interface in interfaces %}
+ exports.{{interface.name}}Proxy = {{interface.name}}Proxy;
+ exports.{{interface.name}}Stub = {{interface.name}}Stub;
+{%- endfor %}
+ return exports;
+});
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl
new file mode 100644
index 00000000000..ae1ccb079af
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl
@@ -0,0 +1,72 @@
+{#--- Begin #}
+ function {{struct.name}}() {
+ this.initDefaults_();
+ }
+
+{#--- Enums #}
+{%- from "enum_definition.tmpl" import enum_def %}
+{% for enum in struct.enums %}
+ {{enum_def("%s.%s"|format(struct.name, enum.name), enum, module)}}
+{% endfor %}
+
+{#--- Constants #}
+{% for constant in struct.constants %}
+ {{struct.name}}.{{constant.name}} = {{constant.value|expression_to_text}};
+{% endfor %}
+
+{#--- Set up defaults #}
+ {{struct.name}}.prototype.initDefaults_ = function() {
+{%- for packed_field in struct.packed.packed_fields %}
+ this.{{packed_field.field.name}} = {{packed_field.field|default_value}};
+{%- endfor %}
+ };
+
+{#--- Encoding and decoding #}
+
+ {{struct.name}}.encodedSize = codec.kStructHeaderSize + {{struct.packed|payload_size}};
+
+ {{struct.name}}.decode = function(decoder) {
+ var packed;
+ var val = new {{struct.name}}();
+ var numberOfBytes = decoder.readUint32();
+ var numberOfFields = decoder.readUint32();
+{%- for byte in struct.bytes %}
+{%- if byte.packed_fields|length > 1 %}
+ packed = decoder.readUint8();
+{%- for packed_field in byte.packed_fields %}
+ val.{{packed_field.field.name}} = (packed >> {{packed_field.bit}}) & 1 ? true : false;
+{%- endfor %}
+{%- else %}
+{%- for packed_field in byte.packed_fields %}
+ val.{{packed_field.field.name}} = decoder.{{packed_field.field.kind|decode_snippet}};
+{%- endfor %}
+{%- endif %}
+{%- if byte.is_padding %}
+ decoder.skip(1);
+{%- endif %}
+{%- endfor %}
+ return val;
+ };
+
+ {{struct.name}}.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32({{struct.name}}.encodedSize);
+ encoder.writeUint32({{struct.packed.packed_fields|length}});
+
+{%- for byte in struct.bytes %}
+{%- if byte.packed_fields|length > 1 %}
+ packed = 0;
+{%- for packed_field in byte.packed_fields %}
+ packed |= (val.{{packed_field.field.name}} & 1) << {{packed_field.bit}}
+{%- endfor %}
+ encoder.writeUint8(packed);
+{%- else %}
+{%- for packed_field in byte.packed_fields %}
+ encoder.{{packed_field.field.kind|encode_snippet}}val.{{packed_field.field.name}});
+{%- endfor %}
+{%- endif %}
+{%- if byte.is_padding %}
+ encoder.skip(1);
+{%- endif %}
+{%- endfor %}
+ };
diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
new file mode 100644
index 00000000000..812dd47c609
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -0,0 +1,286 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generates C++ source files from a mojom.Module."""
+
+import mojom.generate.generator as generator
+import mojom.generate.module as mojom
+import mojom.generate.pack as pack
+from mojom.generate.template_expander import UseJinja
+
+
+_kind_to_cpp_type = {
+ mojom.BOOL: "bool",
+ mojom.INT8: "int8_t",
+ mojom.UINT8: "uint8_t",
+ mojom.INT16: "int16_t",
+ mojom.UINT16: "uint16_t",
+ mojom.INT32: "int32_t",
+ mojom.UINT32: "uint32_t",
+ mojom.FLOAT: "float",
+ mojom.HANDLE: "mojo::Handle",
+ mojom.DCPIPE: "mojo::DataPipeConsumerHandle",
+ mojom.DPPIPE: "mojo::DataPipeProducerHandle",
+ mojom.MSGPIPE: "mojo::MessagePipeHandle",
+ mojom.SHAREDBUFFER: "mojo::SharedBufferHandle",
+ mojom.INT64: "int64_t",
+ mojom.UINT64: "uint64_t",
+ mojom.DOUBLE: "double",
+}
+
+def DefaultValue(field):
+ if field.default:
+ if isinstance(field.kind, mojom.Struct):
+ assert field.default == "default"
+ return "%s::New()" % GetNameForKind(field.kind)
+ return ExpressionToText(field.default)
+ return ""
+
+def NamespaceToArray(namespace):
+ return namespace.split('.') if namespace else []
+
+def GetNameForKind(kind, internal = False):
+ parts = []
+ if kind.imported_from:
+ parts.extend(NamespaceToArray(kind.imported_from["namespace"]))
+ if internal:
+ parts.append("internal")
+ if kind.parent_kind:
+ parts.append(kind.parent_kind.name)
+ parts.append(kind.name)
+ return "::".join(parts)
+
+def GetCppType(kind):
+ if isinstance(kind, mojom.Struct):
+ return "%s_Data*" % GetNameForKind(kind, internal=True)
+ if isinstance(kind, mojom.Array):
+ return "mojo::internal::Array_Data<%s>*" % GetCppType(kind.kind)
+ if isinstance(kind, mojom.Interface) or \
+ isinstance(kind, mojom.InterfaceRequest):
+ return "mojo::MessagePipeHandle"
+ if isinstance(kind, mojom.Enum):
+ return "int32_t"
+ if kind.spec == 's':
+ return "mojo::internal::String_Data*"
+ return _kind_to_cpp_type[kind]
+
+def GetCppPodType(kind):
+ if kind.spec == 's':
+ return "char*"
+ return _kind_to_cpp_type[kind]
+
+def GetCppArrayArgWrapperType(kind):
+ if isinstance(kind, mojom.Enum):
+ return GetNameForKind(kind)
+ if isinstance(kind, mojom.Struct):
+ return "%sPtr" % GetNameForKind(kind)
+ if isinstance(kind, mojom.Array):
+ return "mojo::Array<%s> " % GetCppArrayArgWrapperType(kind.kind)
+ if isinstance(kind, mojom.Interface):
+ raise Exception("Arrays of interfaces not yet supported!")
+ if isinstance(kind, mojom.InterfaceRequest):
+ raise Exception("Arrays of interface requests not yet supported!")
+ if kind.spec == 's':
+ return "mojo::String"
+ if kind.spec == 'h':
+ return "mojo::ScopedHandle"
+ if kind.spec == 'h:d:c':
+ return "mojo::ScopedDataPipeConsumerHandle"
+ if kind.spec == 'h:d:p':
+ return "mojo::ScopedDataPipeProducerHandle"
+ if kind.spec == 'h:m':
+ return "mojo::ScopedMessagePipeHandle"
+ if kind.spec == 'h:s':
+ return "mojo::ScopedSharedBufferHandle"
+ return _kind_to_cpp_type[kind]
+
+def GetCppResultWrapperType(kind):
+ if isinstance(kind, mojom.Enum):
+ return GetNameForKind(kind)
+ if isinstance(kind, mojom.Struct):
+ return "%sPtr" % GetNameForKind(kind)
+ if isinstance(kind, mojom.Array):
+ return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind)
+ if isinstance(kind, mojom.Interface):
+ return "%sPtr" % GetNameForKind(kind)
+ if isinstance(kind, mojom.InterfaceRequest):
+ return "mojo::InterfaceRequest<%s>" % GetNameForKind(kind.kind)
+ if kind.spec == 's':
+ return "mojo::String"
+ if kind.spec == 'h':
+ return "mojo::ScopedHandle"
+ if kind.spec == 'h:d:c':
+ return "mojo::ScopedDataPipeConsumerHandle"
+ if kind.spec == 'h:d:p':
+ return "mojo::ScopedDataPipeProducerHandle"
+ if kind.spec == 'h:m':
+ return "mojo::ScopedMessagePipeHandle"
+ if kind.spec == 'h:s':
+ return "mojo::ScopedSharedBufferHandle"
+ return _kind_to_cpp_type[kind]
+
+def GetCppWrapperType(kind):
+ if isinstance(kind, mojom.Enum):
+ return GetNameForKind(kind)
+ if isinstance(kind, mojom.Struct):
+ return "%sPtr" % GetNameForKind(kind)
+ if isinstance(kind, mojom.Array):
+ return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind)
+ if isinstance(kind, mojom.Interface):
+ return "mojo::ScopedMessagePipeHandle"
+ if isinstance(kind, mojom.InterfaceRequest):
+ raise Exception("InterfaceRequest fields not supported!")
+ if kind.spec == 's':
+ return "mojo::String"
+ if kind.spec == 'h':
+ return "mojo::ScopedHandle"
+ if kind.spec == 'h:d:c':
+ return "mojo::ScopedDataPipeConsumerHandle"
+ if kind.spec == 'h:d:p':
+ return "mojo::ScopedDataPipeProducerHandle"
+ if kind.spec == 'h:m':
+ return "mojo::ScopedMessagePipeHandle"
+ if kind.spec == 'h:s':
+ return "mojo::ScopedSharedBufferHandle"
+ return _kind_to_cpp_type[kind]
+
+def GetCppConstWrapperType(kind):
+ if isinstance(kind, mojom.Struct):
+ return "%sPtr" % GetNameForKind(kind)
+ if isinstance(kind, mojom.Array):
+ return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind)
+ if isinstance(kind, mojom.Interface):
+ return "%sPtr" % GetNameForKind(kind)
+ if isinstance(kind, mojom.InterfaceRequest):
+ return "mojo::InterfaceRequest<%s>" % GetNameForKind(kind.kind)
+ if isinstance(kind, mojom.Enum):
+ return GetNameForKind(kind)
+ if kind.spec == 's':
+ return "const mojo::String&"
+ if kind.spec == 'h':
+ return "mojo::ScopedHandle"
+ if kind.spec == 'h:d:c':
+ return "mojo::ScopedDataPipeConsumerHandle"
+ if kind.spec == 'h:d:p':
+ return "mojo::ScopedDataPipeProducerHandle"
+ if kind.spec == 'h:m':
+ return "mojo::ScopedMessagePipeHandle"
+ if kind.spec == 'h:s':
+ return "mojo::ScopedSharedBufferHandle"
+ if not kind in _kind_to_cpp_type:
+ print "missing:", kind.spec
+ return _kind_to_cpp_type[kind]
+
+def GetCppFieldType(kind):
+ if isinstance(kind, mojom.Struct):
+ return ("mojo::internal::StructPointer<%s_Data>" %
+ GetNameForKind(kind, internal=True))
+ if isinstance(kind, mojom.Array):
+ return "mojo::internal::ArrayPointer<%s>" % GetCppType(kind.kind)
+ if isinstance(kind, mojom.Interface) or \
+ isinstance(kind, mojom.InterfaceRequest):
+ return "mojo::MessagePipeHandle"
+ if isinstance(kind, mojom.Enum):
+ return GetNameForKind(kind)
+ if kind.spec == 's':
+ return "mojo::internal::StringPointer"
+ return _kind_to_cpp_type[kind]
+
+def IsStructWithHandles(struct):
+ for pf in struct.packed.packed_fields:
+ if generator.IsHandleKind(pf.field.kind):
+ return True
+ return False
+
+def TranslateConstants(token):
+ if isinstance(token, (mojom.NamedValue, mojom.EnumValue)):
+ # Both variable and enum constants are constructed like:
+ # Namespace::Struct::CONSTANT_NAME
+ name = []
+ if token.imported_from:
+ name.extend(NamespaceToArray(token.namespace))
+ if token.parent_kind:
+ name.append(token.parent_kind.name)
+ name.append(token.name)
+ return "::".join(name)
+ return token
+
+def ExpressionToText(value):
+ return TranslateConstants(value)
+
+def HasCallbacks(interface):
+ for method in interface.methods:
+ if method.response_parameters != None:
+ return True
+ return False
+
+def ShouldInlineStruct(struct):
+ # TODO(darin): Base this on the size of the wrapper class.
+ if len(struct.fields) > 4:
+ return False
+ for field in struct.fields:
+ if generator.IsHandleKind(field.kind) or generator.IsObjectKind(field.kind):
+ return False
+ return True
+
+_HEADER_SIZE = 8
+
+class Generator(generator.Generator):
+
+ cpp_filters = {
+ "cpp_const_wrapper_type": GetCppConstWrapperType,
+ "cpp_field_type": GetCppFieldType,
+ "cpp_pod_type": GetCppPodType,
+ "cpp_result_type": GetCppResultWrapperType,
+ "cpp_type": GetCppType,
+ "cpp_wrapper_type": GetCppWrapperType,
+ "default_value": DefaultValue,
+ "expression_to_text": ExpressionToText,
+ "get_name_for_kind": GetNameForKind,
+ "get_pad": pack.GetPad,
+ "has_callbacks": HasCallbacks,
+ "should_inline": ShouldInlineStruct,
+ "is_enum_kind": generator.IsEnumKind,
+ "is_move_only_kind": generator.IsMoveOnlyKind,
+ "is_handle_kind": generator.IsHandleKind,
+ "is_interface_kind": generator.IsInterfaceKind,
+ "is_interface_request_kind": generator.IsInterfaceRequestKind,
+ "is_object_kind": generator.IsObjectKind,
+ "is_string_kind": generator.IsStringKind,
+ "is_struct_with_handles": IsStructWithHandles,
+ "struct_size": lambda ps: ps.GetTotalSize() + _HEADER_SIZE,
+ "struct_from_method": generator.GetStructFromMethod,
+ "response_struct_from_method": generator.GetResponseStructFromMethod,
+ "stylize_method": generator.StudlyCapsToCamel,
+ }
+
+ def GetJinjaExports(self):
+ return {
+ "module": self.module,
+ "namespace": self.module.namespace,
+ "namespaces_as_array": NamespaceToArray(self.module.namespace),
+ "imports": self.module.imports,
+ "kinds": self.module.kinds,
+ "enums": self.module.enums,
+ "structs": self.GetStructs(),
+ "interfaces": self.module.interfaces,
+ }
+
+ @UseJinja("cpp_templates/module.h.tmpl", filters=cpp_filters)
+ def GenerateModuleHeader(self):
+ return self.GetJinjaExports()
+
+ @UseJinja("cpp_templates/module-internal.h.tmpl", filters=cpp_filters)
+ def GenerateModuleInternalHeader(self):
+ return self.GetJinjaExports()
+
+ @UseJinja("cpp_templates/module.cc.tmpl", filters=cpp_filters)
+ def GenerateModuleSource(self):
+ return self.GetJinjaExports()
+
+ def GenerateFiles(self, args):
+ self.Write(self.GenerateModuleHeader(), "%s.h" % self.module.name)
+ self.Write(self.GenerateModuleInternalHeader(),
+ "%s-internal.h" % self.module.name)
+ self.Write(self.GenerateModuleSource(), "%s.cc" % self.module.name)
diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py
new file mode 100644
index 00000000000..ca43b845630
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -0,0 +1,187 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generates java source files from a mojom.Module."""
+
+import argparse
+import os
+import re
+
+import mojom.generate.generator as generator
+import mojom.generate.module as mojom
+from mojom.generate.template_expander import UseJinja
+
+
+GENERATOR_PREFIX = 'java'
+
+_spec_to_java_type = {
+ 'b': 'boolean',
+ 'd': 'double',
+ 'f': 'float',
+ 'h:d:c': 'org.chromium.mojo.system.DataPipe.ConsumerHandle',
+ 'h:d:p': 'org.chromium.mojo.system.DataPipe.ProducerHandle',
+ 'h:m': 'org.chromium.mojo.system.MessagePipeHandle',
+ 'h': 'org.chromium.mojo.system.UntypedHandle',
+ 'h:s': 'org.chromium.mojo.system.SharedBufferHandle',
+ 'i16': 'short',
+ 'i32': 'int',
+ 'i64': 'long',
+ 'i8': 'byte',
+ 's': 'String',
+ 'u16': 'short',
+ 'u32': 'int',
+ 'u64': 'long',
+ 'u8': 'byte',
+}
+
+
+def NameToComponent(name):
+ # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
+ # HTTP_Entry2_FooBar)
+ name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name)
+ # insert '_' between non upper and start of upper blocks (e.g.,
+ # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar)
+ name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name)
+ return [x.lower() for x in name.split('_')]
+
+def CapitalizeFirst(string):
+ return string[0].upper() + string[1:]
+
+def UpperCamelCase(name):
+ return ''.join([CapitalizeFirst(x) for x in NameToComponent(name)])
+
+def CamelCase(name):
+ uccc = UpperCamelCase(name)
+ return uccc[0].lower() + uccc[1:]
+
+def ConstantStyle(name):
+ components = NameToComponent(name)
+ if components[0] == 'k':
+ components = components[1:]
+ return '_'.join([x.upper() for x in components])
+
+def GetNameForElement(element):
+ if (isinstance(element, mojom.Enum) or
+ isinstance(element, mojom.Interface) or
+ isinstance(element, mojom.Struct)):
+ return UpperCamelCase(element.name)
+ if (isinstance(element, mojom.Method) or
+ isinstance(element, mojom.Parameter) or
+ isinstance(element, mojom.Field)):
+ return CamelCase(element.name)
+ if isinstance(element, mojom.EnumValue):
+ return (UpperCamelCase(element.enum_name) + '.' +
+ ConstantStyle(element.name))
+ if (isinstance(element, mojom.NamedValue) or
+ isinstance(element, mojom.Constant)):
+ return ConstantStyle(element.name)
+ raise Exception("Unexpected element: " % element)
+
+def ParseStringAttribute(attribute):
+ assert isinstance(attribute, basestring)
+ return attribute
+
+def GetPackage(module):
+ if 'JavaPackage' in module.attributes:
+ return ParseStringAttribute(module.attributes['JavaPackage'])
+ # Default package.
+ return "org.chromium.mojom." + module.namespace
+
+def GetNameForKind(kind):
+ def _GetNameHierachy(kind):
+ hierachy = []
+ if kind.parent_kind:
+ hierachy = _GetNameHierachy(kind.parent_kind)
+ hierachy.append(kind.name)
+ return hierachy
+
+ elements = [GetPackage(kind.module)]
+ elements += _GetNameHierachy(kind)
+ return '.'.join(elements)
+
+def GetJavaType(kind):
+ if isinstance(kind, (mojom.Struct, mojom.Interface)):
+ return GetNameForKind(kind)
+ if isinstance(kind, mojom.Array):
+ return "%s[]" % GetJavaType(kind.kind)
+ if isinstance(kind, mojom.Enum):
+ return "int"
+ return _spec_to_java_type[kind.spec]
+
+def ExpressionToText(token):
+ def _TranslateNamedValue(named_value):
+ entity_name = GetNameForElement(named_value)
+ if named_value.parent_kind:
+ return GetJavaType(named_value.parent_kind) + '.' + entity_name
+ # Handle the case where named_value is a module level constant:
+ if not isinstance(named_value, mojom.EnumValue):
+ entity_name = (GetConstantsMainEntityName(named_value.module) + '.' +
+ entity_name)
+ return GetPackage(named_value.module) + '.' + entity_name
+
+ if isinstance(token, mojom.NamedValue):
+ return _TranslateNamedValue(token)
+ # Add Long suffix to all number literals.
+ if re.match('^[0-9]+$', token):
+ return token + 'L'
+ return token
+
+def GetConstantsMainEntityName(module):
+ if 'JavaConstantsClassName' in module.attributes:
+ return ParseStringAttribute(module.attributes['JavaConstantsClassName'])
+ # This constructs the name of the embedding classes for module level constants
+ # by extracting the mojom's filename and prepending it to Constants.
+ return (UpperCamelCase(module.path.split('/')[-1].rsplit('.', 1)[0]) +
+ 'Constants')
+
+class Generator(generator.Generator):
+
+ java_filters = {
+ "expression_to_text": ExpressionToText,
+ "java_type": GetJavaType,
+ "name": GetNameForElement,
+ }
+
+ def GetJinjaExports(self):
+ return {
+ "module": self.module,
+ "package": GetPackage(self.module),
+ }
+
+ @UseJinja("java_templates/enum.java.tmpl", filters=java_filters,
+ lstrip_blocks=True, trim_blocks=True)
+ def GenerateEnumSource(self, enum):
+ exports = self.GetJinjaExports()
+ exports.update({"enum": enum})
+ return exports
+
+ @UseJinja("java_templates/constants.java.tmpl", filters=java_filters,
+ lstrip_blocks=True, trim_blocks=True)
+ def GenerateConstantsSource(self, module):
+ exports = self.GetJinjaExports()
+ exports.update({"main_entity": GetConstantsMainEntityName(module),
+ "constants": module.constants})
+ return exports
+
+ def GenerateFiles(self, unparsed_args):
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--java_output_directory", dest="java_output_directory")
+ args = parser.parse_args(unparsed_args)
+ if self.output_dir and args.java_output_directory:
+ self.output_dir = os.path.join(args.java_output_directory,
+ GetPackage(self.module).replace('.', '/'))
+ if not os.path.exists(self.output_dir):
+ try:
+ os.makedirs(self.output_dir)
+ except:
+ # Ignore errors on directory creation.
+ pass
+
+ for enum in self.module.enums:
+ self.Write(self.GenerateEnumSource(enum),
+ "%s.java" % GetNameForElement(enum))
+
+ if self.module.constants:
+ self.Write(self.GenerateConstantsSource(self.module),
+ "%s.java" % GetConstantsMainEntityName(self.module))
diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py
new file mode 100644
index 00000000000..1fa351037c6
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -0,0 +1,186 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generates JavaScript source files from a mojom.Module."""
+
+import mojom.generate.generator as generator
+import mojom.generate.module as mojom
+import mojom.generate.pack as pack
+from mojom.generate.template_expander import UseJinja
+
+_kind_to_javascript_default_value = {
+ mojom.BOOL: "false",
+ mojom.INT8: "0",
+ mojom.UINT8: "0",
+ mojom.INT16: "0",
+ mojom.UINT16: "0",
+ mojom.INT32: "0",
+ mojom.UINT32: "0",
+ mojom.FLOAT: "0",
+ mojom.HANDLE: "null",
+ mojom.DCPIPE: "null",
+ mojom.DPPIPE: "null",
+ mojom.MSGPIPE: "null",
+ mojom.SHAREDBUFFER: "null",
+ mojom.INT64: "0",
+ mojom.UINT64: "0",
+ mojom.DOUBLE: "0",
+ mojom.STRING: '""',
+}
+
+
+def JavaScriptDefaultValue(field):
+ if field.default:
+ if isinstance(field.kind, mojom.Struct):
+ assert field.default == "default"
+ return "new %s()" % JavascriptType(field.kind)
+ return ExpressionToText(field.default)
+ if field.kind in mojom.PRIMITIVES:
+ return _kind_to_javascript_default_value[field.kind]
+ if isinstance(field.kind, mojom.Struct):
+ return "null"
+ if isinstance(field.kind, mojom.Array):
+ return "[]"
+ if isinstance(field.kind, mojom.Interface) or \
+ isinstance(field.kind, mojom.InterfaceRequest):
+ return _kind_to_javascript_default_value[mojom.MSGPIPE]
+ if isinstance(field.kind, mojom.Enum):
+ return "0"
+
+
+def JavaScriptPayloadSize(packed):
+ packed_fields = packed.packed_fields
+ if not packed_fields:
+ return 0
+ last_field = packed_fields[-1]
+ offset = last_field.offset + last_field.size
+ pad = pack.GetPad(offset, 8)
+ return offset + pad
+
+
+_kind_to_codec_type = {
+ mojom.BOOL: "codec.Uint8",
+ mojom.INT8: "codec.Int8",
+ mojom.UINT8: "codec.Uint8",
+ mojom.INT16: "codec.Int16",
+ mojom.UINT16: "codec.Uint16",
+ mojom.INT32: "codec.Int32",
+ mojom.UINT32: "codec.Uint32",
+ mojom.FLOAT: "codec.Float",
+ mojom.HANDLE: "codec.Handle",
+ mojom.DCPIPE: "codec.Handle",
+ mojom.DPPIPE: "codec.Handle",
+ mojom.MSGPIPE: "codec.Handle",
+ mojom.SHAREDBUFFER: "codec.Handle",
+ mojom.INT64: "codec.Int64",
+ mojom.UINT64: "codec.Uint64",
+ mojom.DOUBLE: "codec.Double",
+ mojom.STRING: "codec.String",
+}
+
+
+def CodecType(kind):
+ if kind in mojom.PRIMITIVES:
+ return _kind_to_codec_type[kind]
+ if isinstance(kind, mojom.Struct):
+ return "new codec.PointerTo(%s)" % CodecType(kind.name)
+ if isinstance(kind, mojom.Array):
+ return "new codec.ArrayOf(%s)" % CodecType(kind.kind)
+ if isinstance(kind, mojom.Interface) or \
+ isinstance(kind, mojom.InterfaceRequest):
+ return CodecType(mojom.MSGPIPE)
+ if isinstance(kind, mojom.Enum):
+ return _kind_to_codec_type[mojom.INT32]
+ return kind
+
+
+def JavaScriptDecodeSnippet(kind):
+ if kind in mojom.PRIMITIVES:
+ return "decodeStruct(%s)" % CodecType(kind)
+ if isinstance(kind, mojom.Struct):
+ return "decodeStructPointer(%s)" % CodecType(kind.name)
+ if isinstance(kind, mojom.Array):
+ return "decodeArrayPointer(%s)" % CodecType(kind.kind)
+ if isinstance(kind, mojom.Interface) or \
+ isinstance(kind, mojom.InterfaceRequest):
+ return JavaScriptDecodeSnippet(mojom.MSGPIPE)
+ if isinstance(kind, mojom.Enum):
+ return JavaScriptDecodeSnippet(mojom.INT32)
+
+
+def JavaScriptEncodeSnippet(kind):
+ if kind in mojom.PRIMITIVES:
+ return "encodeStruct(%s, " % CodecType(kind)
+ if isinstance(kind, mojom.Struct):
+ return "encodeStructPointer(%s, " % CodecType(kind.name)
+ if isinstance(kind, mojom.Array):
+ return "encodeArrayPointer(%s, " % CodecType(kind.kind)
+ if isinstance(kind, mojom.Interface) or \
+ isinstance(kind, mojom.InterfaceRequest):
+ return JavaScriptEncodeSnippet(mojom.MSGPIPE)
+ if isinstance(kind, mojom.Enum):
+ return JavaScriptEncodeSnippet(mojom.INT32)
+
+
+def TranslateConstants(token):
+ if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
+ # Both variable and enum constants are constructed like:
+ # NamespaceUid.Struct[.Enum].CONSTANT_NAME
+ name = []
+ if token.imported_from:
+ name.append(token.imported_from["unique_name"])
+ if token.parent_kind:
+ name.append(token.parent_kind.name)
+ if isinstance(token, mojom.EnumValue):
+ name.append(token.enum_name)
+ name.append(token.name)
+ return ".".join(name)
+ return token
+
+
+def ExpressionToText(value):
+ return TranslateConstants(value)
+
+
+def JavascriptType(kind):
+ if kind.imported_from:
+ return kind.imported_from["unique_name"] + "." + kind.name
+ return kind.name
+
+
+class Generator(generator.Generator):
+
+ js_filters = {
+ "default_value": JavaScriptDefaultValue,
+ "payload_size": JavaScriptPayloadSize,
+ "decode_snippet": JavaScriptDecodeSnippet,
+ "encode_snippet": JavaScriptEncodeSnippet,
+ "expression_to_text": ExpressionToText,
+ "js_type": JavascriptType,
+ "stylize_method": generator.StudlyCapsToCamel,
+ }
+
+ @UseJinja("js_templates/module.js.tmpl", filters=js_filters)
+ def GenerateJsModule(self):
+ return {
+ "namespace": self.module.namespace,
+ "imports": self.GetImports(),
+ "kinds": self.module.kinds,
+ "enums": self.module.enums,
+ "module": self.module,
+ "structs": self.GetStructs() + self.GetStructsFromMethods(),
+ "interfaces": self.module.interfaces,
+ }
+
+ def GenerateFiles(self, args):
+ self.Write(self.GenerateJsModule(), "%s.js" % self.module.name)
+
+ def GetImports(self):
+ # Since each import is assigned a variable in JS, they need to have unique
+ # names.
+ counter = 1
+ for each in self.module.imports:
+ each["unique_name"] = "import" + str(counter)
+ counter += 1
+ return self.module.imports
diff --git a/chromium/mojo/public/tools/bindings/generators/run_cpp_generator.py b/chromium/mojo/public/tools/bindings/generators/run_cpp_generator.py
new file mode 100755
index 00000000000..4c6f5974069
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/run_cpp_generator.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import ast
+import os
+import sys
+
+script_dir = os.path.dirname(os.path.realpath(__file__))
+sys.path.insert(0, os.path.join(script_dir, os.pardir, "pylib"))
+
+from mojom.generate.data
+import mojom_cpp_generator
+
+def ReadDict(file):
+ with open(file, 'r') as f:
+ s = f.read()
+ dict = ast.literal_eval(s)
+ return dict
+
+dict = ReadDict(sys.argv[1])
+module = mojom.generate.data.ModuleFromData(dict)
+dir = None
+if len(sys.argv) > 2:
+ dir = sys.argv[2]
+cpp = mojom_cpp_generator.Generator(module, ".", dir)
+cpp.GenerateFiles([])
diff --git a/chromium/mojo/public/tools/bindings/mojom.gni b/chromium/mojo/public/tools/bindings/mojom.gni
new file mode 100644
index 00000000000..3376abfb6d0
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/mojom.gni
@@ -0,0 +1,90 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Generate C++ and JavaScript source files from mojom files.
+template("mojom") {
+ assert(defined(invoker.sources),
+ "\"sources\" must be defined for the $target_name template.")
+
+ generator_root = "//mojo/public/tools/bindings"
+ generator_script = "$generator_root/mojom_bindings_generator.py"
+ generator_sources = [
+ generator_script,
+ "$generator_root/generators/cpp_templates/enum_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/interface_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/interface_definition.tmpl",
+ "$generator_root/generators/cpp_templates/interface_macros.tmpl",
+ "$generator_root/generators/cpp_templates/interface_proxy_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/interface_request_validator_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/interface_response_validator_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/interface_stub_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/module.cc.tmpl",
+ "$generator_root/generators/cpp_templates/module.h.tmpl",
+ "$generator_root/generators/cpp_templates/module-internal.h.tmpl",
+ "$generator_root/generators/cpp_templates/params_definition.tmpl",
+ "$generator_root/generators/cpp_templates/struct_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/struct_definition.tmpl",
+ "$generator_root/generators/cpp_templates/struct_serialization_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/struct_serialization_definition.tmpl",
+ "$generator_root/generators/cpp_templates/struct_macros.tmpl",
+ "$generator_root/generators/cpp_templates/wrapper_class_declaration.tmpl",
+ "$generator_root/generators/cpp_templates/wrapper_class_definition.tmpl",
+ "$generator_root/generators/js_templates/enum_definition.tmpl",
+ "$generator_root/generators/js_templates/interface_definition.tmpl",
+ "$generator_root/generators/js_templates/module.js.tmpl",
+ "$generator_root/generators/js_templates/struct_definition.tmpl",
+ "$generator_root/generators/mojom_cpp_generator.py",
+ "$generator_root/generators/mojom_js_generator.py",
+ "$generator_root/pylib/mojom/__init__.py",
+ "$generator_root/pylib/mojom/error.py",
+ "$generator_root/pylib/mojom/generate/__init__.py",
+ "$generator_root/pylib/mojom/generate/data.py",
+ "$generator_root/pylib/mojom/generate/generator.py",
+ "$generator_root/pylib/mojom/generate/module.py",
+ "$generator_root/pylib/mojom/generate/pack.py",
+ "$generator_root/pylib/mojom/generate/template_expander.py",
+ "$generator_root/pylib/mojom/parse/__init__.py",
+ "$generator_root/pylib/mojom/parse/ast.py",
+ "$generator_root/pylib/mojom/parse/lexer.py",
+ "$generator_root/pylib/mojom/parse/parser.py",
+ "$generator_root/pylib/mojom/parse/translate.py",
+ ]
+ generator_cpp_outputs = [
+ "$target_gen_dir/{{source_name_part}}.mojom.cc",
+ "$target_gen_dir/{{source_name_part}}.mojom.h",
+ "$target_gen_dir/{{source_name_part}}.mojom-internal.h",
+ ]
+ generator_js_outputs = [
+ "$target_gen_dir/{{source_name_part}}.mojom.js",
+ ]
+
+ target_visibility = ":$target_name"
+
+ generator_target_name = target_name + "_generator"
+ action_foreach(generator_target_name) {
+ visibility = target_visibility
+ script = generator_script
+ source_prereqs = generator_sources
+ sources = invoker.sources
+ outputs = generator_cpp_outputs + generator_js_outputs
+ args = [
+ "{{source}}",
+ "--use_chromium_bundled_pylibs",
+ "-d", rebase_path("//", root_build_dir),
+ "-o", rebase_path(target_gen_dir, root_build_dir),
+ ]
+ }
+
+ source_set(target_name) {
+ if (defined(invoker.visibility)) {
+ visibility = invoker.visibility
+ }
+ sources = process_file_template(invoker.sources, generator_cpp_outputs)
+ data = process_file_template(invoker.sources, generator_js_outputs)
+ deps = [
+ ":$generator_target_name",
+ "//mojo/public/cpp/bindings",
+ ]
+ }
+}
diff --git a/chromium/mojo/public/tools/bindings/mojom_bindings_generator.gypi b/chromium/mojo/public/tools/bindings/mojom_bindings_generator.gypi
new file mode 100644
index 00000000000..1341685a2ee
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/mojom_bindings_generator.gypi
@@ -0,0 +1,99 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'rules': [
+ {
+ 'rule_name': 'Generate C++, JS and Java source files from mojom files',
+ 'extension': 'mojom',
+ 'variables': {
+ 'mojom_base_output_dir':
+ '<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))',
+ 'mojom_bindings_generator':
+ '<(DEPTH)/mojo/public/tools/bindings/mojom_bindings_generator.py',
+ 'java_out_dir': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src',
+ },
+ 'inputs': [
+ '<(mojom_bindings_generator)',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/java_templates/constant_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/java_templates/constants.java.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/java_templates/enum.java.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/java_templates/header.java.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/java_templates/java_macros.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/mojom_java_generator.py',
+ '<(DEPTH)/mojo/public/tools/bindings/generators/mojom_js_generator.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/__init__.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/error.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/data.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/generator.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/module.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/pack.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/ast.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/parser.py',
+ '<(DEPTH)/mojo/public/tools/bindings/pylib/mojom/parse/translate.py',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom.h',
+ '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom.js',
+ '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom-internal.h',
+ ],
+ 'action': [
+ 'python', '<@(mojom_bindings_generator)',
+ './<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom',
+ '--use_chromium_bundled_pylibs',
+ '-d', '<(DEPTH)',
+ '-o', '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)',
+ '--java_output_directory=<(java_out_dir)',
+ ],
+ 'message': 'Generating Mojo bindings from <(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom',
+ 'process_outputs_as_sources': 1,
+ }
+ ],
+ 'include_dirs': [
+ '<(DEPTH)',
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(DEPTH)',
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'variables': {
+ 'generated_src_dirs': [
+ '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src',
+ ],
+ },
+ },
+ 'hard_dependency': 1,
+}
diff --git a/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py b/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py
new file mode 100755
index 00000000000..93325767b2a
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The frontend for the Mojo bindings system."""
+
+
+import argparse
+import imp
+import os
+import pprint
+import sys
+
+# Disable lint check for finding modules:
+# pylint: disable=F0401
+
+def _GetDirAbove(dirname):
+ """Returns the directory "above" this file containing |dirname| (which must
+ also be "above" this file)."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ assert tail
+ if tail == dirname:
+ return path
+
+# Manually check for the command-line flag. (This isn't quite right, since it
+# ignores, e.g., "--", but it's close enough.)
+if "--use_chromium_bundled_pylibs" in sys.argv[1:]:
+ sys.path.insert(0, os.path.join(_GetDirAbove("mojo"), "third_party"))
+
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ "pylib"))
+
+from mojom.error import Error
+from mojom.generate.data import OrderedModuleFromData
+from mojom.parse.parser import Parse
+from mojom.parse.translate import Translate
+
+
+def LoadGenerators(generators_string):
+ if not generators_string:
+ return [] # No generators.
+
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ generators = []
+ for generator_name in [s.strip() for s in generators_string.split(",")]:
+ # "Built-in" generators:
+ if generator_name.lower() == "c++":
+ generator_name = os.path.join(script_dir, "generators",
+ "mojom_cpp_generator.py")
+ elif generator_name.lower() == "javascript":
+ generator_name = os.path.join(script_dir, "generators",
+ "mojom_js_generator.py")
+ elif generator_name.lower() == "java":
+ generator_name = os.path.join(script_dir, "generators",
+ "mojom_java_generator.py")
+ # Specified generator python module:
+ elif generator_name.endswith(".py"):
+ pass
+ else:
+ print "Unknown generator name %s" % generator_name
+ sys.exit(1)
+ generator_module = imp.load_source(os.path.basename(generator_name)[:-3],
+ generator_name)
+ generators.append(generator_module)
+ return generators
+
+
+def MakeImportStackMessage(imported_filename_stack):
+ """Make a (human-readable) message listing a chain of imports. (Returned
+ string begins with a newline (if nonempty) and does not end with one.)"""
+ return ''.join(
+ reversed(["\n %s was imported by %s" % (a, b) for (a, b) in \
+ zip(imported_filename_stack[1:], imported_filename_stack)]))
+
+
+# Disable check for dangerous default arguments (they're "private" keyword
+# arguments; note that we want |_processed_files| to memoize across invocations
+# of |ProcessFile()|):
+# pylint: disable=W0102
+def ProcessFile(args, remaining_args, generator_modules, filename,
+ _processed_files={}, _imported_filename_stack=None):
+ # Memoized results.
+ if filename in _processed_files:
+ return _processed_files[filename]
+
+ if _imported_filename_stack is None:
+ _imported_filename_stack = []
+
+ # Ensure we only visit each file once.
+ if filename in _imported_filename_stack:
+ print "%s: Error: Circular dependency" % filename + \
+ MakeImportStackMessage(_imported_filename_stack + [filename])
+ sys.exit(1)
+
+ try:
+ with open(filename) as f:
+ source = f.read()
+ except IOError as e:
+ print "%s: Error: %s" % (e.filename, e.strerror) + \
+ MakeImportStackMessage(_imported_filename_stack + [filename])
+ sys.exit(1)
+
+ try:
+ tree = Parse(source, filename)
+ except Error as e:
+ print str(e) + MakeImportStackMessage(_imported_filename_stack + [filename])
+ sys.exit(1)
+
+ dirname, name = os.path.split(filename)
+ mojom = Translate(tree, name)
+ if args.debug_print_intermediate:
+ pprint.PrettyPrinter().pprint(mojom)
+
+ # Process all our imports first and collect the module object for each.
+ # We use these to generate proper type info.
+ for import_data in mojom['imports']:
+ import_filename = os.path.join(dirname, import_data['filename'])
+ import_data['module'] = ProcessFile(
+ args, remaining_args, generator_modules, import_filename,
+ _processed_files=_processed_files,
+ _imported_filename_stack=_imported_filename_stack + [filename])
+
+ module = OrderedModuleFromData(mojom)
+
+ # Set the path as relative to the source root.
+ module.path = os.path.relpath(os.path.abspath(filename),
+ os.path.abspath(args.depth))
+
+ # Normalize to unix-style path here to keep the generators simpler.
+ module.path = module.path.replace('\\', '/')
+
+ for generator_module in generator_modules:
+ generator = generator_module.Generator(module, args.output_dir)
+ filtered_args = []
+ if hasattr(generator_module, 'GENERATOR_PREFIX'):
+ prefix = '--' + generator_module.GENERATOR_PREFIX + '_'
+ filtered_args = [arg for arg in remaining_args if arg.startswith(prefix)]
+ generator.GenerateFiles(filtered_args)
+
+ # Save result.
+ _processed_files[filename] = module
+ return module
+# pylint: enable=W0102
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Generate bindings from mojom files.")
+ parser.add_argument("filename", nargs="+",
+ help="mojom input file")
+ parser.add_argument("-d", "--depth", dest="depth", default=".",
+ help="depth from source root")
+ parser.add_argument("-o", "--output_dir", dest="output_dir", default=".",
+ help="output directory for generated files")
+ parser.add_argument("-g", "--generators", dest="generators_string",
+ metavar="GENERATORS", default="c++,javascript,java",
+ help="comma-separated list of generators")
+ parser.add_argument("--debug_print_intermediate", action="store_true",
+ help="print the intermediate representation")
+ parser.add_argument("--use_chromium_bundled_pylibs", action="store_true",
+ help="use Python modules bundled in the Chromium source")
+ (args, remaining_args) = parser.parse_known_args()
+
+ generator_modules = LoadGenerators(args.generators_string)
+
+ if not os.path.exists(args.output_dir):
+ os.makedirs(args.output_dir)
+
+ for filename in args.filename:
+ ProcessFile(args, remaining_args, generator_modules, filename)
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py b/chromium/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py
new file mode 100644
index 00000000000..de388561cb5
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/mojom_bindings_generator_unittest.py
@@ -0,0 +1,23 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from mojom_bindings_generator import MakeImportStackMessage
+
+
+class MojoBindingsGeneratorTest(unittest.TestCase):
+ """Tests mojo_bindings_generator."""
+
+ def testMakeImportStackMessage(self):
+ """Tests MakeImportStackMessage()."""
+ self.assertEquals(MakeImportStackMessage(["x"]), "")
+ self.assertEquals(MakeImportStackMessage(["x", "y"]),
+ "\n y was imported by x")
+ self.assertEquals(MakeImportStackMessage(["x", "y", "z"]),
+ "\n z was imported by y\n y was imported by x")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/__init__.py b/chromium/mojo/public/tools/bindings/pylib/mojom/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/__init__.py
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/error.py b/chromium/mojo/public/tools/bindings/pylib/mojom/error.py
new file mode 100644
index 00000000000..99522b9507f
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/error.py
@@ -0,0 +1,27 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class Error(Exception):
+ """Base class for Mojo IDL bindings parser/generator errors."""
+
+ def __init__(self, filename, message, lineno=None, addenda=None, **kwargs):
+ """|filename| is the (primary) file which caused the error, |message| is the
+ error message, |lineno| is the 1-based line number (or |None| if not
+ applicable/available), and |addenda| is a list of additional lines to append
+ to the final error message."""
+ Exception.__init__(self, **kwargs)
+ self.filename = filename
+ self.message = message
+ self.lineno = lineno
+ self.addenda = addenda
+
+ def __str__(self):
+ if self.lineno:
+ s = "%s:%d: Error: %s" % (self.filename, self.lineno, self.message)
+ else:
+ s = "%s: Error: %s" % (self.filename, self.message)
+ return "\n".join([s] + self.addenda) if self.addenda else s
+
+ def __repr__(self):
+ return str(self)
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data.py
new file mode 100644
index 00000000000..608603b8584
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data.py
@@ -0,0 +1,348 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO(vtl): "data" is a pretty vague name. Rename it?
+
+import copy
+
+import module as mojom
+
+# This module provides a mechanism to turn mojom Modules to dictionaries and
+# back again. This can be used to persist a mojom Module created progromatically
+# or to read a dictionary from code or a file.
+# Example:
+# test_dict = {
+# 'name': 'test',
+# 'namespace': 'testspace',
+# 'structs': [{
+# 'name': 'teststruct',
+# 'fields': [
+# {'name': 'testfield1', 'kind': 'i32'},
+# {'name': 'testfield2', 'kind': 'a:i32', 'ordinal': 42}]}],
+# 'interfaces': [{
+# 'name': 'Server',
+# 'methods': [{
+# 'name': 'Foo',
+# 'parameters': [{
+# 'name': 'foo', 'kind': 'i32'},
+# {'name': 'bar', 'kind': 'a:x:teststruct'}],
+# 'ordinal': 42}]}]
+# }
+# test_module = data.ModuleFromData(test_dict)
+
+# Used to create a subclass of str that supports sorting by index, to make
+# pretty printing maintain the order.
+def istr(index, string):
+ class IndexedString(str):
+ def __lt__(self, other):
+ return self.__index__ < other.__index__
+
+ istr = IndexedString(string)
+ istr.__index__ = index
+ return istr
+
+def LookupKind(kinds, spec, scope):
+ """Tries to find which Kind a spec refers to, given the scope in which its
+ referenced. Starts checking from the narrowest scope to most general. For
+ example, given a struct field like
+ Foo.Bar x;
+ Foo.Bar could refer to the type 'Bar' in the 'Foo' namespace, or an inner
+ type 'Bar' in the struct 'Foo' in the current namespace.
+
+ |scope| is a tuple that looks like (namespace, struct/interface), referring
+ to the location where the type is referenced."""
+ if spec.startswith('x:'):
+ name = spec[2:]
+ for i in xrange(len(scope), -1, -1):
+ test_spec = 'x:'
+ if i > 0:
+ test_spec += '.'.join(scope[:i]) + '.'
+ test_spec += name
+ kind = kinds.get(test_spec)
+ if kind:
+ return kind
+
+ return kinds.get(spec)
+
+def LookupValue(values, name, scope):
+ """Like LookupKind, but for constant values."""
+ for i in xrange(len(scope), -1, -1):
+ if i > 0:
+ test_spec = '.'.join(scope[:i]) + '.'
+ test_spec += name
+ value = values.get(test_spec)
+ if value:
+ return value
+
+ return values.get(name)
+
+def FixupExpression(module, value, scope):
+ """Translates an IDENTIFIER into a structured Value object."""
+ if isinstance(value, tuple) and value[0] == 'IDENTIFIER':
+ result = LookupValue(module.values, value[1], scope)
+ if result:
+ return result
+ return value
+
+def KindToData(kind):
+ return kind.spec
+
+def KindFromData(kinds, data, scope):
+ kind = LookupKind(kinds, data, scope)
+ if kind:
+ return kind
+ if data.startswith('a:'):
+ kind = mojom.Array()
+ kind.kind = KindFromData(kinds, data[2:], scope)
+ elif data.startswith('r:'):
+ kind = mojom.InterfaceRequest()
+ kind.kind = KindFromData(kinds, data[2:], scope)
+ else:
+ kind = mojom.Kind()
+ kind.spec = data
+ kinds[data] = kind
+ return kind
+
+def KindFromImport(original_kind, imported_from):
+ """Used with 'import module' - clones the kind imported from the given
+ module's namespace. Only used with Structs, Interfaces and Enums."""
+ kind = copy.deepcopy(original_kind)
+ kind.imported_from = imported_from
+ return kind
+
+def ImportFromData(module, data):
+ import_module = data['module']
+
+ import_item = {}
+ import_item['module_name'] = import_module.name
+ import_item['namespace'] = import_module.namespace
+ import_item['module'] = import_module
+
+ # Copy the struct kinds from our imports into the current module.
+ for kind in import_module.kinds.itervalues():
+ if (isinstance(kind, (mojom.Struct, mojom.Enum, mojom.Interface)) and
+ kind.imported_from is None):
+ kind = KindFromImport(kind, import_item)
+ module.kinds[kind.spec] = kind
+ # Ditto for values.
+ for value in import_module.values.itervalues():
+ if value.imported_from is None:
+ value = copy.deepcopy(value)
+ value.imported_from = import_item
+ module.values[value.GetSpec()] = value
+
+ return import_item
+
+def StructToData(struct):
+ return {
+ istr(0, 'name'): struct.name,
+ istr(1, 'fields'): map(FieldToData, struct.fields)
+ }
+
+def StructFromData(module, data):
+ struct = mojom.Struct(module=module)
+ struct.name = data['name']
+ struct.attributes = data['attributes']
+ struct.spec = 'x:' + module.namespace + '.' + struct.name
+ module.kinds[struct.spec] = struct
+ struct.enums = map(lambda enum:
+ EnumFromData(module, enum, struct), data['enums'])
+ struct.constants = map(lambda constant:
+ ConstantFromData(module, constant, struct), data['constants'])
+ # Stash fields data here temporarily.
+ struct.fields_data = data['fields']
+ return struct
+
+def FieldToData(field):
+ data = {
+ istr(0, 'name'): field.name,
+ istr(1, 'kind'): KindToData(field.kind)
+ }
+ if field.ordinal != None:
+ data[istr(2, 'ordinal')] = field.ordinal
+ if field.default != None:
+ data[istr(3, 'default')] = field.default
+ return data
+
+def FieldFromData(module, data, struct):
+ field = mojom.Field()
+ field.name = data['name']
+ field.kind = KindFromData(
+ module.kinds, data['kind'], (module.namespace, struct.name))
+ field.ordinal = data.get('ordinal')
+ field.default = FixupExpression(
+ module, data.get('default'), (module.namespace, struct.name))
+ return field
+
+def ParameterToData(parameter):
+ data = {
+ istr(0, 'name'): parameter.name,
+ istr(1, 'kind'): parameter.kind.spec
+ }
+ if parameter.ordinal != None:
+ data[istr(2, 'ordinal')] = parameter.ordinal
+ if parameter.default != None:
+ data[istr(3, 'default')] = parameter.default
+ return data
+
+def ParameterFromData(module, data, interface):
+ parameter = mojom.Parameter()
+ parameter.name = data['name']
+ parameter.kind = KindFromData(
+ module.kinds, data['kind'], (module.namespace, interface.name))
+ parameter.ordinal = data.get('ordinal')
+ parameter.default = data.get('default')
+ return parameter
+
+def MethodToData(method):
+ data = {
+ istr(0, 'name'): method.name,
+ istr(1, 'parameters'): map(ParameterToData, method.parameters)
+ }
+ if method.ordinal != None:
+ data[istr(2, 'ordinal')] = method.ordinal
+ if method.response_parameters != None:
+ data[istr(3, 'response_parameters')] = map(
+ ParameterToData, method.response_parameters)
+ return data
+
+def MethodFromData(module, data, interface):
+ method = mojom.Method(interface, data['name'], ordinal=data.get('ordinal'))
+ method.default = data.get('default')
+ method.parameters = map(lambda parameter:
+ ParameterFromData(module, parameter, interface), data['parameters'])
+ if data.has_key('response_parameters'):
+ method.response_parameters = map(
+ lambda parameter: ParameterFromData(module, parameter, interface),
+ data['response_parameters'])
+ return method
+
+def InterfaceToData(interface):
+ return {
+ istr(0, 'name'): interface.name,
+ istr(1, 'client'): interface.client,
+ istr(2, 'methods'): map(MethodToData, interface.methods)
+ }
+
+def InterfaceFromData(module, data):
+ interface = mojom.Interface(module=module)
+ interface.name = data['name']
+ interface.spec = 'x:' + module.namespace + '.' + interface.name
+ interface.client = data['client'] if data.has_key('client') else None
+ module.kinds[interface.spec] = interface
+ interface.enums = map(lambda enum:
+ EnumFromData(module, enum, interface), data['enums'])
+ interface.constants = map(lambda constant:
+ ConstantFromData(module, constant, interface), data['constants'])
+ # Stash methods data here temporarily.
+ interface.methods_data = data['methods']
+ return interface
+
+def EnumFieldFromData(module, enum, data, parent_kind):
+ field = mojom.EnumField()
+ field.name = data['name']
+ # TODO(mpcomplete): FixupExpression should be done in the second pass,
+ # so constants and enums can refer to each other.
+ # TODO(mpcomplete): But then, what if constants are initialized to an enum? Or
+ # vice versa?
+ if parent_kind:
+ field.value = FixupExpression(
+ module, data['value'], (module.namespace, parent_kind.name))
+ else:
+ field.value = FixupExpression(
+ module, data['value'], (module.namespace, ))
+ value = mojom.EnumValue(module, enum, field)
+ module.values[value.GetSpec()] = value
+ return field
+
+def EnumFromData(module, data, parent_kind):
+ enum = mojom.Enum(module=module)
+ enum.name = data['name']
+ name = enum.name
+ if parent_kind:
+ name = parent_kind.name + '.' + name
+ enum.spec = 'x:%s.%s' % (module.namespace, name)
+ enum.parent_kind = parent_kind
+
+ enum.fields = map(
+ lambda field: EnumFieldFromData(module, enum, field, parent_kind),
+ data['fields'])
+ module.kinds[enum.spec] = enum
+ return enum
+
+def ConstantFromData(module, data, parent_kind):
+ constant = mojom.Constant()
+ constant.name = data['name']
+ if parent_kind:
+ scope = (module.namespace, parent_kind.name)
+ else:
+ scope = (module.namespace, )
+ # TODO(mpcomplete): maybe we should only support POD kinds.
+ constant.kind = KindFromData(module.kinds, data['kind'], scope)
+ constant.value = FixupExpression(module, data.get('value'), scope)
+
+ value = mojom.NamedValue(module, parent_kind, constant.name)
+ module.values[value.GetSpec()] = value
+ return constant
+
+def ModuleToData(module):
+ return {
+ istr(0, 'name'): module.name,
+ istr(1, 'namespace'): module.namespace,
+ istr(2, 'structs'): map(StructToData, module.structs),
+ istr(3, 'interfaces'): map(InterfaceToData, module.interfaces)
+ }
+
+def ModuleFromData(data):
+ module = mojom.Module()
+ module.kinds = {}
+ for kind in mojom.PRIMITIVES:
+ module.kinds[kind.spec] = kind
+
+ module.values = {}
+
+ module.name = data['name']
+ module.namespace = data['namespace']
+ module.attributes = data['attributes']
+ # Imports must come first, because they add to module.kinds which is used
+ # by by the others.
+ module.imports = map(
+ lambda import_data: ImportFromData(module, import_data),
+ data['imports'])
+
+ # First pass collects kinds.
+ module.enums = map(
+ lambda enum: EnumFromData(module, enum, None), data['enums'])
+ module.structs = map(
+ lambda struct: StructFromData(module, struct), data['structs'])
+ module.interfaces = map(
+ lambda interface: InterfaceFromData(module, interface),
+ data['interfaces'])
+ module.constants = map(
+ lambda constant: ConstantFromData(module, constant, None),
+ data['constants'])
+
+ # Second pass expands fields and methods. This allows fields and parameters
+ # to refer to kinds defined anywhere in the mojom.
+ for struct in module.structs:
+ struct.fields = map(lambda field:
+ FieldFromData(module, field, struct), struct.fields_data)
+ del struct.fields_data
+ for interface in module.interfaces:
+ interface.methods = map(lambda method:
+ MethodFromData(module, method, interface), interface.methods_data)
+ del interface.methods_data
+
+ return module
+
+def OrderedModuleFromData(data):
+ module = ModuleFromData(data)
+ next_interface_ordinal = 0
+ for interface in module.interfaces:
+ next_ordinal = 0
+ for method in interface.methods:
+ if method.ordinal is None:
+ method.ordinal = next_ordinal
+ next_ordinal = method.ordinal + 1
+ return module
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py
new file mode 100644
index 00000000000..096554c61a9
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/data_tests.py
@@ -0,0 +1,86 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+import data
+import test_support
+
+EXPECT_EQ = test_support.EXPECT_EQ
+EXPECT_TRUE = test_support.EXPECT_TRUE
+RunTest = test_support.RunTest
+
+
+def DeepEquals(d1, d2):
+ if d1 == d2:
+ return True
+ if d2.__class__ != d2.__class__:
+ return False
+ if isinstance(d1, dict):
+ if set(d1.keys()) != set(d2.keys()):
+ return False
+ for key in d1.keys():
+ if not DeepEquals(d1[key], d2[key]):
+ return False
+ return True
+ if isinstance(d1, (list, tuple)):
+ if len(d1) != len(d2):
+ return False
+ for i in range(len(d1)):
+ if not DeepEquals(d1[i], d2[i]):
+ return False
+ return True
+ return False
+
+
+test_dict = {
+ 'name': 'test',
+ 'namespace': 'testspace',
+ 'structs': [{
+ 'name': 'teststruct',
+ 'fields': [
+ {'name': 'testfield1', 'kind': 'i32'},
+ {'name': 'testfield2', 'kind': 'a:i32', 'ordinal': 42}]}],
+ 'interfaces': [{
+ 'name': 'Server',
+ 'client': None,
+ 'methods': [{
+ 'name': 'Foo',
+ 'parameters': [
+ {'name': 'foo', 'kind': 'i32'},
+ {'name': 'bar', 'kind': 'a:x:teststruct'}],
+ 'ordinal': 42}]}]
+}
+
+
+def TestRead():
+ module = data.ModuleFromData(test_dict)
+ return test_support.TestTestModule(module)
+
+
+def TestWrite():
+ module = test_support.BuildTestModule()
+ d = data.ModuleToData(module)
+ return EXPECT_TRUE(DeepEquals(test_dict, d))
+
+
+def TestWriteRead():
+ module1 = test_support.BuildTestModule()
+
+ dict1 = data.ModuleToData(module1)
+ module2 = data.ModuleFromData(dict1)
+ return EXPECT_TRUE(test_support.ModulesAreEqual(module1, module2))
+
+
+def Main(args):
+ errors = 0
+ errors += RunTest(TestWriteRead)
+ errors += RunTest(TestRead)
+ errors += RunTest(TestWrite)
+
+ return errors
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
new file mode 100644
index 00000000000..707028568c3
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
@@ -0,0 +1,90 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Code shared by the various language-specific code generators."""
+
+from functools import partial
+import os.path
+
+import module as mojom
+import pack
+
+def GetStructFromMethod(method):
+ """Converts a method's parameters into the fields of a struct."""
+ params_class = "%s_%s_Params" % (method.interface.name, method.name)
+ struct = mojom.Struct(params_class, module=method.interface.module)
+ for param in method.parameters:
+ struct.AddField(param.name, param.kind, param.ordinal)
+ struct.packed = pack.PackedStruct(struct)
+ return struct
+
+def GetResponseStructFromMethod(method):
+ """Converts a method's response_parameters into the fields of a struct."""
+ params_class = "%s_%s_ResponseParams" % (method.interface.name, method.name)
+ struct = mojom.Struct(params_class, module=method.interface.module)
+ for param in method.response_parameters:
+ struct.AddField(param.name, param.kind, param.ordinal)
+ struct.packed = pack.PackedStruct(struct)
+ return struct
+
+def GetDataHeader(exported, struct):
+ struct.packed = pack.PackedStruct(struct)
+ struct.bytes = pack.GetByteLayout(struct.packed)
+ struct.exported = exported
+ return struct
+
+def IsStringKind(kind):
+ return kind.spec == 's'
+
+def IsEnumKind(kind):
+ return isinstance(kind, mojom.Enum)
+
+def IsObjectKind(kind):
+ return isinstance(kind, (mojom.Struct, mojom.Array)) or IsStringKind(kind)
+
+def IsHandleKind(kind):
+ return kind.spec.startswith('h') or \
+ isinstance(kind, mojom.Interface) or \
+ isinstance(kind, mojom.InterfaceRequest)
+
+def IsInterfaceKind(kind):
+ return isinstance(kind, mojom.Interface)
+
+def IsInterfaceRequestKind(kind):
+ return isinstance(kind, mojom.InterfaceRequest)
+
+def IsMoveOnlyKind(kind):
+ return IsObjectKind(kind) or IsHandleKind(kind)
+
+def StudlyCapsToCamel(studly):
+ return studly[0].lower() + studly[1:]
+
+class Generator(object):
+ # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all
+ # files to stdout.
+ def __init__(self, module, output_dir=None):
+ self.module = module
+ self.output_dir = output_dir
+
+ def GetStructsFromMethods(self):
+ result = []
+ for interface in self.module.interfaces:
+ for method in interface.methods:
+ result.append(GetStructFromMethod(method))
+ if method.response_parameters != None:
+ result.append(GetResponseStructFromMethod(method))
+ return map(partial(GetDataHeader, False), result)
+
+ def GetStructs(self):
+ return map(partial(GetDataHeader, True), self.module.structs)
+
+ def Write(self, contents, filename):
+ if self.output_dir is None:
+ print contents
+ return
+ with open(os.path.join(self.output_dir, filename), "w+") as f:
+ f.write(contents)
+
+ def GenerateFiles(self, args):
+ raise NotImplementedError("Subclasses must override/implement this method")
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py
new file mode 100644
index 00000000000..345f432030f
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -0,0 +1,217 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This module's classes provide an interface to mojo modules. Modules are
+# collections of interfaces and structs to be used by mojo ipc clients and
+# servers.
+#
+# A simple interface would be created this way:
+# module = mojom.generate.module.Module('Foo')
+# interface = module.AddInterface('Bar')
+# method = interface.AddMethod('Tat', 0)
+# method.AddParameter('baz', 0, mojom.INT32)
+#
+
+class Kind(object):
+ def __init__(self, spec=None):
+ self.spec = spec
+ self.parent_kind = None
+
+# Initialize the set of primitive types. These can be accessed by clients.
+BOOL = Kind('b')
+INT8 = Kind('i8')
+INT16 = Kind('i16')
+INT32 = Kind('i32')
+INT64 = Kind('i64')
+UINT8 = Kind('u8')
+UINT16 = Kind('u16')
+UINT32 = Kind('u32')
+UINT64 = Kind('u64')
+FLOAT = Kind('f')
+DOUBLE = Kind('d')
+STRING = Kind('s')
+HANDLE = Kind('h')
+DCPIPE = Kind('h:d:c')
+DPPIPE = Kind('h:d:p')
+MSGPIPE = Kind('h:m')
+SHAREDBUFFER = Kind('h:s')
+
+
+# Collection of all Primitive types
+PRIMITIVES = (
+ BOOL,
+ INT8,
+ INT16,
+ INT32,
+ INT64,
+ UINT8,
+ UINT16,
+ UINT32,
+ UINT64,
+ FLOAT,
+ DOUBLE,
+ STRING,
+ HANDLE,
+ DCPIPE,
+ DPPIPE,
+ MSGPIPE,
+ SHAREDBUFFER
+)
+
+
+class NamedValue(object):
+ def __init__(self, module, parent_kind, name):
+ self.module = module
+ self.namespace = module.namespace
+ self.parent_kind = parent_kind
+ self.name = name
+ self.imported_from = None
+
+ def GetSpec(self):
+ return (self.namespace + '.' +
+ (self.parent_kind and (self.parent_kind.name + '.') or "") +
+ self.name)
+
+
+class EnumValue(NamedValue):
+ def __init__(self, module, enum, field):
+ NamedValue.__init__(self, module, enum.parent_kind, field.name)
+ self.enum_name = enum.name
+
+
+class Constant(object):
+ def __init__(self, name=None, kind=None, value=None):
+ self.name = name
+ self.kind = kind
+ self.value = value
+
+
+class Field(object):
+ def __init__(self, name=None, kind=None, ordinal=None, default=None):
+ self.name = name
+ self.kind = kind
+ self.ordinal = ordinal
+ self.default = default
+
+
+class Struct(Kind):
+ def __init__(self, name=None, module=None):
+ self.name = name
+ self.module = module
+ self.imported_from = None
+ if name != None:
+ spec = 'x:' + name
+ else:
+ spec = None
+ Kind.__init__(self, spec)
+ self.fields = []
+
+ def AddField(self, name, kind, ordinal=None, default=None):
+ field = Field(name, kind, ordinal, default)
+ self.fields.append(field)
+ return field
+
+
+class Array(Kind):
+ def __init__(self, kind=None):
+ self.kind = kind
+ if kind != None:
+ Kind.__init__(self, 'a:' + kind.spec)
+ else:
+ Kind.__init__(self)
+
+
+class InterfaceRequest(Kind):
+ def __init__(self, kind=None):
+ self.kind = kind
+ if kind != None:
+ Kind.__init__(self, 'r:' + kind.spec)
+ else:
+ Kind.__init__(self)
+
+
+class Parameter(object):
+ def __init__(self, name=None, kind=None, ordinal=None, default=None):
+ self.name = name
+ self.ordinal = ordinal
+ self.kind = kind
+ self.default = default
+
+
+class Method(object):
+ def __init__(self, interface, name, ordinal=None):
+ self.interface = interface
+ self.name = name
+ self.ordinal = ordinal
+ self.parameters = []
+ self.response_parameters = None
+
+ def AddParameter(self, name, kind, ordinal=None, default=None):
+ parameter = Parameter(name, kind, ordinal, default)
+ self.parameters.append(parameter)
+ return parameter
+
+ def AddResponseParameter(self, name, kind, ordinal=None, default=None):
+ if self.response_parameters == None:
+ self.response_parameters = []
+ parameter = Parameter(name, kind, ordinal, default)
+ self.response_parameters.append(parameter)
+ return parameter
+
+
+class Interface(Kind):
+ def __init__(self, name=None, client=None, module=None):
+ self.module = module
+ self.name = name
+ self.imported_from = None
+ if name != None:
+ spec = 'x:' + name
+ else:
+ spec = None
+ Kind.__init__(self, spec)
+ self.client = client
+ self.methods = []
+
+ def AddMethod(self, name, ordinal=None):
+ method = Method(self, name, ordinal=ordinal)
+ self.methods.append(method)
+ return method
+
+
+class EnumField(object):
+ def __init__(self, name=None, value=None):
+ self.name = name
+ self.value = value
+
+
+class Enum(Kind):
+ def __init__(self, name=None, module=None):
+ self.module = module
+ self.name = name
+ self.imported_from = None
+ if name != None:
+ spec = 'x:' + name
+ else:
+ spec = None
+ Kind.__init__(self, spec)
+ self.fields = []
+
+
+class Module(object):
+ def __init__(self, name=None, namespace=None):
+ self.name = name
+ self.path = name
+ self.namespace = namespace
+ self.structs = []
+ self.interfaces = []
+
+ def AddInterface(self, name):
+ interface=Interface(name, module=self);
+ self.interfaces.append(interface)
+ return interface
+
+ def AddStruct(self, name):
+ struct=Struct(name, module=self)
+ self.structs.append(struct)
+ return struct
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py
new file mode 100644
index 00000000000..a887686e1b5
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py
@@ -0,0 +1,34 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+import test_support
+
+EXPECT_EQ = test_support.EXPECT_EQ
+EXPECT_TRUE = test_support.EXPECT_TRUE
+RunTest = test_support.RunTest
+ModulesAreEqual = test_support.ModulesAreEqual
+BuildTestModule = test_support.BuildTestModule
+TestTestModule = test_support.TestTestModule
+
+
+def BuildAndTestModule():
+ return TestTestModule(BuildTestModule())
+
+
+def TestModulesEqual():
+ return EXPECT_TRUE(ModulesAreEqual(BuildTestModule(), BuildTestModule()))
+
+
+def Main(args):
+ errors = 0
+ errors += RunTest(BuildAndTestModule)
+ errors += RunTest(TestModulesEqual)
+
+ return errors
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/pack.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
new file mode 100644
index 00000000000..21d2c184180
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/pack.py
@@ -0,0 +1,150 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import module as mojom
+
+# This module provides a mechanism for determining the packed order and offsets
+# of a mojom.Struct.
+#
+# ps = pack.PackedStruct(struct)
+# ps.packed_fields will access a list of PackedField objects, each of which
+# will have an offset, a size and a bit (for mojom.BOOLs).
+
+class PackedField(object):
+ kind_to_size = {
+ mojom.BOOL: 1,
+ mojom.INT8: 1,
+ mojom.UINT8: 1,
+ mojom.INT16: 2,
+ mojom.UINT16: 2,
+ mojom.INT32: 4,
+ mojom.UINT32: 4,
+ mojom.FLOAT: 4,
+ mojom.HANDLE: 4,
+ mojom.MSGPIPE: 4,
+ mojom.SHAREDBUFFER: 4,
+ mojom.DCPIPE: 4,
+ mojom.DPPIPE: 4,
+ mojom.INT64: 8,
+ mojom.UINT64: 8,
+ mojom.DOUBLE: 8,
+ mojom.STRING: 8
+ }
+
+ @classmethod
+ def GetSizeForKind(cls, kind):
+ if isinstance(kind, mojom.Array) or isinstance(kind, mojom.Struct):
+ return 8
+ if isinstance(kind, mojom.Interface) or \
+ isinstance(kind, mojom.InterfaceRequest):
+ kind = mojom.MSGPIPE
+ if isinstance(kind, mojom.Enum):
+ # TODO(mpcomplete): what about big enums?
+ return cls.kind_to_size[mojom.INT32]
+ if not kind in cls.kind_to_size:
+ raise Exception("Invalid kind: %s" % kind.spec)
+ return cls.kind_to_size[kind]
+
+ def __init__(self, field, ordinal):
+ self.field = field
+ self.ordinal = ordinal
+ self.size = self.GetSizeForKind(field.kind)
+ self.offset = None
+ self.bit = None
+
+
+# Returns the pad necessary to reserve space for alignment of |size|.
+def GetPad(offset, size):
+ return (size - (offset % size)) % size
+
+
+# Returns a 2-tuple of the field offset and bit (for BOOLs)
+def GetFieldOffset(field, last_field):
+ if field.field.kind == mojom.BOOL and \
+ last_field.field.kind == mojom.BOOL and \
+ last_field.bit < 7:
+ return (last_field.offset, last_field.bit + 1)
+
+ offset = last_field.offset + last_field.size
+ pad = GetPad(offset, field.size)
+ return (offset + pad, 0)
+
+
+class PackedStruct(object):
+ def __init__(self, struct):
+ self.struct = struct
+ self.packed_fields = []
+
+ # No fields.
+ if (len(struct.fields) == 0):
+ return
+
+ # Start by sorting by ordinal.
+ src_fields = []
+ ordinal = 0
+ for field in struct.fields:
+ if field.ordinal is not None:
+ ordinal = field.ordinal
+ src_fields.append(PackedField(field, ordinal))
+ ordinal += 1
+ src_fields.sort(key=lambda field: field.ordinal)
+
+ src_field = src_fields[0]
+ src_field.offset = 0
+ src_field.bit = 0
+ # dst_fields will contain each of the fields, in increasing offset order.
+ dst_fields = self.packed_fields
+ dst_fields.append(src_field)
+
+ # Then find first slot that each field will fit.
+ for src_field in src_fields[1:]:
+ last_field = dst_fields[0]
+ for i in xrange(1, len(dst_fields)):
+ next_field = dst_fields[i]
+ offset, bit = GetFieldOffset(src_field, last_field)
+ if offset + src_field.size <= next_field.offset:
+ # Found hole.
+ src_field.offset = offset
+ src_field.bit = bit
+ dst_fields.insert(i, src_field)
+ break
+ last_field = next_field
+ if src_field.offset is None:
+ # Add to end
+ src_field.offset, src_field.bit = GetFieldOffset(src_field, last_field)
+ dst_fields.append(src_field)
+
+ def GetTotalSize(self):
+ if not self.packed_fields:
+ return 0
+ last_field = self.packed_fields[-1]
+ offset = last_field.offset + last_field.size
+ pad = GetPad(offset, 8)
+ return offset + pad
+
+
+class ByteInfo(object):
+ def __init__(self):
+ self.is_padding = False
+ self.packed_fields = []
+
+
+def GetByteLayout(packed_struct):
+ bytes = [ByteInfo() for i in xrange(packed_struct.GetTotalSize())]
+
+ limit_of_previous_field = 0
+ for packed_field in packed_struct.packed_fields:
+ for i in xrange(limit_of_previous_field, packed_field.offset):
+ bytes[i].is_padding = True
+ bytes[packed_field.offset].packed_fields.append(packed_field)
+ limit_of_previous_field = packed_field.offset + packed_field.size
+
+ for i in xrange(limit_of_previous_field, len(bytes)):
+ bytes[i].is_padding = True
+
+ for byte in bytes:
+ # A given byte cannot both be padding and have a fields packed into it.
+ assert not (byte.is_padding and byte.packed_fields)
+
+ return bytes
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py
new file mode 100644
index 00000000000..4e61004e5f4
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py
@@ -0,0 +1,176 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+import module as mojom
+import pack
+import test_support
+
+
+EXPECT_EQ = test_support.EXPECT_EQ
+EXPECT_TRUE = test_support.EXPECT_TRUE
+RunTest = test_support.RunTest
+
+
+def TestOrdinalOrder():
+ errors = 0
+ struct = mojom.Struct('test')
+ struct.AddField('testfield1', mojom.INT32, 2)
+ struct.AddField('testfield2', mojom.INT32, 1)
+ ps = pack.PackedStruct(struct)
+
+ errors += EXPECT_EQ(2, len(ps.packed_fields))
+ errors += EXPECT_EQ('testfield2', ps.packed_fields[0].field.name)
+ errors += EXPECT_EQ('testfield1', ps.packed_fields[1].field.name)
+
+ return errors
+
+def TestZeroFields():
+ errors = 0
+ struct = mojom.Struct('test')
+ ps = pack.PackedStruct(struct)
+ errors += EXPECT_EQ(0, len(ps.packed_fields))
+ return errors
+
+
+def TestOneField():
+ errors = 0
+ struct = mojom.Struct('test')
+ struct.AddField('testfield1', mojom.INT8)
+ ps = pack.PackedStruct(struct)
+ errors += EXPECT_EQ(1, len(ps.packed_fields))
+ return errors
+
+# Pass three tuples.
+# |kinds| is a sequence of mojom.Kinds that specify the fields that are to
+# be created.
+# |fields| is the expected order of the resulting fields, with the integer
+# "1" first.
+# |offsets| is the expected order of offsets, with the integer "0" first.
+def TestSequence(kinds, fields, offsets):
+ errors = 0
+ struct = mojom.Struct('test')
+ index = 1
+ for kind in kinds:
+ struct.AddField("%d" % index, kind)
+ index += 1
+ ps = pack.PackedStruct(struct)
+ num_fields = len(ps.packed_fields)
+ errors += EXPECT_EQ(len(kinds), num_fields)
+ for i in xrange(num_fields):
+ EXPECT_EQ("%d" % fields[i], ps.packed_fields[i].field.name)
+ EXPECT_EQ(offsets[i], ps.packed_fields[i].offset)
+
+ return errors
+
+
+def TestPaddingPackedInOrder():
+ return TestSequence(
+ (mojom.INT8, mojom.UINT8, mojom.INT32),
+ (1, 2, 3),
+ (0, 1, 4))
+
+
+def TestPaddingPackedOutOfOrder():
+ return TestSequence(
+ (mojom.INT8, mojom.INT32, mojom.UINT8),
+ (1, 3, 2),
+ (0, 1, 4))
+
+
+def TestPaddingPackedOverflow():
+ kinds = (mojom.INT8, mojom.INT32, mojom.INT16, mojom.INT8, mojom.INT8)
+ # 2 bytes should be packed together first, followed by short, then by int.
+ fields = (1, 4, 3, 2, 5)
+ offsets = (0, 1, 2, 4, 8)
+ return TestSequence(kinds, fields, offsets)
+
+
+def TestAllTypes():
+ struct = mojom.Struct('test')
+ array = mojom.Array()
+ return TestSequence(
+ (mojom.BOOL, mojom.INT8, mojom.STRING, mojom.UINT8,
+ mojom.INT16, mojom.DOUBLE, mojom.UINT16,
+ mojom.INT32, mojom.UINT32, mojom.INT64,
+ mojom.FLOAT, mojom.STRING, mojom.HANDLE,
+ mojom.UINT64, mojom.Struct('test'), mojom.Array()),
+ (1, 2, 4, 5, 7, 3, 6, 8, 9, 10, 11, 13, 12, 14, 15, 16, 17),
+ (0, 1, 2, 4, 6, 8, 16, 24, 28, 32, 40, 44, 48, 56, 64, 72, 80))
+
+
+def TestPaddingPackedOutOfOrderByOrdinal():
+ errors = 0
+ struct = mojom.Struct('test')
+ struct.AddField('testfield1', mojom.INT8)
+ struct.AddField('testfield3', mojom.UINT8, 3)
+ struct.AddField('testfield2', mojom.INT32, 2)
+ ps = pack.PackedStruct(struct)
+ errors += EXPECT_EQ(3, len(ps.packed_fields))
+
+ # Second byte should be packed in behind first, altering order.
+ errors += EXPECT_EQ('testfield1', ps.packed_fields[0].field.name)
+ errors += EXPECT_EQ('testfield3', ps.packed_fields[1].field.name)
+ errors += EXPECT_EQ('testfield2', ps.packed_fields[2].field.name)
+
+ # Second byte should be packed with first.
+ errors += EXPECT_EQ(0, ps.packed_fields[0].offset)
+ errors += EXPECT_EQ(1, ps.packed_fields[1].offset)
+ errors += EXPECT_EQ(4, ps.packed_fields[2].offset)
+
+ return errors
+
+
+def TestBools():
+ errors = 0
+ struct = mojom.Struct('test')
+ struct.AddField('bit0', mojom.BOOL)
+ struct.AddField('bit1', mojom.BOOL)
+ struct.AddField('int', mojom.INT32)
+ struct.AddField('bit2', mojom.BOOL)
+ struct.AddField('bit3', mojom.BOOL)
+ struct.AddField('bit4', mojom.BOOL)
+ struct.AddField('bit5', mojom.BOOL)
+ struct.AddField('bit6', mojom.BOOL)
+ struct.AddField('bit7', mojom.BOOL)
+ struct.AddField('bit8', mojom.BOOL)
+ ps = pack.PackedStruct(struct)
+ errors += EXPECT_EQ(10, len(ps.packed_fields))
+
+ # First 8 bits packed together.
+ for i in xrange(8):
+ pf = ps.packed_fields[i]
+ errors += EXPECT_EQ(0, pf.offset)
+ errors += EXPECT_EQ("bit%d" % i, pf.field.name)
+ errors += EXPECT_EQ(i, pf.bit)
+
+ # Ninth bit goes into second byte.
+ errors += EXPECT_EQ("bit8", ps.packed_fields[8].field.name)
+ errors += EXPECT_EQ(1, ps.packed_fields[8].offset)
+ errors += EXPECT_EQ(0, ps.packed_fields[8].bit)
+
+ # int comes last.
+ errors += EXPECT_EQ("int", ps.packed_fields[9].field.name)
+ errors += EXPECT_EQ(4, ps.packed_fields[9].offset)
+
+ return errors
+
+
+def Main(args):
+ errors = 0
+ errors += RunTest(TestZeroFields)
+ errors += RunTest(TestOneField)
+ errors += RunTest(TestPaddingPackedInOrder)
+ errors += RunTest(TestPaddingPackedOutOfOrder)
+ errors += RunTest(TestPaddingPackedOverflow)
+ errors += RunTest(TestAllTypes)
+ errors += RunTest(TestPaddingPackedOutOfOrderByOrdinal)
+ errors += RunTest(TestBools)
+
+ return errors
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/run_tests.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/run_tests.py
new file mode 100755
index 00000000000..41f11a2b71e
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/run_tests.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Test runner for Mojom """
+
+import subprocess
+import sys
+
+def TestMojom(testname, args):
+ print '\nRunning unit tests for %s.' % testname
+ try:
+ args = [sys.executable, testname] + args
+ subprocess.check_call(args, stdout=sys.stdout)
+ print 'Succeeded'
+ return 0
+ except subprocess.CalledProcessError as err:
+ print 'Failed with %s.' % str(err)
+ return 1
+
+
+def main(args):
+ errors = 0
+ errors += TestMojom('data_tests.py', ['--test'])
+ errors += TestMojom('module_tests.py', ['--test'])
+ errors += TestMojom('pack_tests.py', ['--test'])
+
+ if errors:
+ print '\nFailed tests.'
+ return min(errors, 127) # Make sure the return value doesn't "wrap".
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py
new file mode 100644
index 00000000000..86ea0eac0b4
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py
@@ -0,0 +1,54 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Based on:
+# http://src.chromium.org/viewvc/blink/trunk/Source/build/scripts/template_expander.py
+
+import imp
+import inspect
+import os.path
+import sys
+
+# Disable lint check for finding modules:
+# pylint: disable=F0401
+
+def _GetDirAbove(dirname):
+ """Returns the directory "above" this file containing |dirname| (which must
+ also be "above" this file)."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ assert tail
+ if tail == dirname:
+ return path
+
+try:
+ imp.find_module("jinja2")
+except ImportError:
+ sys.path.append(os.path.join(_GetDirAbove("mojo"), "third_party"))
+import jinja2
+
+
+def ApplyTemplate(base_dir, path_to_template, params, filters=None, **kwargs):
+ template_directory, template_name = os.path.split(path_to_template)
+ path_to_templates = os.path.join(base_dir, template_directory)
+ loader = jinja2.FileSystemLoader([path_to_templates])
+ jinja_env = jinja2.Environment(loader=loader, keep_trailing_newline=True,
+ **kwargs)
+ if filters:
+ jinja_env.filters.update(filters)
+ template = jinja_env.get_template(template_name)
+ return template.render(params)
+
+
+def UseJinja(path_to_template, **kwargs):
+ # Get the directory of our caller's file.
+ base_dir = os.path.dirname(inspect.getfile(sys._getframe(1)))
+ def RealDecorator(generator):
+ def GeneratorInternal(*args, **kwargs2):
+ parameters = generator(*args, **kwargs2)
+ return ApplyTemplate(base_dir, path_to_template, parameters, **kwargs)
+ GeneratorInternal.func_name = generator.func_name
+ return GeneratorInternal
+ return RealDecorator
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py
new file mode 100644
index 00000000000..eb394619d2b
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/test_support.py
@@ -0,0 +1,193 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+import traceback
+
+import module as mojom
+
+# Support for writing mojom test cases.
+# RunTest(fn) will execute fn, catching any exceptions. fn should return
+# the number of errors that are encountered.
+#
+# EXPECT_EQ(a, b) and EXPECT_TRUE(b) will print error information if the
+# expectations are not true and return a non zero value. This allows test cases
+# to be written like this
+#
+# def Foo():
+# errors = 0
+# errors += EXPECT_EQ('test', test())
+# ...
+# return errors
+#
+# RunTest(foo)
+
+def FieldsAreEqual(field1, field2):
+ if field1 == field2:
+ return True
+ return field1.name == field2.name and \
+ KindsAreEqual(field1.kind, field2.kind) and \
+ field1.ordinal == field2.ordinal and \
+ field1.default == field2.default
+
+
+def KindsAreEqual(kind1, kind2):
+ if kind1 == kind2:
+ return True
+ if kind1.__class__ != kind2.__class__ or kind1.spec != kind2.spec:
+ return False
+ if kind1.__class__ == mojom.Kind:
+ return kind1.spec == kind2.spec
+ if kind1.__class__ == mojom.Struct:
+ if kind1.name != kind2.name or \
+ kind1.spec != kind2.spec or \
+ len(kind1.fields) != len(kind2.fields):
+ return False
+ for i in range(len(kind1.fields)):
+ if not FieldsAreEqual(kind1.fields[i], kind2.fields[i]):
+ return False
+ return True
+ if kind1.__class__ == mojom.Array:
+ return KindsAreEqual(kind1.kind, kind2.kind)
+ print 'Unknown Kind class: ', kind1.__class__.__name__
+ return False
+
+
+def ParametersAreEqual(parameter1, parameter2):
+ if parameter1 == parameter2:
+ return True
+ return parameter1.name == parameter2.name and \
+ parameter1.ordinal == parameter2.ordinal and \
+ parameter1.default == parameter2.default and \
+ KindsAreEqual(parameter1.kind, parameter2.kind)
+
+
+def MethodsAreEqual(method1, method2):
+ if method1 == method2:
+ return True
+ if method1.name != method2.name or \
+ method1.ordinal != method2.ordinal or \
+ len(method1.parameters) != len(method2.parameters):
+ return False
+ for i in range(len(method1.parameters)):
+ if not ParametersAreEqual(method1.parameters[i], method2.parameters[i]):
+ return False
+ return True
+
+
+def InterfacesAreEqual(interface1, interface2):
+ if interface1 == interface2:
+ return True
+ if interface1.name != interface2.name or \
+ len(interface1.methods) != len(interface2.methods):
+ return False
+ for i in range(len(interface1.methods)):
+ if not MethodsAreEqual(interface1.methods[i], interface2.methods[i]):
+ return False
+ return True
+
+
+def ModulesAreEqual(module1, module2):
+ if module1 == module2:
+ return True
+ if module1.name != module2.name or \
+ module1.namespace != module2.namespace or \
+ len(module1.structs) != len(module2.structs) or \
+ len(module1.interfaces) != len(module2.interfaces):
+ return False
+ for i in range(len(module1.structs)):
+ if not KindsAreEqual(module1.structs[i], module2.structs[i]):
+ return False
+ for i in range(len(module1.interfaces)):
+ if not InterfacesAreEqual(module1.interfaces[i], module2.interfaces[i]):
+ return False
+ return True
+
+
+# Builds and returns a Module suitable for testing/
+def BuildTestModule():
+ module = mojom.Module('test', 'testspace')
+ struct = module.AddStruct('teststruct')
+ struct.AddField('testfield1', mojom.INT32)
+ struct.AddField('testfield2', mojom.Array(mojom.INT32), 42)
+
+ interface = module.AddInterface('Server')
+ method = interface.AddMethod('Foo', 42)
+ method.AddParameter('foo', mojom.INT32)
+ method.AddParameter('bar', mojom.Array(struct))
+
+ return module
+
+
+# Tests if |module| is as built by BuildTestModule(). Returns the number of
+# errors
+def TestTestModule(module):
+ errors = 0
+
+ errors += EXPECT_EQ('test', module.name)
+ errors += EXPECT_EQ('testspace', module.namespace)
+ errors += EXPECT_EQ(1, len(module.structs))
+ errors += EXPECT_EQ('teststruct', module.structs[0].name)
+ errors += EXPECT_EQ(2, len(module.structs[0].fields))
+ errors += EXPECT_EQ('testfield1', module.structs[0].fields[0].name)
+ errors += EXPECT_EQ(mojom.INT32, module.structs[0].fields[0].kind)
+ errors += EXPECT_EQ('testfield2', module.structs[0].fields[1].name)
+ errors += EXPECT_EQ(mojom.Array, module.structs[0].fields[1].kind.__class__)
+ errors += EXPECT_EQ(mojom.INT32, module.structs[0].fields[1].kind.kind)
+
+ errors += EXPECT_EQ(1, len(module.interfaces))
+ errors += EXPECT_EQ('Server', module.interfaces[0].name)
+ errors += EXPECT_EQ(1, len(module.interfaces[0].methods))
+ errors += EXPECT_EQ('Foo', module.interfaces[0].methods[0].name)
+ errors += EXPECT_EQ(2, len(module.interfaces[0].methods[0].parameters))
+ errors += EXPECT_EQ('foo', module.interfaces[0].methods[0].parameters[0].name)
+ errors += EXPECT_EQ(mojom.INT32,
+ module.interfaces[0].methods[0].parameters[0].kind)
+ errors += EXPECT_EQ('bar', module.interfaces[0].methods[0].parameters[1].name)
+ errors += EXPECT_EQ(
+ mojom.Array,
+ module.interfaces[0].methods[0].parameters[1].kind.__class__)
+ errors += EXPECT_EQ(
+ module.structs[0],
+ module.interfaces[0].methods[0].parameters[1].kind.kind)
+ return errors
+
+
+def PrintFailure(string):
+ stack = traceback.extract_stack()
+ frame = stack[len(stack)-3]
+ sys.stderr.write("ERROR at %s:%d, %s\n" % (frame[0], frame[1], string))
+ print "Traceback:"
+ for line in traceback.format_list(stack[:len(stack)-2]):
+ sys.stderr.write(line)
+
+
+def EXPECT_EQ(a, b):
+ if a != b:
+ PrintFailure("%s != %s" % (a, b))
+ return 1
+ return 0
+
+
+def EXPECT_TRUE(a):
+ if not a:
+ PrintFailure('Expecting True')
+ return 1
+ return 0
+
+
+def RunTest(fn):
+ sys.stdout.write('Running %s...' % fn.__name__)
+ try:
+ errors = fn()
+ except:
+ traceback.print_exc(sys.stderr)
+ errors = 1
+ if errors == 0:
+ sys.stdout.write('OK\n')
+ elif errors == 1:
+ sys.stdout.write('1 ERROR\n')
+ else:
+ sys.stdout.write('%d ERRORS\n' % errors)
+ return errors
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/__init__.py
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/ast.py b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/ast.py
new file mode 100644
index 00000000000..bd398c18ecb
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/ast.py
@@ -0,0 +1,25 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Node objects for the AST for a Mojo IDL file."""
+
+# Note: For convenience of testing, you probably want to define __eq__() methods
+# for all node types; it's okay to be slightly lax (e.g., not compare filename
+# and lineno).
+
+
+class BaseNode(object):
+ def __init__(self, filename=None, lineno=None):
+ self.filename = filename
+ self.lineno = lineno
+
+
+class Ordinal(BaseNode):
+ """Represents an ordinal value labeling, e.g., a struct field."""
+ def __init__(self, value, **kwargs):
+ BaseNode.__init__(self, **kwargs)
+ self.value = value
+
+ def __eq__(self, other):
+ return self.value == other.value
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py
new file mode 100644
index 00000000000..34419acd53c
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/lexer.py
@@ -0,0 +1,277 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import imp
+import os.path
+import sys
+
+# Disable lint check for finding modules:
+# pylint: disable=F0401
+
+def _GetDirAbove(dirname):
+ """Returns the directory "above" this file containing |dirname| (which must
+ also be "above" this file)."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ assert tail
+ if tail == dirname:
+ return path
+
+try:
+ imp.find_module("ply")
+except ImportError:
+ sys.path.append(os.path.join(_GetDirAbove("mojo"), "third_party"))
+from ply.lex import TOKEN
+
+from ..error import Error
+
+
+# Disable lint check for exceptions deriving from Exception:
+# pylint: disable=W0710
+class LexError(Error):
+ """Class for errors from the lexer."""
+
+ def __init__(self, filename, message, lineno):
+ Error.__init__(self, filename, message, lineno=lineno)
+
+
+# We have methods which look like they could be functions:
+# pylint: disable=R0201
+class Lexer(object):
+
+ def __init__(self, filename):
+ self.filename = filename
+
+ ######################-- PRIVATE --######################
+
+ ##
+ ## Internal auxiliary methods
+ ##
+ def _error(self, msg, token):
+ raise LexError(self.filename, msg, token.lineno)
+
+ ##
+ ## Reserved keywords
+ ##
+ keywords = (
+ 'HANDLE',
+
+ 'IMPORT',
+ 'MODULE',
+ 'STRUCT',
+ 'INTERFACE',
+ 'ENUM',
+ 'CONST',
+ 'TRUE',
+ 'FALSE',
+ 'DEFAULT',
+ )
+
+ keyword_map = {}
+ for keyword in keywords:
+ keyword_map[keyword.lower()] = keyword
+
+ ##
+ ## All the tokens recognized by the lexer
+ ##
+ tokens = keywords + (
+ # Identifiers
+ 'NAME',
+
+ # Constants
+ 'ORDINAL',
+ 'INT_CONST_DEC', 'INT_CONST_HEX',
+ 'FLOAT_CONST',
+ 'CHAR_CONST',
+
+ # String literals
+ 'STRING_LITERAL',
+
+ # Operators
+ 'MINUS',
+ 'PLUS',
+ 'AMP',
+
+ # Assignment
+ 'EQUALS',
+
+ # Request / response
+ 'RESPONSE',
+
+ # Delimiters
+ 'LPAREN', 'RPAREN', # ( )
+ 'LBRACKET', 'RBRACKET', # [ ]
+ 'LBRACE', 'RBRACE', # { }
+ 'LANGLE', 'RANGLE', # < >
+ 'SEMI', # ;
+ 'COMMA', 'DOT' # , .
+ )
+
+ ##
+ ## Regexes for use in tokens
+ ##
+
+ # valid C identifiers (K&R2: A.2.3)
+ identifier = r'[a-zA-Z_][0-9a-zA-Z_]*'
+
+ hex_prefix = '0[xX]'
+ hex_digits = '[0-9a-fA-F]+'
+
+ # integer constants (K&R2: A.2.5.1)
+ decimal_constant = '0|([1-9][0-9]*)'
+ hex_constant = hex_prefix+hex_digits
+ # Don't allow octal constants (even invalid octal).
+ octal_constant_disallowed = '0[0-9]+'
+
+ # character constants (K&R2: A.2.5.2)
+ # Note: a-zA-Z and '.-~^_!=&;,' are allowed as escape chars to support #line
+ # directives with Windows paths as filenames (..\..\dir\file)
+ # For the same reason, decimal_escape allows all digit sequences. We want to
+ # parse all correct code, even if it means to sometimes parse incorrect
+ # code.
+ #
+ simple_escape = r"""([a-zA-Z._~!=&\^\-\\?'"])"""
+ decimal_escape = r"""(\d+)"""
+ hex_escape = r"""(x[0-9a-fA-F]+)"""
+ bad_escape = r"""([\\][^a-zA-Z._~^!=&\^\-\\?'"x0-7])"""
+
+ escape_sequence = \
+ r"""(\\("""+simple_escape+'|'+decimal_escape+'|'+hex_escape+'))'
+ cconst_char = r"""([^'\\\n]|"""+escape_sequence+')'
+ char_const = "'"+cconst_char+"'"
+ unmatched_quote = "('"+cconst_char+"*\\n)|('"+cconst_char+"*$)"
+ bad_char_const = \
+ r"""('"""+cconst_char+"""[^'\n]+')|('')|('"""+ \
+ bad_escape+r"""[^'\n]*')"""
+
+ # string literals (K&R2: A.2.6)
+ string_char = r"""([^"\\\n]|"""+escape_sequence+')'
+ string_literal = '"'+string_char+'*"'
+ bad_string_literal = '"'+string_char+'*'+bad_escape+string_char+'*"'
+
+ # floating constants (K&R2: A.2.5.3)
+ exponent_part = r"""([eE][-+]?[0-9]+)"""
+ fractional_constant = r"""([0-9]*\.[0-9]+)|([0-9]+\.)"""
+ floating_constant = \
+ '(((('+fractional_constant+')'+ \
+ exponent_part+'?)|([0-9]+'+exponent_part+')))'
+
+ # Ordinals
+ ordinal = r'@[0-9]+'
+ missing_ordinal_value = r'@'
+ # Don't allow ordinal values in octal (even invalid octal, like 09) or
+ # hexadecimal.
+ octal_or_hex_ordinal_disallowed = r'@((0[0-9]+)|('+hex_prefix+hex_digits+'))'
+
+ ##
+ ## Rules for the normal state
+ ##
+ t_ignore = ' \t\r'
+
+ # Newlines
+ def t_NEWLINE(self, t):
+ r'\n+'
+ t.lexer.lineno += len(t.value)
+
+ # Operators
+ t_MINUS = r'-'
+ t_PLUS = r'\+'
+ t_AMP = r'&'
+
+ # =
+ t_EQUALS = r'='
+
+ # =>
+ t_RESPONSE = r'=>'
+
+ # Delimiters
+ t_LPAREN = r'\('
+ t_RPAREN = r'\)'
+ t_LBRACKET = r'\['
+ t_RBRACKET = r'\]'
+ t_LBRACE = r'\{'
+ t_RBRACE = r'\}'
+ t_LANGLE = r'<'
+ t_RANGLE = r'>'
+ t_COMMA = r','
+ t_DOT = r'\.'
+ t_SEMI = r';'
+
+ t_STRING_LITERAL = string_literal
+
+ # The following floating and integer constants are defined as
+ # functions to impose a strict order (otherwise, decimal
+ # is placed before the others because its regex is longer,
+ # and this is bad)
+ #
+ @TOKEN(floating_constant)
+ def t_FLOAT_CONST(self, t):
+ return t
+
+ @TOKEN(hex_constant)
+ def t_INT_CONST_HEX(self, t):
+ return t
+
+ @TOKEN(octal_constant_disallowed)
+ def t_OCTAL_CONSTANT_DISALLOWED(self, t):
+ msg = "Octal values not allowed"
+ self._error(msg, t)
+
+ @TOKEN(decimal_constant)
+ def t_INT_CONST_DEC(self, t):
+ return t
+
+ # Must come before bad_char_const, to prevent it from
+ # catching valid char constants as invalid
+ #
+ @TOKEN(char_const)
+ def t_CHAR_CONST(self, t):
+ return t
+
+ @TOKEN(unmatched_quote)
+ def t_UNMATCHED_QUOTE(self, t):
+ msg = "Unmatched '"
+ self._error(msg, t)
+
+ @TOKEN(bad_char_const)
+ def t_BAD_CHAR_CONST(self, t):
+ msg = "Invalid char constant %s" % t.value
+ self._error(msg, t)
+
+ # unmatched string literals are caught by the preprocessor
+
+ @TOKEN(bad_string_literal)
+ def t_BAD_STRING_LITERAL(self, t):
+ msg = "String contains invalid escape code"
+ self._error(msg, t)
+
+ # Handle ordinal-related tokens in the right order:
+ @TOKEN(octal_or_hex_ordinal_disallowed)
+ def t_OCTAL_OR_HEX_ORDINAL_DISALLOWED(self, t):
+ msg = "Octal and hexadecimal ordinal values not allowed"
+ self._error(msg, t)
+
+ @TOKEN(ordinal)
+ def t_ORDINAL(self, t):
+ return t
+
+ @TOKEN(missing_ordinal_value)
+ def t_BAD_ORDINAL(self, t):
+ msg = "Missing ordinal value"
+ self._error(msg, t)
+
+ @TOKEN(identifier)
+ def t_NAME(self, t):
+ t.type = self.keyword_map.get(t.value, "NAME")
+ return t
+
+ # Ignore C and C++ style comments
+ def t_COMMENT(self, t):
+ r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)'
+ t.lexer.lineno += t.value.count("\n")
+
+ def t_error(self, t):
+ msg = "Illegal character %s" % repr(t.value[0])
+ self._error(msg, t)
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
new file mode 100644
index 00000000000..da441e3806c
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
@@ -0,0 +1,323 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generates a syntax tree from a Mojo IDL file."""
+
+import imp
+import os.path
+import sys
+
+# Disable lint check for finding modules:
+# pylint: disable=F0401
+
+def _GetDirAbove(dirname):
+ """Returns the directory "above" this file containing |dirname| (which must
+ also be "above" this file)."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ assert tail
+ if tail == dirname:
+ return path
+
+try:
+ imp.find_module("ply")
+except ImportError:
+ sys.path.append(os.path.join(_GetDirAbove("mojo"), "third_party"))
+from ply import lex
+from ply import yacc
+
+from ..error import Error
+import ast
+from lexer import Lexer
+
+
+_MAX_ORDINAL_VALUE = 0xffffffff
+
+
+def _ListFromConcat(*items):
+ """Generate list by concatenating inputs (note: only concatenates lists, not
+ tuples or other iterables)."""
+ itemsout = []
+ for item in items:
+ if item is None:
+ continue
+ if type(item) is not type([]):
+ itemsout.append(item)
+ else:
+ itemsout.extend(item)
+ return itemsout
+
+
+# Disable lint check for exceptions deriving from Exception:
+# pylint: disable=W0710
+class ParseError(Error):
+ """Class for errors from the parser."""
+
+ def __init__(self, filename, message, lineno=None, snippet=None):
+ Error.__init__(self, filename, message, lineno=lineno,
+ addenda=([snippet] if snippet else None))
+
+
+# We have methods which look like they could be functions:
+# pylint: disable=R0201
+class Parser(object):
+
+ def __init__(self, lexer, source, filename):
+ self.tokens = lexer.tokens
+ self.source = source
+ self.filename = filename
+
+ def p_root(self, p):
+ """root : import root
+ | module
+ | definitions"""
+ if len(p) > 2:
+ p[0] = _ListFromConcat(p[1], p[2])
+ else:
+ # Generator expects a module. If one wasn't specified insert one with an
+ # empty name.
+ if p[1][0] != 'MODULE':
+ p[0] = [('MODULE', '', None, p[1])]
+ else:
+ p[0] = [p[1]]
+
+ def p_import(self, p):
+ """import : IMPORT STRING_LITERAL"""
+ # 'eval' the literal to strip the quotes.
+ p[0] = ('IMPORT', eval(p[2]))
+
+ def p_module(self, p):
+ """module : attribute_section MODULE identifier LBRACE definitions RBRACE"""
+ p[0] = ('MODULE', p[3], p[1], p[5])
+
+ def p_definitions(self, p):
+ """definitions : definition definitions
+ | """
+ if len(p) > 1:
+ p[0] = _ListFromConcat(p[1], p[2])
+
+ def p_definition(self, p):
+ """definition : struct
+ | interface
+ | enum
+ | const"""
+ p[0] = p[1]
+
+ def p_attribute_section(self, p):
+ """attribute_section : LBRACKET attributes RBRACKET
+ | """
+ if len(p) > 3:
+ p[0] = p[2]
+
+ def p_attributes(self, p):
+ """attributes : attribute
+ | attribute COMMA attributes
+ | """
+ if len(p) == 2:
+ p[0] = _ListFromConcat(p[1])
+ elif len(p) > 3:
+ p[0] = _ListFromConcat(p[1], p[3])
+
+ def p_attribute(self, p):
+ """attribute : NAME EQUALS evaled_literal
+ | NAME EQUALS NAME"""
+ p[0] = ('ATTRIBUTE', p[1], p[3])
+
+ def p_evaled_literal(self, p):
+ """evaled_literal : literal"""
+ # 'eval' the literal to strip the quotes.
+ p[0] = eval(p[1])
+
+ def p_struct(self, p):
+ """struct : attribute_section STRUCT NAME LBRACE struct_body RBRACE SEMI"""
+ p[0] = ('STRUCT', p[3], p[1], p[5])
+
+ def p_struct_body(self, p):
+ """struct_body : field struct_body
+ | enum struct_body
+ | const struct_body
+ | """
+ if len(p) > 1:
+ p[0] = _ListFromConcat(p[1], p[2])
+
+ def p_field(self, p):
+ """field : typename NAME ordinal default SEMI"""
+ p[0] = ('FIELD', p[1], p[2], p[3], p[4])
+
+ def p_default(self, p):
+ """default : EQUALS constant
+ | """
+ if len(p) > 2:
+ p[0] = p[2]
+
+ def p_interface(self, p):
+ """interface : attribute_section INTERFACE NAME LBRACE interface_body \
+ RBRACE SEMI"""
+ p[0] = ('INTERFACE', p[3], p[1], p[5])
+
+ def p_interface_body(self, p):
+ """interface_body : method interface_body
+ | enum interface_body
+ | const interface_body
+ | """
+ if len(p) > 1:
+ p[0] = _ListFromConcat(p[1], p[2])
+
+ def p_response(self, p):
+ """response : RESPONSE LPAREN parameters RPAREN
+ | """
+ if len(p) > 3:
+ p[0] = p[3]
+
+ def p_method(self, p):
+ """method : NAME ordinal LPAREN parameters RPAREN response SEMI"""
+ p[0] = ('METHOD', p[1], p[4], p[2], p[6])
+
+ def p_parameters(self, p):
+ """parameters : parameter
+ | parameter COMMA parameters
+ | """
+ if len(p) == 1:
+ p[0] = []
+ elif len(p) == 2:
+ p[0] = _ListFromConcat(p[1])
+ elif len(p) > 3:
+ p[0] = _ListFromConcat(p[1], p[3])
+
+ def p_parameter(self, p):
+ """parameter : typename NAME ordinal"""
+ p[0] = ('PARAM', p[1], p[2], p[3])
+
+ def p_typename(self, p):
+ """typename : basictypename
+ | array
+ | interfacerequest"""
+ p[0] = p[1]
+
+ def p_basictypename(self, p):
+ """basictypename : identifier
+ | handletype"""
+ p[0] = p[1]
+
+ def p_handletype(self, p):
+ """handletype : HANDLE
+ | HANDLE LANGLE NAME RANGLE"""
+ if len(p) == 2:
+ p[0] = p[1]
+ else:
+ if p[3] not in ('data_pipe_consumer',
+ 'data_pipe_producer',
+ 'message_pipe',
+ 'shared_buffer'):
+ # Note: We don't enable tracking of line numbers for everything, so we
+ # can't use |p.lineno(3)|.
+ raise ParseError(self.filename, "Invalid handle type %r:" % p[3],
+ lineno=p.lineno(1),
+ snippet=self._GetSnippet(p.lineno(1)))
+ p[0] = "handle<" + p[3] + ">"
+
+ def p_array(self, p):
+ """array : typename LBRACKET RBRACKET"""
+ p[0] = p[1] + "[]"
+
+ def p_interfacerequest(self, p):
+ """interfacerequest : identifier AMP"""
+ p[0] = p[1] + "&"
+
+ def p_ordinal(self, p):
+ """ordinal : ORDINAL
+ | """
+ if len(p) > 1:
+ value = int(p[1][1:])
+ if value > _MAX_ORDINAL_VALUE:
+ raise ParseError(self.filename, "Ordinal value %d too large:" % value,
+ lineno=p.lineno(1),
+ snippet=self._GetSnippet(p.lineno(1)))
+ p[0] = ast.Ordinal(value, filename=self.filename, lineno=p.lineno(1))
+ else:
+ p[0] = ast.Ordinal(None)
+
+ def p_enum(self, p):
+ """enum : ENUM NAME LBRACE enum_fields RBRACE SEMI"""
+ p[0] = ('ENUM', p[2], p[4])
+
+ def p_enum_fields(self, p):
+ """enum_fields : enum_field
+ | enum_field COMMA enum_fields
+ | """
+ if len(p) == 2:
+ p[0] = _ListFromConcat(p[1])
+ elif len(p) > 3:
+ p[0] = _ListFromConcat(p[1], p[3])
+
+ def p_enum_field(self, p):
+ """enum_field : NAME
+ | NAME EQUALS constant"""
+ if len(p) == 2:
+ p[0] = ('ENUM_FIELD', p[1], None)
+ else:
+ p[0] = ('ENUM_FIELD', p[1], p[3])
+
+ def p_const(self, p):
+ """const : CONST typename NAME EQUALS constant SEMI"""
+ p[0] = ('CONST', p[2], p[3], p[5])
+
+ def p_constant(self, p):
+ """constant : literal
+ | identifier_wrapped"""
+ p[0] = p[1]
+
+ def p_identifier_wrapped(self, p):
+ """identifier_wrapped : identifier"""
+ p[0] = ('IDENTIFIER', p[1])
+
+ def p_identifier(self, p):
+ """identifier : NAME
+ | NAME DOT identifier"""
+ p[0] = ''.join(p[1:])
+
+ def p_literal(self, p):
+ """literal : number
+ | CHAR_CONST
+ | TRUE
+ | FALSE
+ | DEFAULT
+ | STRING_LITERAL"""
+ p[0] = p[1]
+
+ def p_number(self, p):
+ """number : digits
+ | PLUS digits
+ | MINUS digits"""
+ p[0] = ''.join(p[1:])
+
+ def p_digits(self, p):
+ """digits : INT_CONST_DEC
+ | INT_CONST_HEX
+ | FLOAT_CONST"""
+ p[0] = p[1]
+
+ def p_error(self, e):
+ if e is None:
+ # Unexpected EOF.
+ # TODO(vtl): Can we figure out what's missing?
+ raise ParseError(self.filename, "Unexpected end of file")
+
+ raise ParseError(self.filename, "Unexpected %r:" % e.value, lineno=e.lineno,
+ snippet=self._GetSnippet(e.lineno))
+
+ def _GetSnippet(self, lineno):
+ return self.source.split('\n')[lineno - 1]
+
+
+def Parse(source, filename):
+ lexer = Lexer(filename)
+ parser = Parser(lexer, source, filename)
+
+ lex.lex(object=lexer)
+ yacc.yacc(module=parser, debug=0, write_tables=0)
+
+ tree = yacc.parse(source)
+ return tree
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/translate.py b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
new file mode 100644
index 00000000000..8407a088c6b
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/translate.py
@@ -0,0 +1,144 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Translates parse tree to Mojom IR."""
+
+
+import ast
+
+
+def _MapTree(func, tree, name):
+ if not tree:
+ return []
+ return [func(subtree) for subtree in tree if subtree[0] == name]
+
+def _MapKind(kind):
+ map_to_kind = { 'bool': 'b',
+ 'int8': 'i8',
+ 'int16': 'i16',
+ 'int32': 'i32',
+ 'int64': 'i64',
+ 'uint8': 'u8',
+ 'uint16': 'u16',
+ 'uint32': 'u32',
+ 'uint64': 'u64',
+ 'float': 'f',
+ 'double': 'd',
+ 'string': 's',
+ 'handle': 'h',
+ 'handle<data_pipe_consumer>': 'h:d:c',
+ 'handle<data_pipe_producer>': 'h:d:p',
+ 'handle<message_pipe>': 'h:m',
+ 'handle<shared_buffer>': 'h:s'}
+ if kind.endswith('[]'):
+ return 'a:' + _MapKind(kind[0:len(kind)-2])
+ if kind.endswith('&'):
+ return 'r:' + _MapKind(kind[0:len(kind)-1])
+ if kind in map_to_kind:
+ return map_to_kind[kind]
+ return 'x:' + kind
+
+def _MapAttributes(attributes):
+ if not attributes:
+ return {}
+ return dict([(attribute[1], attribute[2])
+ for attribute in attributes if attribute[0] == 'ATTRIBUTE'])
+
+def _GetAttribute(attributes, name):
+ out = None
+ if attributes:
+ for attribute in attributes:
+ if attribute[0] == 'ATTRIBUTE' and attribute[1] == name:
+ out = attribute[2]
+ return out
+
+def _MapField(tree):
+ assert type(tree[3]) is ast.Ordinal
+ return {'name': tree[2],
+ 'kind': _MapKind(tree[1]),
+ 'ordinal': tree[3].value,
+ 'default': tree[4]}
+
+def _MapParameter(tree):
+ assert type(tree[3]) is ast.Ordinal
+ return {'name': tree[2],
+ 'kind': _MapKind(tree[1]),
+ 'ordinal': tree[3].value}
+
+def _MapMethod(tree):
+ assert type(tree[3]) is ast.Ordinal
+ method = {'name': tree[1],
+ 'parameters': _MapTree(_MapParameter, tree[2], 'PARAM'),
+ 'ordinal': tree[3].value}
+ if tree[4] != None:
+ method['response_parameters'] = _MapTree(_MapParameter, tree[4], 'PARAM')
+ return method
+
+def _MapEnumField(tree):
+ return {'name': tree[1],
+ 'value': tree[2]}
+
+def _MapStruct(tree):
+ struct = {}
+ struct['name'] = tree[1]
+ struct['attributes'] = _MapAttributes(tree[2])
+ struct['fields'] = _MapTree(_MapField, tree[3], 'FIELD')
+ struct['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM')
+ struct['constants'] = _MapTree(_MapConstant, tree[3], 'CONST')
+ return struct
+
+def _MapInterface(tree):
+ interface = {}
+ interface['name'] = tree[1]
+ interface['client'] = _GetAttribute(tree[2], 'Client')
+ interface['methods'] = _MapTree(_MapMethod, tree[3], 'METHOD')
+ interface['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM')
+ interface['constants'] = _MapTree(_MapConstant, tree[3], 'CONST')
+ return interface
+
+def _MapEnum(tree):
+ enum = {}
+ enum['name'] = tree[1]
+ enum['fields'] = _MapTree(_MapEnumField, tree[2], 'ENUM_FIELD')
+ return enum
+
+def _MapConstant(tree):
+ constant = {}
+ constant['name'] = tree[2]
+ constant['kind'] = _MapKind(tree[1])
+ constant['value'] = tree[3]
+ return constant
+
+def _MapModule(tree, name):
+ mojom = {}
+ mojom['name'] = name
+ mojom['namespace'] = tree[1]
+ mojom['attributes'] = _MapAttributes(tree[2])
+ mojom['structs'] = _MapTree(_MapStruct, tree[3], 'STRUCT')
+ mojom['interfaces'] = _MapTree(_MapInterface, tree[3], 'INTERFACE')
+ mojom['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM')
+ mojom['constants'] = _MapTree(_MapConstant, tree[3], 'CONST')
+ return mojom
+
+def _MapImport(tree):
+ import_item = {}
+ import_item['filename'] = tree[1]
+ return import_item
+
+
+class _MojomBuilder(object):
+ def __init__(self):
+ self.mojom = {}
+
+ def Build(self, tree, name):
+ modules = [_MapModule(item, name) for item in tree if item[0] == 'MODULE']
+ if len(modules) != 1:
+ raise Exception('A mojom file must contain exactly 1 module.')
+ self.mojom = modules[0]
+ self.mojom['imports'] = _MapTree(_MapImport, tree, 'IMPORT')
+ return self.mojom
+
+
+def Translate(tree, name):
+ return _MojomBuilder().Build(tree, name)
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/__init__.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/__init__.py
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/__init__.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/__init__.py
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py
new file mode 100644
index 00000000000..28c936d20b8
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py
@@ -0,0 +1,187 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import imp
+import os.path
+import sys
+import unittest
+
+# Disable lint check for finding modules:
+# pylint: disable=F0401
+
+def _GetDirAbove(dirname):
+ """Returns the directory "above" this file containing |dirname| (which must
+ also be "above" this file)."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ assert tail
+ if tail == dirname:
+ return path
+
+try:
+ imp.find_module("ply")
+except ImportError:
+ sys.path.append(os.path.join(_GetDirAbove("mojo"), "third_party"))
+from ply import lex
+
+try:
+ imp.find_module("mojom")
+except ImportError:
+ sys.path.append(os.path.join(_GetDirAbove("pylib"), "pylib"))
+import mojom.parse.lexer
+
+
+# This (monkey-patching LexToken to make comparison value-based) is evil, but
+# we'll do it anyway. (I'm pretty sure ply's lexer never cares about comparing
+# for object identity.)
+def _LexTokenEq(self, other):
+ return self.type == other.type and self.value == other.value and \
+ self.lineno == other.lineno and self.lexpos == other.lexpos
+setattr(lex.LexToken, '__eq__', _LexTokenEq)
+
+
+def _MakeLexToken(token_type, value, lineno=1, lexpos=0):
+ """Makes a LexToken with the given parameters. (Note that lineno is 1-based,
+ but lexpos is 0-based.)"""
+ rv = lex.LexToken()
+ rv.type, rv.value, rv.lineno, rv.lexpos = token_type, value, lineno, lexpos
+ return rv
+
+
+def _MakeLexTokenForKeyword(keyword, **kwargs):
+ """Makes a LexToken for the given keyword."""
+ return _MakeLexToken(keyword.upper(), keyword.lower(), **kwargs)
+
+
+class LexerTest(unittest.TestCase):
+ """Tests |mojom.parse.lexer.Lexer|."""
+
+ def __init__(self, *args, **kwargs):
+ unittest.TestCase.__init__(self, *args, **kwargs)
+ # Clone all lexer instances from this one, since making a lexer is slow.
+ self._zygote_lexer = lex.lex(mojom.parse.lexer.Lexer("my_file.mojom"))
+
+ def testValidKeywords(self):
+ """Tests valid keywords."""
+ self.assertEquals(self._SingleTokenForInput("handle"),
+ _MakeLexTokenForKeyword("handle"))
+ self.assertEquals(self._SingleTokenForInput("import"),
+ _MakeLexTokenForKeyword("import"))
+ self.assertEquals(self._SingleTokenForInput("module"),
+ _MakeLexTokenForKeyword("module"))
+ self.assertEquals(self._SingleTokenForInput("struct"),
+ _MakeLexTokenForKeyword("struct"))
+ self.assertEquals(self._SingleTokenForInput("interface"),
+ _MakeLexTokenForKeyword("interface"))
+ self.assertEquals(self._SingleTokenForInput("enum"),
+ _MakeLexTokenForKeyword("enum"))
+ self.assertEquals(self._SingleTokenForInput("const"),
+ _MakeLexTokenForKeyword("const"))
+ self.assertEquals(self._SingleTokenForInput("true"),
+ _MakeLexTokenForKeyword("true"))
+ self.assertEquals(self._SingleTokenForInput("false"),
+ _MakeLexTokenForKeyword("false"))
+ self.assertEquals(self._SingleTokenForInput("default"),
+ _MakeLexTokenForKeyword("default"))
+
+ def testValidIdentifiers(self):
+ """Tests identifiers."""
+ self.assertEquals(self._SingleTokenForInput("abcd"),
+ _MakeLexToken("NAME", "abcd"))
+ self.assertEquals(self._SingleTokenForInput("AbC_d012_"),
+ _MakeLexToken("NAME", "AbC_d012_"))
+ self.assertEquals(self._SingleTokenForInput("_0123"),
+ _MakeLexToken("NAME", "_0123"))
+
+ def testInvalidIdentifiers(self):
+ with self.assertRaisesRegexp(
+ mojom.parse.lexer.LexError,
+ r"^my_file\.mojom:1: Error: Illegal character '\$'$"):
+ self._TokensForInput("$abc")
+ with self.assertRaisesRegexp(
+ mojom.parse.lexer.LexError,
+ r"^my_file\.mojom:1: Error: Illegal character '\$'$"):
+ self._TokensForInput("a$bc")
+
+ def testDecimalIntegerConstants(self):
+ self.assertEquals(self._SingleTokenForInput("0"),
+ _MakeLexToken("INT_CONST_DEC", "0"))
+ self.assertEquals(self._SingleTokenForInput("1"),
+ _MakeLexToken("INT_CONST_DEC", "1"))
+ self.assertEquals(self._SingleTokenForInput("123"),
+ _MakeLexToken("INT_CONST_DEC", "123"))
+ self.assertEquals(self._SingleTokenForInput("10"),
+ _MakeLexToken("INT_CONST_DEC", "10"))
+
+ def testValidTokens(self):
+ """Tests valid tokens (which aren't tested elsewhere)."""
+ # Keywords tested in |testValidKeywords|.
+ # NAME tested in |testValidIdentifiers|.
+ self.assertEquals(self._SingleTokenForInput("@123"),
+ _MakeLexToken("ORDINAL", "@123"))
+ self.assertEquals(self._SingleTokenForInput("456"),
+ _MakeLexToken("INT_CONST_DEC", "456"))
+ self.assertEquals(self._SingleTokenForInput("0x01aB2eF3"),
+ _MakeLexToken("INT_CONST_HEX", "0x01aB2eF3"))
+ self.assertEquals(self._SingleTokenForInput("123.456"),
+ _MakeLexToken("FLOAT_CONST", "123.456"))
+ self.assertEquals(self._SingleTokenForInput("'x'"),
+ _MakeLexToken("CHAR_CONST", "'x'"))
+ self.assertEquals(self._SingleTokenForInput("\"hello\""),
+ _MakeLexToken("STRING_LITERAL", "\"hello\""))
+ self.assertEquals(self._SingleTokenForInput("+"),
+ _MakeLexToken("PLUS", "+"))
+ self.assertEquals(self._SingleTokenForInput("-"),
+ _MakeLexToken("MINUS", "-"))
+ self.assertEquals(self._SingleTokenForInput("&"),
+ _MakeLexToken("AMP", "&"))
+ self.assertEquals(self._SingleTokenForInput("="),
+ _MakeLexToken("EQUALS", "="))
+ self.assertEquals(self._SingleTokenForInput("=>"),
+ _MakeLexToken("RESPONSE", "=>"))
+ self.assertEquals(self._SingleTokenForInput("("),
+ _MakeLexToken("LPAREN", "("))
+ self.assertEquals(self._SingleTokenForInput(")"),
+ _MakeLexToken("RPAREN", ")"))
+ self.assertEquals(self._SingleTokenForInput("["),
+ _MakeLexToken("LBRACKET", "["))
+ self.assertEquals(self._SingleTokenForInput("]"),
+ _MakeLexToken("RBRACKET", "]"))
+ self.assertEquals(self._SingleTokenForInput("{"),
+ _MakeLexToken("LBRACE", "{"))
+ self.assertEquals(self._SingleTokenForInput("}"),
+ _MakeLexToken("RBRACE", "}"))
+ self.assertEquals(self._SingleTokenForInput("<"),
+ _MakeLexToken("LANGLE", "<"))
+ self.assertEquals(self._SingleTokenForInput(">"),
+ _MakeLexToken("RANGLE", ">"))
+ self.assertEquals(self._SingleTokenForInput(";"),
+ _MakeLexToken("SEMI", ";"))
+ self.assertEquals(self._SingleTokenForInput(","),
+ _MakeLexToken("COMMA", ","))
+ self.assertEquals(self._SingleTokenForInput("."),
+ _MakeLexToken("DOT", "."))
+
+ def _TokensForInput(self, input_string):
+ """Gets a list of tokens for the given input string."""
+ lexer = self._zygote_lexer.clone()
+ lexer.input(input_string)
+ rv = []
+ while True:
+ tok = lexer.token()
+ if not tok:
+ return rv
+ rv.append(tok)
+
+ def _SingleTokenForInput(self, input_string):
+ """Gets the single token for the given input string. (Raises an exception if
+ the input string does not result in exactly one token.)"""
+ toks = self._TokensForInput(input_string)
+ assert len(toks) == 1
+ return toks[0]
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/parser_unittest.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/parser_unittest.py
new file mode 100644
index 00000000000..024b433410b
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/parser_unittest.py
@@ -0,0 +1,493 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import imp
+import os.path
+import sys
+import unittest
+
+# Disable lint check for finding modules:
+# pylint: disable=F0401
+
+def _GetDirAbove(dirname):
+ """Returns the directory "above" this file containing |dirname| (which must
+ also be "above" this file)."""
+ path = os.path.abspath(__file__)
+ while True:
+ path, tail = os.path.split(path)
+ assert tail
+ if tail == dirname:
+ return path
+
+try:
+ imp.find_module("mojom")
+except ImportError:
+ sys.path.append(os.path.join(_GetDirAbove("pylib"), "pylib"))
+import mojom.parse.ast as ast
+import mojom.parse.lexer as lexer
+import mojom.parse.parser as parser
+
+
+class ParserTest(unittest.TestCase):
+ """Tests |parser.Parse()|."""
+
+ def testTrivialValidSource(self):
+ """Tests a trivial, but valid, .mojom source."""
+ source = """\
+// This is a comment.
+
+module my_module {
+}
+"""
+ self.assertEquals(parser.Parse(source, "my_file.mojom"),
+ [("MODULE", "my_module", None, None)])
+
+ def testSourceWithCrLfs(self):
+ """Tests a .mojom source with CR-LFs instead of LFs."""
+ source = "// This is a comment.\r\n\r\nmodule my_module {\r\n}\r\n"
+ self.assertEquals(parser.Parse(source, "my_file.mojom"),
+ [("MODULE", "my_module", None, None)])
+
+ def testUnexpectedEOF(self):
+ """Tests a "truncated" .mojom source."""
+ source = """\
+// This is a comment.
+
+module my_module {
+"""
+ with self.assertRaisesRegexp(
+ parser.ParseError,
+ r"^my_file\.mojom: Error: Unexpected end of file$"):
+ parser.Parse(source, "my_file.mojom")
+
+ def testCommentLineNumbers(self):
+ """Tests that line numbers are correctly tracked when comments are
+ present."""
+ source1 = """\
+// Isolated C++-style comments.
+
+// Foo.
+asdf1
+"""
+ with self.assertRaisesRegexp(
+ parser.ParseError,
+ r"^my_file\.mojom:4: Error: Unexpected 'asdf1':\nasdf1$"):
+ parser.Parse(source1, "my_file.mojom")
+
+ source2 = """\
+// Consecutive C++-style comments.
+// Foo.
+ // Bar.
+
+struct Yada { // Baz.
+// Quux.
+ int32 x;
+};
+
+asdf2
+"""
+ with self.assertRaisesRegexp(
+ parser.ParseError,
+ r"^my_file\.mojom:10: Error: Unexpected 'asdf2':\nasdf2$"):
+ parser.Parse(source2, "my_file.mojom")
+
+ source3 = """\
+/* Single-line C-style comments. */
+/* Foobar. */
+
+/* Baz. */
+asdf3
+"""
+ with self.assertRaisesRegexp(
+ parser.ParseError,
+ r"^my_file\.mojom:5: Error: Unexpected 'asdf3':\nasdf3$"):
+ parser.Parse(source3, "my_file.mojom")
+
+ source4 = """\
+/* Multi-line C-style comments.
+*/
+/*
+Foo.
+Bar.
+*/
+
+/* Baz
+ Quux. */
+asdf4
+"""
+ with self.assertRaisesRegexp(
+ parser.ParseError,
+ r"^my_file\.mojom:10: Error: Unexpected 'asdf4':\nasdf4$"):
+ parser.Parse(source4, "my_file.mojom")
+
+
+ def testSimpleStruct(self):
+ """Tests a simple .mojom source that just defines a struct."""
+ source = """\
+module my_module {
+
+struct MyStruct {
+ int32 a;
+ double b;
+};
+
+} // module my_module
+"""
+ expected = \
+[('MODULE',
+ 'my_module',
+ None,
+ [('STRUCT',
+ 'MyStruct',
+ None,
+ [('FIELD', 'int32', 'a', ast.Ordinal(None), None),
+ ('FIELD', 'double', 'b', ast.Ordinal(None), None)])])]
+ self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
+
+ def testSimpleStructWithoutModule(self):
+ """Tests a simple struct without an enclosing module."""
+ source = """\
+struct MyStruct {
+ int32 a;
+ double b;
+};
+"""
+ expected = \
+[('MODULE',
+ '',
+ None,
+ [('STRUCT',
+ 'MyStruct',
+ None,
+ [('FIELD', 'int32', 'a', ast.Ordinal(None), None),
+ ('FIELD', 'double', 'b', ast.Ordinal(None), None)])])]
+ self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
+
+ def testMissingModuleName(self):
+ """Tests an (invalid) .mojom with a missing module name."""
+ source1 = """\
+// Missing module name.
+module {
+struct MyStruct {
+ int32 a;
+};
+}
+"""
+ with self.assertRaisesRegexp(
+ parser.ParseError,
+ r"^my_file\.mojom:2: Error: Unexpected '{':\nmodule {$"):
+ parser.Parse(source1, "my_file.mojom")
+
+ # Another similar case, but make sure that line-number tracking/reporting
+ # is correct.
+ source2 = """\
+module
+// This line intentionally left unblank.
+
+{
+}
+"""
+ with self.assertRaisesRegexp(
+ parser.ParseError,
+ r"^my_file\.mojom:4: Error: Unexpected '{':\n{$"):
+ parser.Parse(source2, "my_file.mojom")
+
+ def testEnumInitializers(self):
+ """Tests an enum with simple initialized values."""
+ source = """\
+module my_module {
+
+enum MyEnum {
+ MY_ENUM_NEG1 = -1,
+ MY_ENUM_ZERO = 0,
+ MY_ENUM_1 = +1,
+ MY_ENUM_2,
+};
+
+} // my_module
+"""
+ expected = \
+[('MODULE',
+ 'my_module',
+ None,
+ [('ENUM',
+ 'MyEnum',
+ [('ENUM_FIELD', 'MY_ENUM_NEG1', '-1'),
+ ('ENUM_FIELD', 'MY_ENUM_ZERO', '0'),
+ ('ENUM_FIELD', 'MY_ENUM_1', '+1'),
+ ('ENUM_FIELD', 'MY_ENUM_2', None)])])]
+ self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
+
+ def testConst(self):
+ """Tests some constants and struct memebers initialized with them."""
+ source = """\
+module my_module {
+
+struct MyStruct {
+ const int8 kNumber = -1;
+ int8 number@0 = kNumber;
+};
+
+} // my_module
+"""
+ expected = \
+[('MODULE',
+ 'my_module',
+ None,
+ [('STRUCT',
+ 'MyStruct', None,
+ [('CONST', 'int8', 'kNumber', '-1'),
+ ('FIELD', 'int8', 'number',
+ ast.Ordinal(0), ('IDENTIFIER', 'kNumber'))])])]
+ self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
+
+ def testNoConditionals(self):
+ """Tests that ?: is not allowed."""
+ source = """\
+module my_module {
+
+enum MyEnum {
+ MY_ENUM_1 = 1 ? 2 : 3
+};
+
+} // my_module
+"""
+ with self.assertRaisesRegexp(
+ lexer.LexError,
+ r"^my_file\.mojom:4: Error: Illegal character '\?'$"):
+ parser.Parse(source, "my_file.mojom")
+
+ def testSimpleOrdinals(self):
+ """Tests that (valid) ordinal values are scanned correctly."""
+ source = """\
+module my_module {
+
+// This isn't actually valid .mojom, but the problem (missing ordinals) should
+// be handled at a different level.
+struct MyStruct {
+ int32 a0@0;
+ int32 a1@1;
+ int32 a2@2;
+ int32 a9@9;
+ int32 a10 @10;
+ int32 a11 @11;
+ int32 a29 @29;
+ int32 a1234567890 @1234567890;
+};
+
+} // module my_module
+"""
+ expected = \
+[('MODULE',
+ 'my_module',
+ None,
+ [('STRUCT',
+ 'MyStruct',
+ None,
+ [('FIELD', 'int32', 'a0', ast.Ordinal(0), None),
+ ('FIELD', 'int32', 'a1', ast.Ordinal(1), None),
+ ('FIELD', 'int32', 'a2', ast.Ordinal(2), None),
+ ('FIELD', 'int32', 'a9', ast.Ordinal(9), None),
+ ('FIELD', 'int32', 'a10', ast.Ordinal(10), None),
+ ('FIELD', 'int32', 'a11', ast.Ordinal(11), None),
+ ('FIELD', 'int32', 'a29', ast.Ordinal(29), None),
+ ('FIELD', 'int32', 'a1234567890', ast.Ordinal(1234567890), None)])])]
+ self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
+
+ def testInvalidOrdinals(self):
+ """Tests that (lexically) invalid ordinals are correctly detected."""
+ source1 = """\
+module my_module {
+
+struct MyStruct {
+ int32 a_missing@;
+};
+
+} // module my_module
+"""
+ with self.assertRaisesRegexp(
+ lexer.LexError,
+ r"^my_file\.mojom:4: Error: Missing ordinal value$"):
+ parser.Parse(source1, "my_file.mojom")
+
+ source2 = """\
+module my_module {
+
+struct MyStruct {
+ int32 a_octal@01;
+};
+
+} // module my_module
+"""
+ with self.assertRaisesRegexp(
+ lexer.LexError,
+ r"^my_file\.mojom:4: Error: "
+ r"Octal and hexadecimal ordinal values not allowed$"):
+ parser.Parse(source2, "my_file.mojom")
+
+ source3 = """\
+module my_module { struct MyStruct { int32 a_invalid_octal@08; }; }
+"""
+ with self.assertRaisesRegexp(
+ lexer.LexError,
+ r"^my_file\.mojom:1: Error: "
+ r"Octal and hexadecimal ordinal values not allowed$"):
+ parser.Parse(source3, "my_file.mojom")
+
+ source4 = """\
+module my_module { struct MyStruct { int32 a_hex@0x1aB9; }; }
+"""
+ with self.assertRaisesRegexp(
+ lexer.LexError,
+ r"^my_file\.mojom:1: Error: "
+ r"Octal and hexadecimal ordinal values not allowed$"):
+ parser.Parse(source4, "my_file.mojom")
+
+ source5 = """\
+module my_module { struct MyStruct { int32 a_hex@0X0; }; }
+"""
+ with self.assertRaisesRegexp(
+ lexer.LexError,
+ r"^my_file\.mojom:1: Error: "
+ r"Octal and hexadecimal ordinal values not allowed$"):
+ parser.Parse(source5, "my_file.mojom")
+
+ source6 = """\
+struct MyStruct {
+ int32 a_too_big@999999999999;
+};
+"""
+ with self.assertRaisesRegexp(
+ parser.ParseError,
+ r"^my_file\.mojom:2: Error: "
+ r"Ordinal value 999999999999 too large:\n"
+ r" int32 a_too_big@999999999999;$"):
+ parser.Parse(source6, "my_file.mojom")
+
+ def testNestedNamespace(self):
+ """Tests that "nested" namespaces work."""
+ source = """\
+module my.mod {
+
+struct MyStruct {
+ int32 a;
+};
+
+} // module my.mod
+"""
+ expected = \
+[('MODULE',
+ 'my.mod',
+ None,
+ [('STRUCT',
+ 'MyStruct',
+ None,
+ [('FIELD', 'int32', 'a', ast.Ordinal(None), None)])])]
+ self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
+
+ def testValidHandleTypes(self):
+ """Tests (valid) handle types."""
+ source = """\
+struct MyStruct {
+ handle a;
+ handle<data_pipe_consumer> b;
+ handle <data_pipe_producer> c;
+ handle < message_pipe > d;
+ handle
+ < shared_buffer
+ > e;
+};
+"""
+ expected = \
+[('MODULE',
+ '',
+ None,
+ [('STRUCT',
+ 'MyStruct',
+ None,
+ [('FIELD', 'handle', 'a', ast.Ordinal(None), None),
+ ('FIELD', 'handle<data_pipe_consumer>', 'b', ast.Ordinal(None), None),
+ ('FIELD', 'handle<data_pipe_producer>', 'c', ast.Ordinal(None), None),
+ ('FIELD', 'handle<message_pipe>', 'd', ast.Ordinal(None), None),
+ ('FIELD', 'handle<shared_buffer>', 'e', ast.Ordinal(None), None)])])]
+ self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
+
+ def testInvalidHandleType(self):
+ """Tests an invalid (unknown) handle type."""
+ source = """\
+struct MyStruct {
+ handle<wtf_is_this> foo;
+};
+"""
+ with self.assertRaisesRegexp(
+ parser.ParseError,
+ r"^my_file\.mojom:2: Error: "
+ r"Invalid handle type 'wtf_is_this':\n"
+ r" handle<wtf_is_this> foo;$"):
+ parser.Parse(source, "my_file.mojom")
+
+ def testValidDefaultValues(self):
+ """Tests default values that are valid (to the parser)."""
+ source = """\
+struct MyStruct {
+ int16 a0 = 0;
+ uint16 a1 = 0x0;
+ uint16 a2 = 0x00;
+ uint16 a3 = 0x01;
+ uint16 a4 = 0xcd;
+ int32 a5 = 12345;
+ int64 a6 = -12345;
+ int64 a7 = +12345;
+ uint32 a8 = 0x12cd3;
+ uint32 a9 = -0x12cD3;
+ uint32 a10 = +0x12CD3;
+ bool a11 = true;
+ bool a12 = false;
+ float a13 = 1.2345;
+ float a14 = -1.2345;
+ float a15 = +1.2345;
+ float a16 = 123.;
+ float a17 = .123;
+ double a18 = 1.23E10;
+ double a19 = 1.E-10;
+ double a20 = .5E+10;
+ double a21 = -1.23E10;
+ double a22 = +.123E10;
+};
+"""
+ expected = \
+[('MODULE',
+ '',
+ None,
+ [('STRUCT',
+ 'MyStruct',
+ None,
+ [('FIELD', 'int16', 'a0', ast.Ordinal(None), '0'),
+ ('FIELD', 'uint16', 'a1', ast.Ordinal(None), '0x0'),
+ ('FIELD', 'uint16', 'a2', ast.Ordinal(None), '0x00'),
+ ('FIELD', 'uint16', 'a3', ast.Ordinal(None), '0x01'),
+ ('FIELD', 'uint16', 'a4', ast.Ordinal(None), '0xcd'),
+ ('FIELD', 'int32', 'a5' , ast.Ordinal(None), '12345'),
+ ('FIELD', 'int64', 'a6', ast.Ordinal(None), '-12345'),
+ ('FIELD', 'int64', 'a7', ast.Ordinal(None), '+12345'),
+ ('FIELD', 'uint32', 'a8', ast.Ordinal(None), '0x12cd3'),
+ ('FIELD', 'uint32', 'a9', ast.Ordinal(None), '-0x12cD3'),
+ ('FIELD', 'uint32', 'a10', ast.Ordinal(None), '+0x12CD3'),
+ ('FIELD', 'bool', 'a11', ast.Ordinal(None), 'true'),
+ ('FIELD', 'bool', 'a12', ast.Ordinal(None), 'false'),
+ ('FIELD', 'float', 'a13', ast.Ordinal(None), '1.2345'),
+ ('FIELD', 'float', 'a14', ast.Ordinal(None), '-1.2345'),
+ ('FIELD', 'float', 'a15', ast.Ordinal(None), '+1.2345'),
+ ('FIELD', 'float', 'a16', ast.Ordinal(None), '123.'),
+ ('FIELD', 'float', 'a17', ast.Ordinal(None), '.123'),
+ ('FIELD', 'double', 'a18', ast.Ordinal(None), '1.23E10'),
+ ('FIELD', 'double', 'a19', ast.Ordinal(None), '1.E-10'),
+ ('FIELD', 'double', 'a20', ast.Ordinal(None), '.5E+10'),
+ ('FIELD', 'double', 'a21', ast.Ordinal(None), '-1.23E10'),
+ ('FIELD', 'double', 'a22', ast.Ordinal(None), '+.123E10')])])]
+ self.assertEquals(parser.Parse(source, "my_file.mojom"), expected)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/run_parser.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/run_parser.py
new file mode 100755
index 00000000000..edca7e11ff1
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/run_parser.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Simple testing utility to just run the mojom parser."""
+
+
+import os.path
+import sys
+
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ os.path.pardir, os.path.pardir))
+
+# Disable lint check for finding modules:
+# pylint: disable=F0401
+
+from mojom.parse.parser import Parse, ParseError
+
+
+def main(argv):
+ if len(argv) < 2:
+ print "usage: %s filename" % argv[0]
+ return 0
+
+ for filename in argv[1:]:
+ with open(filename) as f:
+ print "%s:" % filename
+ try:
+ print Parse(f.read(), filename)
+ except ParseError, e:
+ print e
+ return 1
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/run_translate.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/run_translate.py
new file mode 100755
index 00000000000..833af6292a7
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/run_translate.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Simple testing utility to just run the mojom translate stage."""
+
+
+import os.path
+import sys
+
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ os.path.pardir, os.path.pardir))
+
+# Disable lint check for finding modules:
+# pylint: disable=F0401
+
+from mojom.parse.parser import Parse
+from mojom.parse.translate import Translate
+
+
+def main(argv):
+ if len(argv) < 2:
+ print "usage: %s filename" % sys.argv[0]
+ return 1
+
+ for filename in argv[1:]:
+ with open(filename) as f:
+ print "%s:" % filename
+ print Translate(Parse(f.read(), filename),
+ os.path.splitext(os.path.basename(filename))[0])
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/__init__.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/__init__.py
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/find_files.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/find_files.py
new file mode 100644
index 00000000000..00524a2413a
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/find_files.py
@@ -0,0 +1,32 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from fnmatch import filter
+from os import walk
+from os.path import join
+import sys
+
+
+def FindFiles(top, pattern, **kwargs):
+ """Finds files under |top| matching the glob pattern |pattern|, returning a
+ list of paths."""
+ matches = []
+ for dirpath, _, filenames in walk(top, **kwargs):
+ for filename in filter(filenames, pattern):
+ matches.append(join(dirpath, filename))
+ return matches
+
+
+def main(argv):
+ if len(argv) != 3:
+ print "usage: %s path pattern" % argv[0]
+ return 1
+
+ for filename in FindFiles(argv[1], argv[2]):
+ print filename
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/run_bindings_generator.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/run_bindings_generator.py
new file mode 100644
index 00000000000..20ef4619699
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/support/run_bindings_generator.py
@@ -0,0 +1,47 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os.path
+from subprocess import check_call
+import sys
+
+
+def RunBindingsGenerator(out_dir, root_dir, mojom_file, extra_flags=None):
+ out_dir = os.path.abspath(out_dir)
+ root_dir = os.path.abspath(root_dir)
+ mojom_file = os.path.abspath(mojom_file)
+
+ # The mojom file should be under the root directory somewhere.
+ assert mojom_file.startswith(root_dir)
+ mojom_reldir = os.path.dirname(os.path.relpath(mojom_file, root_dir))
+
+ # TODO(vtl): Abstract out the "main" functions, so that we can just import
+ # the bindings generator (which would be more portable and easier to use in
+ # tests).
+ this_dir = os.path.dirname(os.path.abspath(__file__))
+ # We're in src/mojo/public/tools/bindings/pylib/mojom_tests/support;
+ # mojom_bindings_generator.py is in .../bindings.
+ bindings_generator = os.path.join(this_dir, os.pardir, os.pardir, os.pardir,
+ "mojom_bindings_generator.py")
+
+ args = ["python", bindings_generator,
+ "-o", os.path.join(out_dir, mojom_reldir)]
+ if extra_flags:
+ args.extend(extra_flags)
+ args.append(mojom_file)
+
+ check_call(args)
+
+
+def main(argv):
+ if len(argv) < 4:
+ print "usage: %s out_dir root_dir mojom_file [extra_flags]" % argv[0]
+ return 1
+
+ RunBindingsGenerator(argv[1], argv[2], argv[3], extra_flags=argv[4:])
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))